RFR: 8281213: Unsafe uses of long and size_t in MemReporterBase::diff_in_current_scale [v2]

Evgeny Astigeevich eastigeevich at openjdk.org
Thu Dec 15 11:33:06 UTC 2022


On Thu, 15 Dec 2022 11:00:52 GMT, Afshin Zafari <duke at openjdk.org> wrote:

> The predicates : `amount + _scale/2 <= SIZE_MAX` and its equivalent `amount <= SIZE_MAX - _scale/2` are always true.

You are not correct. `amount + _scale/2 <= SIZE_MAX` is always true but `amount <= SIZE_MAX - _scale/2` is not.
Example:
Let's SIZE_MAX to be 255 and _scale to be 10. SIZE_MAX, _scale and amount are `unsigned char`.
When `amount` is 252, the expression `amount + _scale/2 <= SIZE_MAX` is evaluated as:
- `a = amount + _scale/2`
- `a <= SIZE_MAX`
So we have:
- `a = 252 + 10/2 == 257 % 256 => 1`
- `1 <= 255 => true`

Now evaluate `amount <= SIZE_MAX - _scale/2`:
- `a = SIZE_MAX - _scale/2` => `a = 255 - 5` => 250
- `amount <= a` => `252 <= 250` => false

You can see that `amount <= SIZE_MAX - _scale/2` detects overflow.

> I used `(a + b) > a` where `b != 0` for finding if an overflow happened or not.

This works for unsigned types in C++ but the result is undefined for signed types. In your code:


    int64_t amount = s1 - s2;
    int64_t scale = (int64_t)_scale;


So according to the C++ standard, the result of `(amount + scale / 2) > amount` is undefined.

-------------

PR: https://git.openjdk.org/jdk/pull/11514


More information about the hotspot-runtime-dev mailing list