[Python-checkins] cpython (merge 3.6 -> default): Issue #27599: Fixed buffer overrun in binascii.b2a_qp() and binascii.a2b_qp().

serhiy.storchaka python-checkins at python.org
Wed Sep 14 09:39:15 EDT 2016


https://hg.python.org/cpython/rev/56294e03ad89
changeset: 103803:56294e03ad89
parent: 103799:070cc3b9d5cc
parent: 103802:d53e1a5576e6
user: Serhiy Storchaka <storchaka at gmail.com>
date: Wed Sep 14 16:38:48 2016 +0300
summary:
 Issue #27599: Fixed buffer overrun in binascii.b2a_qp() and binascii.a2b_qp().
files:
 Lib/test/test_binascii.py | 111 +++++++++++++++++++++----
 Misc/NEWS | 2 +
 Modules/binascii.c | 12 +-
 3 files changed, 99 insertions(+), 26 deletions(-)
diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py
--- a/Lib/test/test_binascii.py
+++ b/Lib/test/test_binascii.py
@@ -192,37 +192,106 @@
 self.assertEqual(binascii.unhexlify(self.type2test(t)), u)
 
 def test_qp(self):
- binascii.a2b_qp(data=b"", header=False) # Keyword arguments allowed
+ type2test = self.type2test
+ a2b_qp = binascii.a2b_qp
+ b2a_qp = binascii.b2a_qp
+
+ a2b_qp(data=b"", header=False) # Keyword arguments allowed
 
 # A test for SF bug 534347 (segfaults without the proper fix)
 try:
- binascii.a2b_qp(b"", **{1:1})
+ a2b_qp(b"", **{1:1})
 except TypeError:
 pass
 else:
 self.fail("binascii.a2b_qp(**{1:1}) didn't raise TypeError")
 
- self.assertEqual(binascii.a2b_qp(b"= "), b"= ")
- self.assertEqual(binascii.a2b_qp(b"=="), b"=")
- self.assertEqual(binascii.a2b_qp(b"=AX"), b"=AX")
- self.assertRaises(TypeError, binascii.b2a_qp, foo="bar")
- self.assertEqual(binascii.a2b_qp(b"=00\r\n=00"), b"\x00\r\n\x00")
- self.assertEqual(
- binascii.b2a_qp(b"\xff\r\n\xff\n\xff"),
- b"=FF\r\n=FF\r\n=FF")
- self.assertEqual(
- binascii.b2a_qp(b"0"*75+b"\xff\r\n\xff\r\n\xff"),
- b"0"*75+b"=\r\n=FF\r\n=FF\r\n=FF")
+ self.assertEqual(a2b_qp(type2test(b"=")), b"")
+ self.assertEqual(a2b_qp(type2test(b"= ")), b"= ")
+ self.assertEqual(a2b_qp(type2test(b"==")), b"=")
+ self.assertEqual(a2b_qp(type2test(b"=\nAB")), b"AB")
+ self.assertEqual(a2b_qp(type2test(b"=\r\nAB")), b"AB")
+ self.assertEqual(a2b_qp(type2test(b"=\rAB")), b"") # ?
+ self.assertEqual(a2b_qp(type2test(b"=\rAB\nCD")), b"CD") # ?
+ self.assertEqual(a2b_qp(type2test(b"=AB")), b"\xab")
+ self.assertEqual(a2b_qp(type2test(b"=ab")), b"\xab")
+ self.assertEqual(a2b_qp(type2test(b"=AX")), b"=AX")
+ self.assertEqual(a2b_qp(type2test(b"=XA")), b"=XA")
+ self.assertEqual(a2b_qp(type2test(b"=AB")[:-1]), b"=A")
 
- self.assertEqual(binascii.b2a_qp(b'0円\n'), b'=00\n')
- self.assertEqual(binascii.b2a_qp(b'0円\n', quotetabs=True), b'=00\n')
- self.assertEqual(binascii.b2a_qp(b'foo\tbar\t\n'), b'foo\tbar=09\n')
- self.assertEqual(binascii.b2a_qp(b'foo\tbar\t\n', quotetabs=True),
- b'foo=09bar=09\n')
+ self.assertEqual(a2b_qp(type2test(b'_')), b'_')
+ self.assertEqual(a2b_qp(type2test(b'_'), header=True), b' ')
 
