mirror of
https://github.com/python/cpython.git
synced 2025-07-28 13:44:43 +00:00
Fix #1679: "0x" was taken as a valid integer literal.
Fixes the tokenizer, tokenize.py and int() to reject this. Patches by Malte Helmert.
This commit is contained in:
parent
2686f4d9d1
commit
14404b68d8
6 changed files with 45 additions and 16 deletions
|
@ -816,6 +816,11 @@ class BuiltinTest(unittest.TestCase):
|
||||||
self.assertEqual(int('0123', 0), 83)
|
self.assertEqual(int('0123', 0), 83)
|
||||||
self.assertEqual(int('0x123', 16), 291)
|
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
|
# SF bug 1334662: int(string, base) wrong answers
|
||||||
# Various representations of 2**32 evaluated to 0
|
# Various representations of 2**32 evaluated to 0
|
||||||
# rather than 2**32 in previous versions
|
# rather than 2**32 in previous versions
|
||||||
|
|
|
@ -30,6 +30,8 @@ class TokenTests(unittest.TestCase):
|
||||||
self.assertEquals(0xff, 255)
|
self.assertEquals(0xff, 255)
|
||||||
self.assertEquals(0377, 255)
|
self.assertEquals(0377, 255)
|
||||||
self.assertEquals(2147483647, 017777777777)
|
self.assertEquals(2147483647, 017777777777)
|
||||||
|
# "0x" is not a valid literal
|
||||||
|
self.assertRaises(SyntaxError, eval, "0x")
|
||||||
from sys import maxint
|
from sys import maxint
|
||||||
if maxint == 2147483647:
|
if maxint == 2147483647:
|
||||||
self.assertEquals(-2147483647-1, -020000000000)
|
self.assertEquals(-2147483647-1, -020000000000)
|
||||||
|
|
|
@ -50,7 +50,7 @@ Comment = r'#[^\r\n]*'
|
||||||
Ignore = Whitespace + any(r'\\\r?\n' + Whitespace) + maybe(Comment)
|
Ignore = Whitespace + any(r'\\\r?\n' + Whitespace) + maybe(Comment)
|
||||||
Name = r'[a-zA-Z_]\w*'
|
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]?'
|
Octnumber = r'0[0-7]*[lL]?'
|
||||||
Decnumber = r'[1-9]\d*[lL]?'
|
Decnumber = r'[1-9]\d*[lL]?'
|
||||||
Intnumber = group(Hexnumber, Octnumber, Decnumber)
|
Intnumber = group(Hexnumber, Octnumber, Decnumber)
|
||||||
|
|
|
@ -12,6 +12,8 @@ What's New in Python 2.6 alpha 1?
|
||||||
Core and builtins
|
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
|
- Issue #1865: Bytes as an alias for str and b"" as an alias "" were
|
||||||
added.
|
added.
|
||||||
|
|
||||||
|
|
|
@ -1332,7 +1332,14 @@ tok_get(register struct tok_state *tok, char **p_start, char **p_end)
|
||||||
goto imaginary;
|
goto imaginary;
|
||||||
#endif
|
#endif
|
||||||
if (c == 'x' || c == 'X') {
|
if (c == 'x' || c == 'X') {
|
||||||
|
|
||||||
/* Hex */
|
/* Hex */
|
||||||
|
c = tok_nextc(tok);
|
||||||
|
if (!isxdigit(c)) {
|
||||||
|
tok->done = E_TOKEN;
|
||||||
|
tok_backup(tok, c);
|
||||||
|
return ERRORTOKEN;
|
||||||
|
}
|
||||||
do {
|
do {
|
||||||
c = tok_nextc(tok);
|
c = tok_nextc(tok);
|
||||||
} while (isxdigit(c));
|
} while (isxdigit(c));
|
||||||
|
|
|
@ -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 */
|
/* check for leading 0 or 0x for auto-base or base 16 */
|
||||||
switch (base) {
|
switch (base) {
|
||||||
case 0: /* look for leading 0, 0x or 0X */
|
case 0: /* look for leading 0, 0x or 0X */
|
||||||
if (*str == '0') {
|
if (*str == '0') {
|
||||||
++str;
|
++str;
|
||||||
if (*str == 'x' || *str == 'X') {
|
if (*str == 'x' || *str == 'X') {
|
||||||
++str;
|
/* there must be at least one digit after 0x */
|
||||||
base = 16;
|
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
|
||||||
|
if (ptr)
|
||||||
|
*ptr = str;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
++str;
|
||||||
base = 8;
|
base = 16;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
base = 10;
|
base = 8;
|
||||||
break;
|
}
|
||||||
|
else
|
||||||
|
base = 10;
|
||||||
|
break;
|
||||||
|
|
||||||
case 16: /* skip leading 0x or 0X */
|
case 16: /* skip leading 0x or 0X */
|
||||||
if (*str == '0') {
|
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;
|
++str;
|
||||||
if (*str == 'x' || *str == 'X')
|
|
||||||
++str;
|
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* catch silly bases */
|
/* catch silly bases */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue