Portability bug in integral conversion
Bruno Medeiros
brunodomedeiros+spam at com.gmail
Fri Feb 4 04:52:10 PST 2011
On 17/01/2011 00:09, Andrei Alexandrescu wrote:
> On 1/16/11 5:24 PM, Graham St Jack wrote:
>> On 16/01/11 08:52, Andrei Alexandrescu wrote:
>>> We've spent a lot of time trying to improve the behavior of integral
>>> types in D. For the most part, we succeeded, but the success was
>>> partial. There was some hope with the polysemy notion, but it
>>> ultimately was abandoned because it was deemed too difficult to
>>> implement for its benefits, which were considered solving a minor
>>> annoyance. I was sorry to see it go, and I'm glad that now its day of
>>> reckoning has come.
>>>
>>> Some of the 32-64 portability bugs have come in the following form:
>>>
>>> char * p;
>>> uint a, b;
>>> ...
>>> p += a - b;
>>>
>>> On 32 bits, the code works even if a < b: the difference will become a
>>> large unsigned number, which is then converted to a size_t (which is a
>>> no-op since size_t is uint) and added to p. The pointer itself is a
>>> 32-bit quantity. Due to two's complement properties, the addition has
>>> the same result regardless of the signedness of its operands.
>>>
>>> On 64-bits, the same code has different behavior. The difference a - b
>>> becomes a large unsigned number (say e.g. 4 billion), which is then
>>> converted to a 64-bit size_t. After conversion the sign is not
>>> extended - so we end up with the number 4 billion on 64-bit. That is
>>> added to a 64-bit pointer yielding an incorrect value. For the
>>> wraparound to work, the 32-bit uint should have been sign-extended to
>>> 64 bit.
>>>
>>> To fix this problem, one possibility is to mark statically every
>>> result of one of uint-uint, uint+int, uint-int as "non-extensible",
>>> i.e. as impossible to implicitly extend to a 64-bit value. That would
>>> force the user to insert a cast appropriately.
>>>
>>> Thoughts? Ideas?
>>>
>>>
>>> Andrei
>> It seems to me that the real problem here is that it isn't meaningful to
>> perform (a-b) on unsigned integers when (a<b). Attempting to clean up
>> the resultant mess is really papering over the problem. How about a
>> runtime error instead, much like dividing by 0?
>
> That's too inefficient.
>
> Andrei
Really? :/ Even if the runtime error can be optionally disabled on
compilation, like arrays bound checking?
--
Bruno Medeiros - Software Engineer
More information about the Digitalmars-d
mailing list