- self.assertEqual(binascii.b2a_qp(b'.'), b'=2E')
- self.assertEqual(binascii.b2a_qp(b'.\n'), b'=2E\n')
- self.assertEqual(binascii.b2a_qp(b'a.\n'), b'a.\n')
+ self.assertRaises(TypeError, b2a_qp, foo="bar")
+ self.assertEqual(a2b_qp(type2test(b"=00\r\n=00")), b"\x00\r\n\x00")
+ self.assertEqual(b2a_qp(type2test(b"\xff\r\n\xff\n\xff")),
+ b"=FF\r\n=FF\r\n=FF")
+ self.assertEqual(b2a_qp(type2test(b"0"*75+b"\xff\r\n\xff\r\n\xff")),
+ b"0"*75+b"=\r\n=FF\r\n=FF\r\n=FF")
+
+ self.assertEqual(b2a_qp(type2test(b'\x7f')), b'=7F')
+ self.assertEqual(b2a_qp(type2test(b'=')), b'=3D')
+
+ self.assertEqual(b2a_qp(type2test(b'_')), b'_')
+ self.assertEqual(b2a_qp(type2test(b'_'), header=True), b'=5F')
+ self.assertEqual(b2a_qp(type2test(b'x y'), header=True), b'x_y')
+ self.assertEqual(b2a_qp(type2test(b'x '), header=True), b'x=20')
+ self.assertEqual(b2a_qp(type2test(b'x y'), header=True, quotetabs=True),
+ b'x=20y')
+ self.assertEqual(b2a_qp(type2test(b'x\ty'), header=True), b'x\ty')
+
+ self.assertEqual(b2a_qp(type2test(b' ')), b'=20')
+ self.assertEqual(b2a_qp(type2test(b'\t')), b'=09')
+ self.assertEqual(b2a_qp(type2test(b' x')), b' x')
+ self.assertEqual(b2a_qp(type2test(b'\tx')), b'\tx')
+ self.assertEqual(b2a_qp(type2test(b' x')[:-1]), b'=20')
+ self.assertEqual(b2a_qp(type2test(b'\tx')[:-1]), b'=09')
+ self.assertEqual(b2a_qp(type2test(b'0円')), b'=00')
+
+ self.assertEqual(b2a_qp(type2test(b'0円\n')), b'=00\n')
+ self.assertEqual(b2a_qp(type2test(b'0円\n'), quotetabs=True), b'=00\n')
+
+ self.assertEqual(b2a_qp(type2test(b'x y\tz')), b'x y\tz')
+ self.assertEqual(b2a_qp(type2test(b'x y\tz'), quotetabs=True),
+ b'x=20y=09z')
+ self.assertEqual(b2a_qp(type2test(b'x y\tz'), istext=False),
+ b'x y\tz')
+ self.assertEqual(b2a_qp(type2test(b'x \ny\t\n')),
+ b'x=20\ny=09\n')
+ self.assertEqual(b2a_qp(type2test(b'x \ny\t\n'), quotetabs=True),
+ b'x=20\ny=09\n')
+ self.assertEqual(b2a_qp(type2test(b'x \ny\t\n'), istext=False),
+ b'x =0Ay\t=0A')
+ self.assertEqual(b2a_qp(type2test(b'x \ry\t\r')),
+ b'x \ry\t\r')
+ self.assertEqual(b2a_qp(type2test(b'x \ry\t\r'), quotetabs=True),
+ b'x=20\ry=09\r')
+ self.assertEqual(b2a_qp(type2test(b'x \ry\t\r'), istext=False),
+ b'x =0Dy\t=0D')
+ self.assertEqual(b2a_qp(type2test(b'x \r\ny\t\r\n')),
+ b'x=20\r\ny=09\r\n')
+ self.assertEqual(b2a_qp(type2test(b'x \r\ny\t\r\n'), quotetabs=True),
+ b'x=20\r\ny=09\r\n')
+ self.assertEqual(b2a_qp(type2test(b'x \r\ny\t\r\n'), istext=False),
+ b'x =0D=0Ay\t=0D=0A')
+
+ self.assertEqual(b2a_qp(type2test(b'x \r\n')[:-1]), b'x \r')
+ self.assertEqual(b2a_qp(type2test(b'x\t\r\n')[:-1]), b'x\t\r')
+ self.assertEqual(b2a_qp(type2test(b'x \r\n')[:-1], quotetabs=True),
+ b'x=20\r')
+ self.assertEqual(b2a_qp(type2test(b'x\t\r\n')[:-1], quotetabs=True),
+ b'x=09\r')
+ self.assertEqual(b2a_qp(type2test(b'x \r\n')[:-1], istext=False),
+ b'x =0D')
+ self.assertEqual(b2a_qp(type2test(b'x\t\r\n')[:-1], istext=False),
+ b'x\t=0D')
+
+ self.assertEqual(b2a_qp(type2test(b'.')), b'=2E')
+ self.assertEqual(b2a_qp(type2test(b'.\n')), b'=2E\n')
+ self.assertEqual(b2a_qp(type2test(b'.\r')), b'=2E\r')
+ self.assertEqual(b2a_qp(type2test(b'.0円')), b'=2E=00')
+ self.assertEqual(b2a_qp(type2test(b'a.\n')), b'a.\n')
+ self.assertEqual(b2a_qp(type2test(b'.a')[:-1]), b'=2E')
 
 def test_empty_string(self):
 # A test for SF bug #1022953. Make sure SystemError is not raised.
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -22,6 +22,8 @@
 Library
 -------
 
