[Python-Dev] Negated hex/oct constants (SF #660455)

Tim Peters tim_one@email.msn.com
Wed, 5 Feb 2003 21:44:56 -0500


[Guido]
> ...
> The cases that bother me are -0xffffffff in Python 2.2 and 2.3: this
> is an unintended side effect of a peephole optimization!!!
>
> It's quite unsettling:
>
>   >>> x = 0xffffffff
>   >>> x
>   -1
>   >>> -x
>   1
>   >>> -(0xffffffff)
>   1
>   >>> -0xffffffff
>   -4294967295L                          <<<<-------- !!!
>   >>>
> ...
> --- CONCLUSION ---
>
> The bad thing is that this bug is already in all versions of Python
> 2.2, as well as in Python 2.3a1.
>
> I originally thought that it absolutely had to be fixed, because the
> inconsistency between -(0xffffffff) and -0xffffffff is just too bad to
> bear.

Ya, but is it a security hole <wink>.

> On the other hand, given that it's already this way in Python 2.2, and
> will be again in Python 2.4, maybe we should leave it this way?  I
> find it almost cute that you can spell negative constants with an
> explicit minus sign.  (It's even correct in the sense that it doesn't
> issue a warning!)
>
> Opinions?  Am I crazy?  It seems too late to use the time machine --
> OTOH I could claim that this is *already* caused by time machine usage
> from the Python 2.4 era.

The Windows installer can scour the disk for previously installed Pythons,
and install one of two versions of python23.dll, depending on which broken
behavior the user is accustomed to.  If there are no installed versions of
Python, it will pick the 2.4-compatible DLL, to minimize future pain (or you
can think of it as the 2.2.2-compatible DLL, to minimize past pain).  If
there are incompatible versions of Python already installed, it will pop up
a dialog box asking the user which to install by default.  The other DLL
will be installed under a different name, and main() and WinMain() will be
fiddled to use that DLL instead if envar PYTHONMINUSOHX exists and has value
OTHER, ALTERNATEPYTHONMINUSOHXBEHAVIORPLEASE, or 1.

Short of that, I vote we keep 2.3 compatible with 2.2 and 2.4.  If anyone
ever reports this bug in 2.2 or 2.3, I'll feign genuine surprise, and
explain it was due to a time-machine backport of 2.4, which can be fixed
over the short term by upgrading to Python 1.6.1.

Note that there's another case:

>>> -037777777777
-4294967295L
>>> -(037777777777)
1
>>>

OTOH, even in 2.1.3, int() didn't agree about what these kinds of int
literals mean:

>>> int("ffffffff", 16)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: int() literal too large: ffffffff
>>>

On the third hand, still in 2.1.3,

>>> int("0xffffffff", 0)
-1
>>>

Going back to 2.3 on the fourth hand gives another surprising pair:

>>> int("ffffffff", 16)
4294967295L
>>> int("0xffffffff", 0)
-1
>>>

A rational user will conclude that Python has no idea what hex literals mean
<0.9 wink>.