[13] RFR: 8202414: Unsafe write after primitive array creation may result in array length change
Vladimir Ivanov
vladimir.x.ivanov at oracle.com
Sat Apr 27 02:30:57 UTC 2019
>> I'd just add "if (st->is_mismatched_access()) { return FAIL; }" in
>> IN::can_capture_store and move the rest into
>> IN::captured_store_insertion_point().
>>
> Yes, I will add following change also along with any final fix.
>
> intptr_t InitializeNode::can_capture_store(StoreNode* st,
> PhaseTransform* phase, bool can_reshape) {
> const int FAIL = 0;
> - if (st->is_unaligned_access()) {
> + if (st->is_unaligned_access() || st->is_mismatched_access()) {
> return FAIL;
> }
Looks good.
>> It looks like InitializeNode::captured_store_insertion_point() is a
>> better place to inspect get_store_offset() and fail on mismatch. It
>> also handles negative values returned by get_store_offset() and has a
>> consistent handling of "size_in_bytes == 0" case.
>>
> (i) At first tried following *wrong* change.
> (confirmed this is not a fix for the issue)
>
> int InitializeNode::captured_store_insertion_point(intptr_t start,
> int size_in_bytes,
> PhaseTransform*
> phase) {
> ...........
> for (uint i = InitializeNode::RawStores, limit = req(); ; ) {
> if (i >= limit) return -(int)i; // not found; here is where to
> put it
>
> Node* st = in(i);
> intptr_t st_off = get_store_offset(st, phase);
> - if (st_off < 0) {
> + if ((size_in_bytes != 0) && (st_off % size_in_bytes) != 0) {
> + return FAIL;
> + } else if (st_off < 0) {
> if (st != zero_memory()) {
> ............
>
>
>
> (ii) When working for correct fix in captured_store_insertion_point(),
> (was looking to get required captured store / get_store_offset value in)
> found that following additions in captured_store_insertion_point()
> actually fixes reported issue; also could not find any other issue with
> testing.
>
> ............
> if (start >= ti_limit) return FAIL;
>
> + if ((size_in_bytes != 0) && (start % size_in_bytes) != 0) {
> + return FAIL;
> + }
> +
> for (uint i = InitializeNode::RawStores, limit = req(); ; ) {
> ...........
>
>
>
> (iii) So if above (ii) is a legal/valid fix, then again can the best
> location of the fix be as following in can_capture_store() itself?
>
> intptr_t InitializeNode::can_capture_store(StoreNode* st,
> PhaseTransform* phase, bool can_reshape) {
> ...................
> AllocateNode* alloc = AllocateNode::Ideal_allocation(adr, phase,
> offset);
> if (alloc == NULL)
> return FAIL; // inscrutable address
> if (alloc != allocation())
> return FAIL; // wrong allocation! (store needs to
> float up)
> + int size_in_bytes = st->memory_size();
> + if ((size_in_bytes != 0) && (offset % size_in_bytes) != 0) {
> + return FAIL;
> + }
> Node* val = st->in(MemNode::ValueIn);
> ...........
> return offset; // success
> }
>
>
>
> (iv) OR something like following in capture_store() ?
> Node* InitializeNode::capture_store(StoreNode* st, intptr_t start,
> PhaseTransform* phase, bool
> can_reshape) {
> assert(stores_are_sane(phase), "");
>
> if (start < 0) return NULL;
> assert(can_capture_store(st, phase, can_reshape) == start, "sanity");
>
> + int size_in_bytes = st->memory_size();
> + if ((size_in_bytes != 0) && (start % size_in_bytes) != 0) {
> + return NULL;
> + }
> Compile* C = phase->C;
> - int size_in_bytes = st->memory_size();
> int i = captured_store_insertion_point(start, size_in_bytes, phase);
> if (i == 0) return NULL; // bail out
> ..................
>
>
>
> (v) Please tell me if I am missing something and none above is valid
> fix. Then should work for a correct fix in
> captured_store_insertion_point().
You are right, I missed that IN::captured_store_insertion_point()
inspects already other stores which are already captured. Sorry for the
confusion.
I agree that IN::can_capture_store() is the right place to put the fix
in and I like (iii). (Just add a comment, "// mismatched access" is enough)
Best regards,
Vladimir Ivanov
>>
>> PS: Frankly speaking, I'm not comfortable with current handling of
>> "size_in_bytes == 0" case:
>>
>> // If size_in_bytes is zero, do not bother with overlap checks.
>> int InitializeNode::captured_store_insertion_point(intptr_t start,
>> int size_in_bytes,
>> PhaseTransform*
>> phase) {
>>
>> "size_in_bytes == 0" is the case for StoreVectorNodes. I believe the
>> logic is there to accommodate bulk initialization with vector stores
>> (haven't found the proofs in the code though), but it looks fragile
>> (especially when vector operations become more common). It would be
>> nice to enable overlap checks for vector operations.
>>
>> But I'm perfectly fine with handling that separately.
>>
> Yes, I will open a new JBS task to address this.
>
>
> Thanks,
> Rahul
>
>> Best regards,
>> Vladimir Ivanov
More information about the hotspot-compiler-dev
mailing list