+- Issue #27599: Fixed buffer overrun in binascii.b2a_qp() and binascii.a2b_qp().
+
 Build
 -----
 
diff --git a/Modules/binascii.c b/Modules/binascii.c
--- a/Modules/binascii.c
+++ b/Modules/binascii.c
@@ -1276,7 +1276,8 @@
 odata[out++] = '=';
 in++;
 }
- else if (((ascii_data[in] >= 'A' && ascii_data[in] <= 'F') ||
+ else if ((in + 1 < datalen) &&
+ ((ascii_data[in] >= 'A' && ascii_data[in] <= 'F') ||
 (ascii_data[in] >= 'a' && ascii_data[in] <= 'f') ||
 (ascii_data[in] >= '0' && ascii_data[in] <= '9')) &&
 ((ascii_data[in+1] >= 'A' && ascii_data[in+1] <= 'F') ||
@@ -1375,7 +1376,8 @@
 (databuf[in] == '=') ||
 (header && databuf[in] == '_') ||
 ((databuf[in] == '.') && (linelen == 0) &&
- (databuf[in+1] == '\n' || databuf[in+1] == '\r' || databuf[in+1] == 0)) ||
+ (in + 1 == datalen || databuf[in+1] == '\n' ||
+ databuf[in+1] == '\r' || databuf[in+1] == 0)) ||
 (!istext && ((databuf[in] == '\r') || (databuf[in] == '\n'))) ||
 ((databuf[in] == '\t' || databuf[in] == ' ') && (in + 1 == datalen)) ||
 ((databuf[in] < 33) &&
@@ -1451,13 +1453,13 @@
 (databuf[in] == '=') ||
 (header && databuf[in] == '_') ||
 ((databuf[in] == '.') && (linelen == 0) &&
- (databuf[in+1] == '\n' || databuf[in+1] == '\r' || databuf[in+1] == 0)) ||
+ (in + 1 == datalen || databuf[in+1] == '\n' ||
+ databuf[in+1] == '\r' || databuf[in+1] == 0)) ||
 (!istext && ((databuf[in] == '\r') || (databuf[in] == '\n'))) ||
 ((databuf[in] == '\t' || databuf[in] == ' ') && (in + 1 == datalen)) ||
 ((databuf[in] < 33) &&
 (databuf[in] != '\r') && (databuf[in] != '\n') &&
- (quotetabs ||
- (!quotetabs && ((databuf[in] != '\t') && (databuf[in] != ' '))))))
+ (quotetabs || ((databuf[in] != '\t') && (databuf[in] != ' ')))))
 {
 if ((linelen + 3 )>= MAXLINESIZE) {
 odata[out++] = '=';
-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /