From 1e3d1c256d79ba3ae4769db3eead6c22bbf1fe87 Mon Sep 17 00:00:00 2001 From: zhangy1317 Date: Fri, 5 Aug 2022 14:48:41 +0800 Subject: [PATCH] Fix CVE-2022-31116 --- 0001-CVE-2022-31116.patch | 246 ++++++++++++++++++++++++++++++++++++++ ujson.spec | 7 +- 2 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 0001-CVE-2022-31116.patch diff --git a/0001-CVE-2022-31116.patch b/0001-CVE-2022-31116.patch new file mode 100644 index 0000000..9e99422 --- /dev/null +++ b/0001-CVE-2022-31116.patch @@ -0,0 +1,246 @@ +From 3c567c2a6499e9d80f6daae5deb6740e79073b81 Mon Sep 17 00:00:00 2001 +From: zhangy1317 +Date: Fri, 5 Aug 2022 15:59:46 +0800 +Subject: [PATCH] CVE-2022-31116 + +--- + lib/ultrajson.h | 3 +- + lib/ultrajsondec.c | 73 +++++++++++++--------------------- + python/JSONtoObj.c | 14 ++++++- + 3 files changed, 41 insertions(+), 49 deletions(-) + +diff --git a/lib/ultrajson.h b/lib/ultrajson.h +index 885f9f7..8878dcb 100644 +--- a/lib/ultrajson.h ++++ b/lib/ultrajson.h +@@ -54,7 +54,6 @@ tree doesn't have cyclic references. + #define __ULTRAJSON_H__ + + #include +-#include + + // Don't output any extra whitespaces when encoding + #define JSON_NO_EXTRA_WHITESPACE +@@ -312,7 +311,7 @@ EXPORTFUNCTION char *JSON_EncodeObject(JSOBJ obj, JSONObjectEncoder *enc, char * + + typedef struct __JSONObjectDecoder + { +- JSOBJ (*newString)(void *prv, wchar_t *start, wchar_t *end); ++ JSOBJ (*newString)(void *prv, JSUINT32 *start, JSUINT32 *end); + void (*objectAddKey)(void *prv, JSOBJ obj, JSOBJ name, JSOBJ value); + void (*arrayAddItem)(void *prv, JSOBJ obj, JSOBJ value); + JSOBJ (*newTrue)(void *prv); +diff --git a/lib/ultrajsondec.c b/lib/ultrajsondec.c +index 184b5b9..3a19afb 100644 +--- a/lib/ultrajsondec.c ++++ b/lib/ultrajsondec.c +@@ -41,7 +41,6 @@ https://opensource.apple.com/source/tcl/tcl-14/tcl/license.terms + #include + #include + #include +-#include + #include + #include + #include +@@ -58,8 +57,8 @@ struct DecoderState + { + char *start; + char *end; +- wchar_t *escStart; +- wchar_t *escEnd; ++ JSUINT32 *escStart; ++ JSUINT32 *escEnd; + int escHeap; + int lastType; + JSUINT32 objDepth; +@@ -309,8 +308,8 @@ static FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_string ( struct DecoderState *ds + JSUTF16 sur[2] = { 0 }; + int iSur = 0; + int index; +- wchar_t *escOffset; +- wchar_t *escStart; ++ JSUINT32 *escOffset; ++ JSUINT32 *escStart; + size_t escLen = (ds->escEnd - ds->escStart); + JSUINT8 *inputOffset; + JSUINT8 oct; +@@ -324,11 +323,11 @@ static FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_string ( struct DecoderState *ds + + if (ds->escHeap) + { +- if (newSize > (SIZE_MAX / sizeof(wchar_t))) ++ if (newSize > (SIZE_MAX / sizeof(JSUINT32))) + { + return SetError(ds, -1, "Could not reserve memory block"); + } +- escStart = (wchar_t *)ds->dec->realloc(ds->escStart, newSize * sizeof(wchar_t)); ++ escStart = (JSUINT32 *)ds->dec->realloc(ds->escStart, newSize * sizeof(JSUINT32)); + if (!escStart) + { + ds->dec->free(ds->escStart); +@@ -338,18 +337,18 @@ static FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_string ( struct DecoderState *ds + } + else + { +- wchar_t *oldStart = ds->escStart; +- if (newSize > (SIZE_MAX / sizeof(wchar_t))) ++ JSUINT32 *oldStart = ds->escStart; ++ if (newSize > (SIZE_MAX / sizeof(JSUINT32))) + { + return SetError(ds, -1, "Could not reserve memory block"); + } +- ds->escStart = (wchar_t *) ds->dec->malloc(newSize * sizeof(wchar_t)); ++ ds->escStart = (JSUINT32 *) ds->dec->malloc(newSize * sizeof(JSUINT32)); + if (!ds->escStart) + { + return SetError(ds, -1, "Could not reserve memory block"); + } + ds->escHeap = 1; +- memcpy(ds->escStart, oldStart, escLen * sizeof(wchar_t)); ++ memcpy(ds->escStart, oldStart, escLen * sizeof(JSUINT32)); + } + + ds->escEnd = ds->escStart + newSize; +@@ -382,14 +381,14 @@ static FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_string ( struct DecoderState *ds + inputOffset ++; + switch (*inputOffset) + { +- case '\\': *(escOffset++) = L'\\'; inputOffset++; continue; +- case '\"': *(escOffset++) = L'\"'; inputOffset++; continue; +- case '/': *(escOffset++) = L'/'; inputOffset++; continue; +- case 'b': *(escOffset++) = L'\b'; inputOffset++; continue; +- case 'f': *(escOffset++) = L'\f'; inputOffset++; continue; +- case 'n': *(escOffset++) = L'\n'; inputOffset++; continue; +- case 'r': *(escOffset++) = L'\r'; inputOffset++; continue; +- case 't': *(escOffset++) = L'\t'; inputOffset++; continue; ++ case '\\': *(escOffset++) = '\\'; inputOffset++; continue; ++ case '\"': *(escOffset++) = '\"'; inputOffset++; continue; ++ case '/': *(escOffset++) = '/'; inputOffset++; continue; ++ case 'b': *(escOffset++) = '\b'; inputOffset++; continue; ++ case 'f': *(escOffset++) = '\f'; inputOffset++; continue; ++ case 'n': *(escOffset++) = '\n'; inputOffset++; continue; ++ case 'r': *(escOffset++) = '\r'; inputOffset++; continue; ++ case 't': *(escOffset++) = '\t'; inputOffset++; continue; + + case 'u': + { +@@ -446,7 +445,7 @@ static FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_string ( struct DecoderState *ds + iSur ++; + break; + } +- (*escOffset++) = (wchar_t) sur[iSur]; ++ (*escOffset++) = (JSUINT32) sur[iSur]; + iSur = 0; + } + else +@@ -456,12 +455,9 @@ static FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_string ( struct DecoderState *ds + { + return SetError (ds, -1, "Unpaired high surrogate when decoding 'string'"); + } +-#if WCHAR_MAX == 0xffff +- (*escOffset++) = (wchar_t) sur[0]; +- (*escOffset++) = (wchar_t) sur[1]; +-#else +- (*escOffset++) = (wchar_t) 0x10000 + (((sur[0] - 0xd800) << 10) | (sur[1] - 0xdc00)); +-#endif ++ (*escOffset++) = (JSUINT32) sur[0]; ++ (*escOffset++) = (JSUINT32) sur[1]; ++ (*escOffset++) = (JSUINT32) 0x10000 + (((sur[0] - 0xd800) << 10) | (sur[1] - 0xdc00)); + iSur = 0; + } + break; +@@ -475,7 +471,7 @@ static FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_string ( struct DecoderState *ds + + case 1: + { +- *(escOffset++) = (wchar_t) (*inputOffset++); ++ *(escOffset++) = (JSUINT32) (*inputOffset++); + break; + } + +@@ -489,7 +485,7 @@ static FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_string ( struct DecoderState *ds + } + ucs |= (*inputOffset++) & 0x3f; + if (ucs < 0x80) return SetError (ds, -1, "Overlong 2 byte UTF-8 sequence detected when decoding 'string'"); +- *(escOffset++) = (wchar_t) ucs; ++ *(escOffset++) = (JSUINT32) ucs; + break; + } + +@@ -512,7 +508,7 @@ static FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_string ( struct DecoderState *ds + } + + if (ucs < 0x800) return SetError (ds, -1, "Overlong 3 byte UTF-8 sequence detected when encoding string"); +- *(escOffset++) = (wchar_t) ucs; ++ *(escOffset++) = (JSUINT32) ucs; + break; + } + +@@ -536,20 +532,7 @@ static FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_string ( struct DecoderState *ds + + if (ucs < 0x10000) return SetError (ds, -1, "Overlong 4 byte UTF-8 sequence detected when decoding 'string'"); + +-#if WCHAR_MAX == 0xffff +- if (ucs >= 0x10000) +- { +- ucs -= 0x10000; +- *(escOffset++) = (wchar_t) (ucs >> 10) + 0xd800; +- *(escOffset++) = (wchar_t) (ucs & 0x3ff) + 0xdc00; +- } +- else +- { +- *(escOffset++) = (wchar_t) ucs; +- } +-#else +- *(escOffset++) = (wchar_t) ucs; +-#endif ++ *(escOffset++) = (JSUINT32) ucs; + break; + } + } +@@ -760,14 +743,14 @@ JSOBJ JSON_DecodeObject(JSONObjectDecoder *dec, const char *buffer, size_t cbBuf + /* + FIXME: Base the size of escBuffer of that of cbBuffer so that the unicode escaping doesn't run into the wall each time */ + struct DecoderState ds; +- wchar_t escBuffer[(JSON_MAX_STACK_BUFFER_SIZE / sizeof(wchar_t))]; ++ JSUINT32 escBuffer[(JSON_MAX_STACK_BUFFER_SIZE / sizeof(JSUINT32))]; + JSOBJ ret; + + ds.start = (char *) buffer; + ds.end = ds.start + cbBuffer; + + ds.escStart = escBuffer; +- ds.escEnd = ds.escStart + (JSON_MAX_STACK_BUFFER_SIZE / sizeof(wchar_t)); ++ ds.escEnd = ds.escStart + (JSON_MAX_STACK_BUFFER_SIZE / sizeof(JSUINT32)); + ds.escHeap = 0; + ds.prv = dec->prv; + ds.dec = dec; +diff --git a/python/JSONtoObj.c b/python/JSONtoObj.c +index 1c7232b..064f6a0 100644 +--- a/python/JSONtoObj.c ++++ b/python/JSONtoObj.c +@@ -58,9 +58,19 @@ static void Object_arrayAddItem(void *prv, JSOBJ obj, JSOBJ value) + return; + } + +-static JSOBJ Object_newString(void *prv, wchar_t *start, wchar_t *end) ++ ++/* ++Check that Py_UCS4 is the same as JSUINT32, else Object_newString will fail. ++Based on Linux's check in vbox_vmmdev_types.h. ++This should be replaced with ++ _Static_assert(sizeof(Py_UCS4) == sizeof(JSUINT32)); ++when C11 is made mandatory (CPython 3.11+, PyPy ?). ++*/ ++typedef char assert_py_ucs4_is_jsuint32[1 - 2*!(sizeof(Py_UCS4) == sizeof(JSUINT32))]; ++ ++static JSOBJ Object_newString(void *prv, JSUINT32 *start, JSUINT32 *end) + { +- return PyUnicode_FromWideChar (start, (end - start)); ++ return PyUnicode_FromKindAndData (PyUnicode_4BYTE_KIND, (Py_UCS4 *) start, (end - start)); + } + + static JSOBJ Object_newTrue(void *prv) +-- +2.28.0 + diff --git a/ujson.spec b/ujson.spec index 14096a2..0558d15 100644 --- a/ujson.spec +++ b/ujson.spec @@ -2,11 +2,12 @@ %global common_desc UltraJSON is an ultra fast JSON encoder and decoder written in pure C with bindings for Python 3.6+ Name: python-ujson Version: 4.0.2 -Release: 2 +Release: 3 Summary: Ultra fast JSON encoder and decoder for Python License: BSD URL: https://github.com/ultrajson/ultrajson Source0: https://files.pythonhosted.org/packages/86/0a/80d87aa4ee79980bddabef13cb7d95de330f85355cf08dfdaf874889b02b/ujson-4.0.2.tar.gz +Patch: 0001-CVE-2022-31116.patch %description %{common_desc} @@ -77,7 +78,11 @@ mv %{buildroot}/doclist.lst . %{_docdir}/* %changelog +* Wed Aug 03 2022 zhangy - 4.0.2-3 +- Fix CVE-2022-31116 + * Thu Sep 16 2021 wangxiyuan - 4.0.2-2 - Add gcc-c++ build require + * Tue Jul 20 2021 OpenStack_SIG - 4.0.2-1 - Package Spec generate -- Gitee