-
-
Notifications
You must be signed in to change notification settings - Fork 31.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bpo-37367: octal escapes applied inconsistently throughout the interpreter and lib #14654
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ | |
import tempfile | ||
import textwrap | ||
import unittest | ||
import ast | ||
|
||
import test.support | ||
import test.string_tests | ||
|
@@ -962,6 +963,45 @@ def test_translate(self): | |
c = b.translate(None, delete=b'e') | ||
self.assertEqual(c, b'hllo') | ||
|
||
def test_octal_values(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is not correct place for such test. This file is for tests of bytes and bytearray methods, not parsing Python code.
|
||
# bpo-37367: verify that octal escape sequences | ||
# with values greater than 255 raise ValueError | ||
|
||
# test 1- and 2- digit octal escape sequences | ||
# (i.e. no leading zeroes) | ||
for i in range(0o00, 0o77): | ||
v = "b'\\{0:o}'".format(i) | ||
self.type2test(ast.literal_eval(v)) | ||
self.assertEqual(ord(ast.literal_eval(v)), i) | ||
|
||
# test 3-digit octal escape sequences | ||
# (including leading zeroes) | ||
for i in range(0o00, 0o400): | ||
v = "b'\\{0:03o}'".format(i) | ||
self.type2test(ast.literal_eval(v)) | ||
self.assertEqual(ord(ast.literal_eval(v)), i) | ||
|
||
raised = 0 | ||
for i in range(0o400, 0o1000): | ||
try: | ||
self.type2test(ast.literal_eval("b'\\{0:o}'".format(i))) | ||
except SyntaxError as e: | ||
# ast.literal_eval() raises SyntaxError and | ||
# mentions the underlying ValueError in | ||
# the returned string. | ||
self.assertEqual(str(e).find("(value error) octal value " | ||
"must be in range(0, 256)", 0), | ||
0) | ||
raised = raised + 1 | ||
self.assertEqual(raised, 0o1000-0o400) | ||
|
||
# test 4-digit octal value (4th digit should be treated as literal) | ||
self.assertEqual(ast.literal_eval("b'\\1234'"), b'S4') | ||
self.assertRaises(SyntaxError, ast.literal_eval, "b'\\4321'") | ||
|
||
# specific case mentioned in bpo-37367 | ||
self.assertRaises(SyntaxError, eval, "ord(b'\\407')") | ||
|
||
|
||
class BytesTest(BaseBytesTest, unittest.TestCase): | ||
type2test = bytes | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1174,7 +1174,7 @@ def test_escape(self): | |
check(br"[\418]", b"[!8]") | ||
check(br"[\101]", b"[A]") | ||
check(br"[\1010]", b"[A0]") | ||
check(br"[\501]", b"[A]") | ||
self.assertRaises(ValueError, decode, br"[\501]") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Move it to test_errors below. |
||
check(br"[\x41]", b"[A]") | ||
check(br"[\x410]", b"[A0]") | ||
for i in range(97, 123): | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Byte strings containing octal escape sequences with values greater than 255 | ||
will now raise ValueError. Patch by Jeffrey Kintscher. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be helpful to mention the previous behavior here. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1185,6 +1185,11 @@ PyObject *_PyBytes_DecodeEscape(const char *s, | |
if (s < end && '0' <= *s && *s <= '7') | ||
c = (c<<3) + *s++ - '0'; | ||
} | ||
if (c > 255) { | ||
PyErr_Format(PyExc_ValueError, | ||
"octal value must be in range(0, 256)"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The error message should contain the position of the invalid octal escape sequence. It would be nice if look similar to error message for invalid hexadecimal escape sequence. For example: "invalid octal escape sequence at position %zd" |
||
goto failed; | ||
} | ||
*p++ = c; | ||
break; | ||
case 'x': | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please keep the imports sorted alphabetically.