]> granicus.if.org Git - python/commitdiff
Issue #23215: Multibyte codecs with custom error handlers that ignores errors
authorSerhiy Storchaka <storchaka@gmail.com>
Fri, 20 Feb 2015 23:19:58 +0000 (01:19 +0200)
committerSerhiy Storchaka <storchaka@gmail.com>
Fri, 20 Feb 2015 23:19:58 +0000 (01:19 +0200)
consumed too much memory and raised SystemError or MemoryError.
Original patch by Aleksi Torhamo.

Lib/test/test_multibytecodec.py
Misc/NEWS
Modules/cjkcodecs/multibytecodec.c

index ce267ddeb319bb32ee0998ee18bb61bdde4def39..2929f988a8e58e6f9bd38b539676135910ddfa9d 100644 (file)
@@ -44,6 +44,13 @@ class Test_MultibyteCodec(unittest.TestCase):
         self.assertRaises(IndexError, dec,
                           b'apple\x92ham\x93spam', 'test.cjktest')
 
+    def test_errorcallback_custom_ignore(self):
+        # Issue #23215: MemoryError with custom error handlers and multibyte codecs
+        data = 100 * "\udc00"
+        codecs.register_error("test.ignore", codecs.ignore_errors)
+        for enc in ALL_CJKENCODINGS:
+            self.assertEqual(data.encode(enc, "test.ignore"), b'')
+
     def test_codingspec(self):
         try:
             for enc in ALL_CJKENCODINGS:
index bcabefaf3f9537a54c839b38a54a112d3981e117..f1426d2f728ac9b24eb835f0a6275245c98a60fa 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -13,6 +13,10 @@ Core and Builtins
 Library
 -------
 
+- Issue #23215: Multibyte codecs with custom error handlers that ignores errors
+  consumed too much memory and raised SystemError or MemoryError.
+  Original patch by Aleksi Torhamo.
+
 - Issue #5700: io.FileIO() called flush() after closing the file.
   flush() was not called in close() if closefd=False.
 
index 087ae9b1aff5eb6f7aa1032c91bccfb4afd28a7c..435529fb0e5304b4bffbb4e8e67088448a611ec7 100644 (file)
@@ -182,8 +182,10 @@ expand_encodebuffer(MultibyteEncodeBuffer *buf, Py_ssize_t esize)
     orgsize = PyBytes_GET_SIZE(buf->outobj);
     incsize = (esize < (orgsize >> 1) ? (orgsize >> 1) | 1 : esize);
 
-    if (orgsize > PY_SSIZE_T_MAX - incsize)
+    if (orgsize > PY_SSIZE_T_MAX - incsize) {
+        PyErr_NoMemory();
         return -1;
+    }
 
     if (_PyBytes_Resize(&buf->outobj, orgsize + incsize) == -1)
         return -1;
@@ -194,11 +196,11 @@ expand_encodebuffer(MultibyteEncodeBuffer *buf, Py_ssize_t esize)
 
     return 0;
 }
-#define REQUIRE_ENCODEBUFFER(buf, s) {                                  \
-    if ((s) < 1 || (buf)->outbuf + (s) > (buf)->outbuf_end)             \
+#define REQUIRE_ENCODEBUFFER(buf, s) do {                               \
+    if ((s) < 0 || (s) > (buf)->outbuf_end - (buf)->outbuf)             \
         if (expand_encodebuffer(buf, s) == -1)                          \
             goto errorexit;                                             \
-}
+} while(0)
 
 
 /**
@@ -332,10 +334,11 @@ multibytecodec_encerror(MultibyteCodec *codec,
 
     assert(PyBytes_Check(retstr));
     retstrsize = PyBytes_GET_SIZE(retstr);
-    REQUIRE_ENCODEBUFFER(buf, retstrsize);
-
-    memcpy(buf->outbuf, PyBytes_AS_STRING(retstr), retstrsize);
-    buf->outbuf += retstrsize;
+    if (retstrsize > 0) {
+        REQUIRE_ENCODEBUFFER(buf, retstrsize);
+        memcpy(buf->outbuf, PyBytes_AS_STRING(retstr), retstrsize);
+        buf->outbuf += retstrsize;
+    }
 
     newpos = PyLong_AsSsize_t(PyTuple_GET_ITEM(retobj, 1));
     if (newpos < 0 && !PyErr_Occurred())