[13] RFR: 8202414: Unsafe write after primitive array creation may result in array length change
Rahul Raghavan
rahul.v.raghavan at oracle.com
Fri Apr 26 09:20:49 UTC 2019
Thank you Vladimir Ivanov for suggestions.
Request help to review the notes inline below to finalize the fix.
On 25/04/19 12:36 AM, Vladimir Ivanov wrote:
>
> A couple of suggestions:
>
> src/hotspot/share/opto/memnode.cpp:
>
> + int size_in_bytes = st->memory_size();
> + if ((size_in_bytes != 0) && (get_store_offset(st, phase) %
> size_in_bytes) != 0) {
> + return FAIL;
> + }
>
> 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;
}
> 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().
>
> 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