Moderate severityNVD Advisory· Published Jul 2, 2010· Updated Apr 29, 2026
CVE-2010-1666
CVE-2010-1666
Description
Buffer overflow in Dan Pascu python-cjson 1.0.5, when UCS-4 encoding is enabled, allows context-dependent attackers to cause a denial of service (application crash) or possibly have unspecified other impact via vectors involving crafted Unicode input to the cjson.encode function.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
python-cjsonPyPI | < 1.0.5.1 | 1.0.5.1 |
Affected products
1- cpe:2.3:a:dan_pascu:python-cjson:1.0.5:*:*:*:*:*:*:*
Patches
1dc2b8781b866Integrate modified 0001-fix-for-CVE-2010-1666 patch from Debian
2 files changed · +33 −11
cjson.c+21 −11 modified@@ -663,17 +663,36 @@ encode_unicode(PyObject *unicode) char *p; static const char *hexdigit = "0123456789abcdef"; +#ifdef Py_UNICODE_WIDE + const Py_ssize_t expandsize = 10; +#else + const Py_ssize_t expandsize = 6; +#endif + + /* Initial allocation is based on the longest-possible unichr + escape. + + In wide (UTF-32) builds '\U00xxxxxx' is 10 chars per source + unichr, so in this case it's the longest unichr escape. In + narrow (UTF-16) builds this is five chars per source unichr + since there are two unichrs in the surrogate pair, so in narrow + (UTF-16) builds it's not the longest unichr escape. + + In wide or narrow builds '\uxxxx' is 6 chars per source unichr, + so in the narrow (UTF-16) build case it's the longest unichr + escape. + */ s = PyUnicode_AS_UNICODE(unicode); size = PyUnicode_GET_SIZE(unicode); - if (size > (PY_SSIZE_T_MAX-2-1)/6) { + if (size > (PY_SSIZE_T_MAX-2-1)/expandsize) { PyErr_SetString(PyExc_OverflowError, "unicode object is too large to make repr"); return NULL; } - repr = PyString_FromStringAndSize(NULL, 2 + 6*size + 1); + repr = PyString_FromStringAndSize(NULL, 2 + expandsize*size + 1); if (repr == NULL) return NULL; @@ -694,15 +713,6 @@ encode_unicode(PyObject *unicode) #ifdef Py_UNICODE_WIDE /* Map 21-bit characters to '\U00xxxxxx' */ else if (ch >= 0x10000) { - int offset = p - PyString_AS_STRING(repr); - - /* Resize the string if necessary */ - if (offset + 12 > PyString_GET_SIZE(repr)) { - if (_PyString_Resize(&repr, PyString_GET_SIZE(repr) + 100)) - return NULL; - p = PyString_AS_STRING(repr) + offset; - } - *p++ = '\\'; *p++ = 'U'; *p++ = hexdigit[(ch >> 28) & 0x0000000F];
jsontest.py+12 −0 modified@@ -317,6 +317,18 @@ def testObjectWithNonEmptyList(self): def testWriteLong(self): self.assertEqual("12345678901234567890", cjson.encode(12345678901234567890)) + + def testWriteLongUnicode(self): + # This test causes a buffer overrun in cjson 1.0.5, on UCS4 builds. + # The string length is only resized for wide unicode characters if + # there is less than 12 bytes of space left. Padding with + # narrow-but-escaped characters prevents string resizing. + # Note that u'\U0001D11E\u1234' also breaks, but sometimes goes + # undetected. + s = cjson.encode(u'\U0001D11E\U0001D11E\U0001D11E\U0001D11E' + u'\u1234\u1234\u1234\u1234\u1234\u1234') + self.assertEqual(r'"\U0001d11e\U0001d11e\U0001d11e\U0001d11e' + r'\u1234\u1234\u1234\u1234\u1234\u1234"', s) def main(): unittest.main()
Vulnerability mechanics
Synthesis attempt was rejected by the grounding validator. Re-run pending.
References
9- secunia.com/advisories/40335nvdVendor Advisory
- github.com/advisories/GHSA-cqmh-mpx2-g633ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2010-1666ghsaADVISORY
- www.debian.org/security/2010/dsa-2068nvdWEB
- bugs.launchpad.net/ubuntu/+source/python-cjson/+bug/585274nvdWEB
- github.com/AGProjects/python-cjson/commit/dc2b8781b8666de5ca707318521f554904fdd690ghsaWEB
- github.com/pypa/advisory-database/tree/main/vulns/python-cjson/PYSEC-2010-30.yamlghsaWEB
- secunia.com/advisories/40500nvd
- www.vupen.com/english/advisories/2010/1774nvd
News mentions
0No linked articles in our index yet.