JDK-8216426 : Usage of array placement new may lead to memory corruption
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 11,12,13
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2019-01-09
  • Updated: 2019-11-04
  • Resolved: 2019-01-16
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 13
11.0.6-oracleFixed 13 b04Fixed
Description
Hotspot code contains a usage of an array placement new in ConcurrentHashTable: "new (memory) Bucket[_size]" where "memory" is allocated by malloc with size "_size * sizeof(Bucket)".

This seems to be fine with nicely behaving compilers (hopefully all we use?).
However, the C++ standard (Section 5.3.4/12) allows the array placement new to use more space than "_size * sizeof(Bucket)". In this case, we may write beyond the allocated memory.

Comments
Fix Request I'm requesting a fix of this in jdk11u, to enhance runtime stability. The patch imports as is with no changes, and the changes are considered low risk as they are running in later JDKs.
25-10-2019

So far as I can tell, there is no portable and correct way to use that form of array placement new expression. One must make use of one of various alternatives. A array new-expression is permitted to add some unspecified amount to the "obvious" object size when requesting the allocation. (5.3.4/10, 5.3.4/12) An allocator is required to return a block of memory of at least the requested size. (5.3.4/14) A array new-expression is permitted to return a pointer that is offset from the pointer returned by the underlying allocator call. (5.3.4/14) This is all so the array new-expression can record the size of the array for use by an eventual array delete-expression. A array placement new-expression of the form being used will call the library's global operator new[](size_t, void*). The overhead may be applied even in this case (5.3.4/12). That function just returns the passed in pointer. If that's not big enough to account for any unspecified extra space requested by the new expression, bad things can (and likely will) happen. There are no placement delete-expressions; objects allocated via a placement new-expression must, for most cases, be deallocated via some other method than calling a delete-expression. (The exceptions are those which invoke the library's nothrow allocator variants.) It might be that some implementations are aware of this issue and their array new-expressions that don't have corresponding array delete-expressions don't add anything to the sizeof(type-to-allocate) and don't record the array size. Martin found this (10 year old) discussion: [1] https://stackoverflow.com/questions/15254/can-placement-new-for-arrays-be-used-in-a-portable-way Reading through it suggests that back then MSVC didn't elide the size recording as suggested above, with resulting memory corruption. The fact that we haven't seen any problems from ConcurrentHashTable suggests that might changed in the intervening years. I looked at the corresponding parts of C++14 and C++17 (the above standard references are for C++03) and didn't find any relevant differences.
11-01-2019

How does it suggest one size the allocated memory correctly ??
09-01-2019