[squeak-dev] Fwd: doesn't Primitive 33 primitiveQuoLargeIntegers relies on C Undefined Behaviour ? uncover a BUG in Primitive 32 primitiveDivLargeIntegers and maybe some others

Igor Stasenko siguctua at gmail.com
Tue Aug 28 23:34:03 UTC 2012


On 28 August 2012 23:36, Nicolas Cellier
<nicolas.cellier.aka.nice at gmail.com> wrote:
> Sorry to post here, this bounced at vm-dev
> But I think it's important
>
> Nicolas
>
>
> ---------- Forwarded message ----------
> From: Nicolas Cellier <nicolas.cellier.aka.nice at gmail.com>
> Date: 2012/8/28
> Subject: doesn't Primitive 33 primitiveQuoLargeIntegers relies on C
> Undefined Behaviour ? uncover a BUG in Primitive 32
> primitiveDivLargeIntegers and maybe some others
> To: vm-dev-request at lists.squeakfoundation.org
>
>
> (1 << 63) negated is converted to signed long long
> 0x8000000000000000LL by signed64BitValueOf:
>
> So far so good...
> Then in primitiveQuoLargeIntegers, we will try to take absolute value
> of this beast...
>
> integerRcvr > 0 ifTrue: [
>                 integerArg > 0
>                         ifTrue: [result := integerRcvr // integerArg]
>                         ifFalse: [result := 0 - (integerRcvr // (0 -
> integerArg))].
>         ] ifFalse: [
>                 integerArg > 0
>                         ifTrue: [result := 0 - ((0 - integerRcvr) //
> integerArg)]
>                         ifFalse: [result := (0 - integerRcvr) // (0 -
> integerArg)].
>         ].
>
> That is translated straightfully in C...
>
>     sqLong integerArg;
>     sqLong integerRcvr;
>     sqLong result;
>
> snip...
>
>         if (integerRcvr > 0) {
>                 if (integerArg > 0) {
>                         result = integerRcvr / integerArg;
>                 }
>                 else {
>                         result = 0 - (integerRcvr / (0 - integerArg));
>                 }
>         }
>         else {
>                 if (integerArg > 0) {
>                         result = 0 - ((0 - integerRcvr) / integerArg);
>                 }
>                 else {
>                         result = (0 - integerRcvr) / (0 - integerArg);
>                 }
>         }
>
> Isn't this relying on UB? like
> http://stackoverflow.com/questions/2539178/why-is-abs0x80000000-0x80000000
> At worse, I would expect 0 -  0x8000000000000000LL to be converted to
> itself  0x8000000000000000LL...
> So can someone explain why this works?
>

i think i know , what is wrong here.

the 'bug' is an arithmetic overflow, because of asymmetry in negative
and positive value ranges.

to simplify, what happens lets consider we dealing with 8-bit integer values.
So, a positive range for 8-bit integer is
1..127
but a negative is
-128 .. -1

mathematically speaking..
  if value E belongs to [-128 .. 127 ],  we want that for any E a
following should also hold:
  (0 - E) belongs to [-128..127]

but apparently it doesn't holds for E = -128.

That means , an expression

x := 0 - y ,

where y is our machine integer may not result in a correct negation,
but can lead to arithmetic overflow.


-- 
Best regards,
Igor Stasenko.


More information about the Squeak-dev mailing list