summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2013-01-25 21:33:22 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2013-01-25 21:33:22 (GMT)
commitf584aba3a506e72a59e2e834bc56a6e97f4ab4dd (patch)
tree781cc4a2bf45328208ea06ca0bb6427a42a6c788
parent13252b877016aa5380f4ae36fb024671c2ea77db (diff)
parente58785b200241bc9ced51a30bce7781a3c0c629c (diff)
downloadcpython-f584aba3a506e72a59e2e834bc56a6e97f4ab4dd.zip
cpython-f584aba3a506e72a59e2e834bc56a6e97f4ab4dd.tar.gz
cpython-f584aba3a506e72a59e2e834bc56a6e97f4ab4dd.tar.bz2
Issue #16975: Fix error handling bug in the escape-decode bytes decoder.
-rw-r--r--Lib/test/test_codecs.py44
-rw-r--r--Misc/NEWS2
-rw-r--r--Objects/bytesobject.c4
3 files changed, 50 insertions, 0 deletions
diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py
index 5be78d7..e0203a9 100644
--- a/Lib/test/test_codecs.py
+++ b/Lib/test/test_codecs.py
@@ -927,6 +927,50 @@ class EscapeDecodeTest(unittest.TestCase):
def test_empty(self):
self.assertEqual(codecs.escape_decode(""), (b"", 0))
+ def test_raw(self):
+ for b in range(256):
+ if b != b'\\'[0]:
+ self.assertEqual(codecs.escape_decode(bytes([b]) + b'0'),
+ (bytes([b]) + b'0', 2))
+
+ def test_escape(self):
+ self.assertEqual(codecs.escape_decode(b"[\\\n]"), (b"[]", 4))
+ self.assertEqual(codecs.escape_decode(br'[\"]'), (b'["]', 4))
+ self.assertEqual(codecs.escape_decode(br"[\']"), (b"[']", 4))
+ self.assertEqual(codecs.escape_decode(br"[\\]"), (br"[\]", 4))
+ self.assertEqual(codecs.escape_decode(br"[\a]"), (b"[\x07]", 4))
+ self.assertEqual(codecs.escape_decode(br"[\b]"), (b"[\x08]", 4))
+ self.assertEqual(codecs.escape_decode(br"[\t]"), (b"[\x09]", 4))
+ self.assertEqual(codecs.escape_decode(br"[\n]"), (b"[\x0a]", 4))
+ self.assertEqual(codecs.escape_decode(br"[\v]"), (b"[\x0b]", 4))
+ self.assertEqual(codecs.escape_decode(br"[\f]"), (b"[\x0c]", 4))
+ self.assertEqual(codecs.escape_decode(br"[\r]"), (b"[\x0d]", 4))
+ self.assertEqual(codecs.escape_decode(br"[\7]"), (b"[\x07]", 4))
+ self.assertEqual(codecs.escape_decode(br"[\8]"), (br"[\8]", 4))
+ self.assertEqual(codecs.escape_decode(br"[\78]"), (b"[\x078]", 5))
+ self.assertEqual(codecs.escape_decode(br"[\41]"), (b"[!]", 5))
+ self.assertEqual(codecs.escape_decode(br"[\418]"), (b"[!8]", 6))
+ self.assertEqual(codecs.escape_decode(br"[\101]"), (b"[A]", 6))
+ self.assertEqual(codecs.escape_decode(br"[\1010]"), (b"[A0]", 7))
+ self.assertEqual(codecs.escape_decode(br"[\501]"), (b"[A]", 6))
+ self.assertEqual(codecs.escape_decode(br"[\x41]"), (b"[A]", 6))
+ self.assertEqual(codecs.escape_decode(br"[\X41]"), (br"[\X41]", 6))
+ self.assertEqual(codecs.escape_decode(br"[\x410]"), (b"[A0]", 7))
+ for b in range(256):
+ if b not in b'\n"\'\\abtnvfr01234567x':
+ self.assertEqual(codecs.escape_decode(b'\\' + bytes([b])),
+ (b'\\' + bytes([b]), 2))
+
+ def test_errors(self):
+ self.assertRaises(ValueError, codecs.escape_decode, br"\x")
+ self.assertRaises(ValueError, codecs.escape_decode, br"[\x]")
+ self.assertEqual(codecs.escape_decode(br"[\x]\x", "ignore"), (b"[]", 6))
+ self.assertEqual(codecs.escape_decode(br"[\x]\x", "replace"), (b"[?]?", 6))
+ self.assertRaises(ValueError, codecs.escape_decode, br"\x0")
+ self.assertRaises(ValueError, codecs.escape_decode, br"[\x0]")
+ self.assertEqual(codecs.escape_decode(br"[\x0]\x0", "ignore"), (b"[]", 8))
+ self.assertEqual(codecs.escape_decode(br"[\x0]\x0", "replace"), (b"[?]?", 8))
+
class RecodingTest(unittest.TestCase):
def test_recoding(self):
f = io.BytesIO()
diff --git a/Misc/NEWS b/Misc/NEWS
index c7e2034..af4ae6a 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,8 @@ What's New in Python 3.4.0 Alpha 1?
Core and Builtins
-----------------
+- Issue #16975: Fix error handling bug in the escape-decode bytes decoder.
+
- Issue #14850: Now a charmap decoder treats U+FFFE as "undefined mapping"
in any mapping, not only in a string.
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index 91f65f9..20de5cc 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -489,6 +489,10 @@ PyObject *PyBytes_DecodeEscape(const char *s,
errors);
goto failed;
}
+ /* skip \x */
+ if (s < end && Py_ISXDIGIT(s[0]))
+ s++; /* and a hexdigit */
+ break;
default:
*p++ = '\\';
s--;