RFR: 8281213: Unsafe uses of long and size_t in MemReporterBase::diff_in_current_scale
Afshin Zafari
duke at openjdk.org
Wed Dec 7 14:19:06 UTC 2022
On Wed, 7 Dec 2022 14:04:36 GMT, Evgeny Astigeevich <eastigeevich at openjdk.org> wrote:
>> New ways of handling wrap-around of size_t variables are implemented and are under tests.
>
> @afshin-zafari,
> I am sorry my code for the negative case will have UB on LP64 systems. It assumes `sizeof(long long) > sizeof(long)`.
> On LP64 systems: `sizeof(size_t) == sizeof(long) == sizeof(long long) == 8`.
> On LP64 systems if `amount == LONG_MAX+1`, then `amount == LLONG_MAX+1`. So `(long long)amount` will have UB.
>
> The correct code for the negative case:
>
>
> if (is_negative) {
> assert(amount - 1 <= LONG_MAX, "cannot fit scaled diff into long);
> return (amount - 1 == LONG_MAX) ? LONG_MIN : -(long)amount;
> }
1) When amount is negative, it is a very large positive number as it is unsigned.
2) amount +/- _scale/2 may wrap-around the boundaries.
3) In some cases, the actual negative amount should be returned. Expected by some tests.
My new code under test (All NMT tests passed locally, mach5 tier1-5 ongoing) is as follows:
inline long diff_in_current_scale(size_t s1, size_t s2) const {
// _scale should not be 0, otherwise division by zero at return.
assert(_scale != 0, "wrong scale");
// Since size_t is unsigned, the amount >= 0 is always true.
// Therefore, shifting the amount half the scale down/up is
// decided based on the s1 and s2. Thus, s1 >= s2 means amount >= 0.
// ((a + b) > a) where b != 0, is used to check wrap-around of adding two size_t variables.
// ((a - b) < a) where b != 0, is used to check wrap-around of subtracting two size_t variables.
size_t amount = s1 - s2;
if (amount == 0){
return 0L;
}
if (s1 >= s2) {
if ((_scale / 2) != 0) {
assert((amount + _scale / 2) > amount, "difference is greater than the upper limit.");
amount += _scale / 2;
}
return (long)(amount / _scale);
}
if ((_scale / 2) != 0){
assert((amount - _scale / 2) < amount, "difference is less than the lower limit.");
amount -= _scale / 2;
}
return (long) amount / (long) _scale;
}
-------------
PR: https://git.openjdk.org/jdk/pull/11514
More information about the hotspot-runtime-dev
mailing list