]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Fix #1679: "0x" was taken as a valid integer literal.
authorGeorg Brandl <georg@python.org>
Sat, 19 Jan 2008 19:27:05 +0000 (19:27 +0000)
committerGeorg Brandl <georg@python.org>
Sat, 19 Jan 2008 19:27:05 +0000 (19:27 +0000)
Fixes the tokenizer, tokenize.py and int() to reject this.
Patches by Malte Helmert.

Lib/test/test_builtin.py
Lib/test/test_grammar.py
Lib/tokenize.py
Misc/NEWS
Parser/tokenizer.c
Python/mystrtoul.c

index d56e6fff87d294670f2a28496c80459612026723..f7b7c0ce74d20712ee0376f25eeb84d3c919150b 100644 (file)
@@ -816,6 +816,11 @@ class BuiltinTest(unittest.TestCase):
         self.assertEqual(int('0123', 0), 83)
         self.assertEqual(int('0x123', 16), 291)
 
+        # Bug 1679: "0x" is not a valid hex literal
+        self.assertRaises(ValueError, int, "0x", 16)
+        self.assertRaises(ValueError, int, "0x", 0)
+
+
         # SF bug 1334662: int(string, base) wrong answers
         # Various representations of 2**32 evaluated to 0
         # rather than 2**32 in previous versions
index 51d77f2ef5e85d4ad4a2c0ce3d8951542fc08952..435227521e7829469352d356ba909f5e916e84e9 100644 (file)
@@ -30,6 +30,8 @@ class TokenTests(unittest.TestCase):
         self.assertEquals(0xff, 255)
         self.assertEquals(0377, 255)
         self.assertEquals(2147483647, 017777777777)
+        # "0x" is not a valid literal
+        self.assertRaises(SyntaxError, eval, "0x")
         from sys import maxint
         if maxint == 2147483647:
             self.assertEquals(-2147483647-1, -020000000000)
index 9322e0fe1bcd1a46d80da9692b7b07687f4f5980..1c9394436818853f4a8390e293aa9c37331399d2 100644 (file)
@@ -50,7 +50,7 @@ Comment = r'#[^\r\n]*'
 Ignore = Whitespace + any(r'\\\r?\n' + Whitespace) + maybe(Comment)
 Name = r'[a-zA-Z_]\w*'
 
-Hexnumber = r'0[xX][\da-fA-F]*[lL]?'
+Hexnumber = r'0[xX][\da-fA-F]+[lL]?'
 Octnumber = r'0[0-7]*[lL]?'
 Decnumber = r'[1-9]\d*[lL]?'
 Intnumber = group(Hexnumber, Octnumber, Decnumber)
index a19a8ad3c05783e5ca384808b005ed1ea51d34fa..8a6ca66ebece30b3eea45b736eee8d5f4dc43ab7 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,8 @@ What's New in Python 2.6 alpha 1?
 Core and builtins
 -----------------
 
+- Issue #1679: "0x" was taken as a valid integer literal.
+
 - Issue #1865: Bytes as an alias for str and b"" as an alias "" were
   added.
 
index 0015daeb72536ca0fd1931b82013f612242b398d..0aaec1993481af7f560f5baf25a1f1fed6ef87de 100644 (file)
@@ -1332,7 +1332,14 @@ tok_get(register struct tok_state *tok, char **p_start, char **p_end)
                                goto imaginary;
 #endif
                        if (c == 'x' || c == 'X') {
+
                                /* Hex */
+                               c = tok_nextc(tok);
+                               if (!isxdigit(c)) {
+                                       tok->done = E_TOKEN;
+                                       tok_backup(tok, c);
+                                       return ERRORTOKEN;
+                               }
                                do {
                                        c = tok_nextc(tok);
                                } while (isxdigit(c));
index f0070575dbf68bdba5fb56cf945cd3ee7ffb3710..a02992f61711d42ac5109b680ce1b576de2f6342 100644 (file)
@@ -112,27 +112,40 @@ PyOS_strtoul(register char *str, char **ptr, int base)
 
        /* check for leading 0 or 0x for auto-base or base 16 */
        switch (base) {
-               case 0:         /* look for leading 0, 0x or 0X */
-                       if (*str == '0') {
-                               ++str;
-                               if (*str == 'x' || *str == 'X') {
-                                       ++str;
-                                       base = 16;
+       case 0:         /* look for leading 0, 0x or 0X */
+               if (*str == '0') {
+                       ++str;
+                       if (*str == 'x' || *str == 'X') {
+                               /* there must be at least one digit after 0x */
+                               if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
+                                       if (ptr)
+                                               *ptr = str;
+                                       return 0;
                                }
-                               else
-                                       base = 8;
+                               ++str;
+                               base = 16;
                        }
                        else
-                               base = 10;
-                       break;
+                               base = 8;
+               }
+               else
+                       base = 10;
+               break;
 
-               case 16:        /* skip leading 0x or 0X */
-                       if (*str == '0') {
+       case 16:        /* skip leading 0x or 0X */
+               if (*str == '0') {
+                       ++str;
+                       if (*str == 'x' || *str == 'X') {
+                               /* there must be at least one digit after 0x */
+                               if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
+                                       if (ptr)
+                                               *ptr = str;
+                                       return 0;
+                               }
                                ++str;
-                               if (*str == 'x' || *str == 'X')
-                                       ++str;
                        }
-                       break;
+               }
+               break;
        }
 
        /* catch silly bases */