Nest host validation vs NestHost attribute performed by Lookup::defineHiddenClass
mandy.chung at oracle.com
Tue Oct 1 04:08:32 UTC 2019
On 9/30/19 8:01 PM, John Rose wrote:
> On Sep 27, 2019, at 3:46 PM, Mandy Chung <mandy.chung at oracle.com> wrote:
>> I have a follow-up question w.r.t. JVMS 5.4.4 access control check (see #4 below). Below #1-3 is a summary with what we agree (please correct if anything is incorrect).
>> 1. Hidden classes do not have names and they cannot participate in NH/NM attributes. These attributes in a hidden class are ignored and pretending not present.
>> 2. LC::defineHiddenClass defines HNC as a nestmate of LC
>> LC must be a nest host and full-power lookup which are required to authorize to add NHC as a member to the nest of LC.
> This is wrong, I think. The asymmetry between nest host and nest members is an artifact
> of the static structure of the class file attributes (NH/NMs) and not semantically significant
> to access control (after validation).
I refer "nest host" above as the runtime nest host after the validation,
i.e. same as 2' you mentioned below. (LC.getNestHost returns). I should
have been made it clearer.
Perhaps the word "authorize" should be avoided which may easily
interpret as static nest membership??
> There are no rules which distinguish the NH of a nest
> as having special powers or responsibilities. This would be the first such rule; I’m against
> it for that reason.
> I also think it makes the present questions unnecessarily difficult. I.e., they get easier
> if we treat all members of a nest equally, so they all have equal ability to be the LC.
> I think any access-checking logic that is nest-sensitive *must* validate static nest attributes.
> There’s no benefit to trying to avoid such validation. It just creates a tangle of new corner cases.
> 2’. C::defineHiddenClass defines HNC as a nestmate of LC
> LC’s static nest information is validated (if not previously validated) and
> a valid LC.getNestHost becomes available.
> If validation fails, or if LC happens to be its own static NH, then HNC.getNestHost
> == LC.getNestHost == LC.
> If instead LC is part of a valid multi-nest, then HNC.getNestHost == LC.getNestHost
> == H, where H is the nest-host of that multi-nest.
We are talking the same scheme.
>> (A nest member can do LC.in(LC.lookupClass().getNestHost()) to teleport to its nest host and call defineHiddenClass.)
> That would be a workaround, but it is clearly wasted work, if the LC can be the class you
> want in the first place.
> Also, the extra ceremony gets problematic in precisely the edge cases we are discussing.
> If the nest of LC is broken (fails to validate), so that NH doesn’t hook up properly to the
> neighboring classes, then forcing it to be the LC means that the workaround doesn’t work
> any more; the teleport will fail.
> It’s better to say that the LC can be, equally, any nest member, and whatever the LC
> reports (dynamically) as getNestHost is the NH assigned to the new hidden class.
>> 2a) validate LC's static NH attribute and error is ignored; LC's runtime nest host is determined.
> +1 (if LC is a nest host it will *not* have an NH attribute, but rather NMs)
> If there is an error, then getNestHost(LC) == LC. It’s dynamically a “mono-nest” even
> if the static classfile attributes seem to be trying for something else.
>> 2b) dynamic nestmates are not available for return in Class::getNM
>> HNC::getNestHost == LC
> No! HNC.getNestHost == LC.getNestHost, which might be != LC
> As noted above, this scheme is much more useful in the presence validation failures.
Yes of course. My bad (I described only the case where LC has a bad NH
>> HNC::getNestMembers == LC::getNestMembers
> +1 (note that LC’s list of static nest-mates is well-defined even if LC is not its own HC)
>> 3. LC::defineHiddenClass defines HC (not added to LC's nest)
>> 3a) no validation of LC's static nest information (as not adding to other nest)
>> 3b) HC belongs to a nest of itself; NH/NM attributes are ignored
>> HC::getNestHost == HC
>> HC.getNestMembers returns 1-element array of HC
>> HC can add dynamic nestmates to its own nest.
>> 4. nestmate access check specified in JVMS 5.4.4
>>> 3a. After validation of the asymmetric NH/NM attributes (or after a “bad” NH is thrown away), access control effects of
>>> nesting structure are applied uniformly across the nest.
>>> 3b. The NestHost has no dynamic distinction from the other nest members, other than a “ceremonial” role in reflection.
>> In JVMS 5.4.4, "The nest host of C and the nest host of D are validated at access check. If any exception is thrown, the nestmate test fails for the same reason."
>> The runtime nest host of LC determined in (3a) above will be considered here.
>> LC calls HNC::m after HNC is defined (or HNC calls LC::privM). This access check succeeds as LC and HNC are in the same nest.
> (And the dynamic nest host might be either LC or a different class.)
>> However, if LC is accessed by other class D (not a dynamic nestmate) but the nest host has been validated, as the bad NH is thrown away, then IAE should be thrown in this case.
>> If no validation of nest host of C has been performed, then access check is the first time attempting the validation, then NCDFE or ICCE is thrown instead. (Note than C and D can be any class).
>> The access control effects are applied uniformly access the nest while in the error case, the exception may be different depends on the timing when validation of C's and D's nest host are triggered. This seems to bring non-uniformity but may be fine as with error cases?
> Yes, such non-uniformity across time is part of the price of lazy evaluation. We try
> to memoize linkage errors for replay when possible, but that technique is limited to
> certain spots where it makes sense, such as resolution of particular CP entries.
More information about the valhalla-dev