Hi David,

On 01/24/20 12:17 pm, David Holmes wrote:
>>
>> That said, memory segments are not the only clients of
>> Unsafe::allocateMemory - so if we decided that overflow is an issue
>> that should be handled in clients, fine, but at least it should be
>> evident somewhere in the javadoc of Unsafe::allocateMemory?
>
> I'm glad you raised that as it prompted me to examine Unsafe in more
> detail. :)
>
> The onus is put on the caller to ensure arguments are valid. Unsafe
> class docs state, and a number of methods like allocateMemory repeat:
>
>      * <em>Note:</em> It is the resposibility of the caller to make
>      * sure arguments are checked before the methods are called. While
>      * some rudimentary checks are performed on the input, the checks
>      * are best effort and when performance is an overriding priority,
>      * as when methods of this class are optimized by the runtime
>      * compiler, some or all checks (if any) may be elided. Hence, the
>      * caller must not rely on the checks and corresponding
>      * exceptions!
>
> So although allocateMemory explicitly checks for size_t related overflow:
>
>      * @throws RuntimeException if the size is negative or too large
>      *         for the native size_t type
>
> the caller should not be relying on that.
>
> The existing overflow check is done by checkSize(long size) which has:
>
>  if (ADDRESS_SIZE == 4) {
>     // Note: this will also check for negative sizes
>     if (!is32BitClean(size)) {
>         throw invalidInput();
>     }
>  }
>
> where is32BitClean is defined as:
>
> value >>> 32 == 0;
>
> and so is incomplete as this doesn't take into account the possible
> align up of "size" that the JVM allocation routine actually
> performs. But even if we fix this, the caller is not supposed to rely on
> it.
>
> In terms of fixing it ... it isn't clear to me whether this case should
> be detected in the VM as Nick's patch does, or whether it should be
> caught before hand in the checkSize Java code (though we don't really
> know what the alignment requirement may be in the Java code). A
> difference is that if we catch it in checkSize then we will throw
> IllegalArgumentException, whereas Nick's approach results in
> OutOfMemoryError. I think the IllegalArgumentException is actually
> preferable here.
>

How about we align the size up to ADDRESS_SIZE (== HeapWordSize) in
Unsafe.allocateMemory() before the call to allocateMemoryChecks(). Like:

  bytes = ((bytes + ADDRESS_SIZE - 1) & ~(ADDRESS_SIZE - 1));

Then it will throw an IllegalArgumentException if the result is outside
the size_t range. And in the native code we can just assert that the
`size' argument is already aligned:

  assert(is_aligned(sz, HeapWordSize), "sz not aligned");


Thanks,
Nick

Reply via email to