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.
diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c
index 14fed3e..3f75fe7 100644
--- a/Modules/cjkcodecs/multibytecodec.c
+++ b/Modules/cjkcodecs/multibytecodec.c
@@ -170,8 +170,10 @@
     orgsize = PyString_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 (_PyString_Resize(&buf->outobj, orgsize + incsize) == -1)
         return -1;
@@ -182,11 +184,11 @@
 
     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)
 
 static int
 expand_decodebuffer(MultibyteDecodeBuffer *buf, Py_ssize_t esize)
@@ -205,11 +207,11 @@
 
     return 0;
 }
-#define REQUIRE_DECODEBUFFER(buf, s) {                                  \
-    if ((s) < 1 || (buf)->outbuf + (s) > (buf)->outbuf_end)             \
+#define REQUIRE_DECODEBUFFER(buf, s) do {                               \
+    if ((s) < 0 || (s) > (buf)->outbuf_end - (buf)->outbuf)             \
         if (expand_decodebuffer(buf, s) == -1)                          \
             goto errorexit;                                             \
-}
+} while(0)
 
 
 /**
@@ -327,10 +329,11 @@
     }
 
     retstrsize = PyString_GET_SIZE(retstr);
-    REQUIRE_ENCODEBUFFER(buf, retstrsize);
-
-    memcpy(buf->outbuf, PyString_AS_STRING(retstr), retstrsize);
-    buf->outbuf += retstrsize;
+    if (retstrsize > 0) {
+        REQUIRE_ENCODEBUFFER(buf, retstrsize);
+        memcpy(buf->outbuf, PyString_AS_STRING(retstr), retstrsize);
+        buf->outbuf += retstrsize;
+    }
 
     newpos = PyInt_AsSsize_t(PyTuple_GET_ITEM(retobj, 1));
     if (newpos < 0 && !PyErr_Occurred())