Attribute safety
Brian Goetz
brian.goetz at oracle.com
Wed Aug 23 17:26:50 UTC 2023
Just a further thought on this: we can further focus our lens on _bound_
attributes, because these are the ones that have come from another
classfile. If the user creates a RVAA during a transform, we should
assume that is fine, just as we do with writing.
On 8/7/2023 6:46 AM, Adam Sotona wrote:
>
> That makes perfect sense, attribute safety is more exactly an
> attribute transformation safety.
>
> I agree that introduction of special read/write filters (in a form of
> context options) is confusing and non-systematic.
>
> When we focus on the implementation of the attributes transformation
> safety, I think the safety switch is less of a global context option
> but rather individual transformation immediate feature (a filtering
> feature).
>
> If we implement it as a global context option, we would have to insert
> a filtering layer before each transformation (on read side) or after
> (on write side) of each transformation. I think it would be pretty
> much the same as filtering on read/write, except for the fact it will
> affect transformations only (so maybe even more confusing).
> Classfile::transform would then behave differently than its expanded
> form using Classfile::build.
>
> However if we implement attribute transformation safety as specific
> transformations (doing the filtering job) – it should work in harmony
> with the rest of the API.
>
> For example in addition to ClassTransform.ACCEPT_ALL we can add
> ClassTransform.ACCEPT_ALL_KNOWN_ATTRIBUTES (dropping UNKNOWN) and
> ClassTransform.ACCEPT_ALL_SAFE_ATTRIBUTES (dropping HAZMAT).
>
> As an interesting expansion of the ClassfileTransform features we can
> provide factories like for example
> ClassfileTransform::dropingAll(Predicate<ClassfileElement> filter) –
> where the “All” (or “Deep” or similar suffix) should indicate forced
> expansion of the whole tree, so the filter is really applied on all
> levels and filtered element never appears in the target class. It can
> be used to implement the global filtering transformations.
>
> I propose to add following set of filtering transformations:
>
> * ClassTransform.ACCEPT_ALL_KNOWN_ATTRIBUTES
> * ClassTransform.ACCEPT_ALL_SAFE_ATTRIBUTES
> * FieldTransform.ACCEPT_ALL_KNOWN_ATTRIBUTES
> * FieldTransform.ACCEPT_ALL_SAFE_ATTRIBUTES
> * MethodTransform.ACCEPT_ALL_KNOWN_ATTRIBUTES
> * MethodTransform.ACCEPT_ALL_SAFE_ATTRIBUTES
> * CodeTransform.ACCEPT_ALL_KNOWN_ATTRIBUTES
> * CodeTransform.ACCEPT_ALL_SAFE_ATTRIBUTES
>
> Thanks,
>
> Adam
>
> *From: *Brian Goetz <brian.goetz at oracle.com>
> *Date: *Saturday, 5 August 2023 3:01
> *To: *Adam Sotona <adam.sotona at oracle.com>,
> classfile-api-dev at openjdk.org <classfile-api-dev at openjdk.org>
> *Subject: *Re: Attribute safety
>
> OK, I thought about this some more while sitting in the sauna ...
>
> I think the locus of attribute safety is not reading or writing, but
> transforming. If I am just going to read a classfile, there is no
> need to drop anything, if I find an attribute I don't recognize, I'll
> just skip over it and keep going -- that's how attributes are designed
> to work. No need to drop anything on read, ever. WHen the library
> finds an unknown attribute, it wraps it with an UnknownAttribute
> element, whose understanding to the attribute is limited to name,
> size, and byte[] of the payload. Nothing so dangerous here that the
> user needs protection.
>
> Similarly, if a user is _writing_ a classfile, again, we should trust
> them that the classfile they are putting together is sensible. We
> shouldn't second guess at "oh, that's a type annotations attribute,
> those are so brittle, please sign here."
>
> Where there is potentially a problem is when we are _transforming_ a
> classfile, because for a HAZMAT or UNKNOWN attribute, we can't
> guarantee its integrity if we've changed anything else about the
> classfile (including reordering the constant pool.) So the "what do
> we do with brittle attributes" question applies only to
> transformation, where we are taking an attribute from one classfile (a
> bound attribute) and writing it to another. This is where the user
> can shoot themselves in the foot, because they might change something
> else about the classfile and subtly (or not subtly) undermine the
> integrity of the annotation they don't understand. And this is why we
> want to classify attributes according to their sensitivity to
> environmental change:
>
> - A stateless attribute is sensitive to no environmental changes. A
> transform can always safely bulk-copy the attribute directly.
>
> - An attribute with CP dependencies is sensitive to restructuring of
> the constant pool (no CP sharing), but the mapper contains enough
> information to survive CP restructuring. A transform can safely
> bulk-copy the attribute directly if the CP is shared between the
> original and new classfile, and can otherwise safely copy the
> attribute by inflating it and deflating it via the
> readAttribute/writeAttribute behavior of the mapper.
>
> - An attribute with label dependencies is sensitive to changes to the
> contents or structure of the bytecode array. A transform can safely
> bulk-copy the attribute directly if code array is unchanged, and can
> otherwise safely copy the attribute by inflating it and deflating it
> via the readAttribute/writeAttribute behavior of the mapper. However,
> there are currently no attributes that have label dependencies only
> but are not already treated specially by the classfile API, so this
> category may not be that interesting.
>
> - An attribute with unpredictable dependencies is sensitive to any
> change to the contents of the entity of which it is an attribute. It
> can be safely bulk-copied if nothing else in that entity has changed,
> but otherwise there is no safe way to copy it.
>
> - An unknown attribute is sensitive to all of the above, and so takes
> on the union of the copying risks of all of the above.
>
> So I think the Option we want governs what to do with various
> attributes when _transforming_ a CompoundElement in which they
> appear. And the problematic cases are those with unpredictable
> dependencies, and unknowns. So I think the options we want are:
>
> - When transforming, always keep HAZMAT and UNKNOWN attributes; for
> safety, lift and lower HAZMAT attributes.
> - When transforming, keep HAZMAT attributes (lifting and lowering),
> but always drop UNKNOWN attributes.
> - When transforming, always drop HAZMAT and UNKNOWN attributes.
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/classfile-api-dev/attachments/20230823/f89c4716/attachment-0001.htm>
More information about the classfile-api-dev
mailing list