| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 2dbde5e commit e78178e
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -806,6 +806,39 @@ def test_bug828737(self): | |||
| 806 | 806 | text = 'abc<def>ghi'*n | |
| 807 | 807 | text.translate(charmap) | |
| 808 | 808 | ||
| 809 | + def test_mutatingdecodehandler(self): | ||
| 810 | + baddata = [ | ||
| 811 | + ("ascii", b"\xff"), | ||
| 812 | + ("utf-7", b"++"), | ||
| 813 | + ("utf-8", b"\xff"), | ||
| 814 | + ("utf-16", b"\xff"), | ||
| 815 | + ("unicode-escape", b"\\u123g"), | ||
| 816 | + ("raw-unicode-escape", b"\\u123g"), | ||
| 817 | + ("unicode-internal", b"\xff"), | ||
| 818 | + ] | ||
| 819 | + | ||
| 820 | + def replacing(exc): | ||
| 821 | + if isinstance(exc, UnicodeDecodeError): | ||
| 822 | + exc.object = 42 | ||
| 823 | + return ("\u4242", 0) | ||
| 824 | + else: | ||
| 825 | + raise TypeError("don't know how to handle %r" % exc) | ||
| 826 | + codecs.register_error("test.replacing", replacing) | ||
| 827 | + for (encoding, data) in baddata: | ||
| 828 | + self.assertRaises(TypeError, data.decode, encoding, "test.replacing") | ||
| 829 | + | ||
| 830 | + def mutating(exc): | ||
| 831 | + if isinstance(exc, UnicodeDecodeError): | ||
| 832 | + exc.object[:] = b"" | ||
| 833 | + return ("\u4242", 0) | ||
| 834 | + else: | ||
| 835 | + raise TypeError("don't know how to handle %r" % exc) | ||
| 836 | + codecs.register_error("test.mutating", mutating) | ||
| 837 | + # If the decoder doesn't pick up the modified input the following | ||
| 838 | + # will lead to an endless loop | ||
| 839 | + for (encoding, data) in baddata: | ||
| 840 | + self.assertRaises(TypeError, data.decode, encoding, "test.replacing") | ||
| 841 | + | ||
| 809 | 842 | def test_main(): | |
| 810 | 843 | test.test_support.run_unittest(CodecCallbackTest) | |
| 811 | 844 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1269,17 +1269,19 @@ int PyUnicode_SetDefaultEncoding(const char *encoding) | |||
| 1269 | 1269 | static | |
| 1270 | 1270 | int unicode_decode_call_errorhandler(const char *errors, PyObject **errorHandler, | |
| 1271 | 1271 | const char *encoding, const char *reason, | |
| 1272 | - const char *input, Py_ssize_t insize, Py_ssize_t *startinpos, Py_ssize_t *endinpos, PyObject **exceptionObject, const char **inptr, | ||
| 1272 | + const char **input, const char **inend, Py_ssize_t *startinpos, Py_ssize_t *endinpos, PyObject **exceptionObject, const char **inptr, | ||
| 1273 | 1273 | PyObject **output, Py_ssize_t *outpos, Py_UNICODE **outptr) | |
| 1274 | 1274 | { | |
| 1275 | 1275 | static char *argparse = "O!n;decoding error handler must return (unicode, int) tuple"; | |
| 1276 | 1276 | ||
| 1277 | 1277 | PyObject *restuple = NULL; | |
| 1278 | 1278 | PyObject *repunicode = NULL; | |
| 1279 | 1279 | Py_ssize_t outsize = PyUnicode_GET_SIZE(*output); | |
| 1280 | + Py_ssize_t insize; | ||
| 1280 | 1281 | Py_ssize_t requiredsize; | |
| 1281 | 1282 | Py_ssize_t newpos; | |
| 1282 | 1283 | Py_UNICODE *repptr; | |
| 1284 | + PyObject *inputobj = NULL; | ||
| 1283 | 1285 | Py_ssize_t repsize; | |
| 1284 | 1286 | int res = -1; | |
| 1285 | 1287 | ||
@@ -1291,7 +1293,7 @@ int unicode_decode_call_errorhandler(const char *errors, PyObject **errorHandler | |||
| 1291 | 1293 | ||
| 1292 | 1294 | if (*exceptionObject == NULL) { | |
| 1293 | 1295 | *exceptionObject = PyUnicodeDecodeError_Create( | |
| 1294 | - encoding, input, insize, *startinpos, *endinpos, reason); | ||
| 1296 | + encoding, *input, *inend-*input, *startinpos, *endinpos, reason); | ||
| 1295 | 1297 | if (*exceptionObject == NULL) | |
| 1296 | 1298 | goto onError; | |
| 1297 | 1299 | } | |
@@ -1313,6 +1315,19 @@ int unicode_decode_call_errorhandler(const char *errors, PyObject **errorHandler | |||
| 1313 | 1315 | } | |
| 1314 | 1316 | if (!PyArg_ParseTuple(restuple, argparse, &PyUnicode_Type, &repunicode, &newpos)) | |
| 1315 | 1317 | goto onError; | |
| 1318 | + | ||
| 1319 | + /* Copy back the bytes variables, which might have been modified by the | ||
| 1320 | + callback */ | ||
| 1321 | + inputobj = PyUnicodeDecodeError_GetObject(*exceptionObject); | ||
| 1322 | + if (!inputobj) | ||
| 1323 | + goto onError; | ||
| 1324 | + if (!PyBytes_Check(inputobj)) { | ||
| 1325 | + PyErr_Format(PyExc_TypeError, "exception attribute object must be bytes"); | ||
| 1326 | + } | ||
| 1327 | + *input = PyBytes_AS_STRING(inputobj); | ||
| 1328 | + insize = PyBytes_GET_SIZE(inputobj); | ||
| 1329 | + *inend = *input + insize; | ||
| 1330 | + | ||
| 1316 | 1331 | if (newpos<0) | |
| 1317 | 1332 | newpos = insize+newpos; | |
| 1318 | 1333 | if (newpos<0 || newpos>insize) { | |
@@ -1335,10 +1350,11 @@ int unicode_decode_call_errorhandler(const char *errors, PyObject **errorHandler | |||
| 1335 | 1350 | *outptr = PyUnicode_AS_UNICODE(*output) + *outpos; | |
| 1336 | 1351 | } | |
| 1337 | 1352 | *endinpos = newpos; | |
| 1338 | - *inptr = input + newpos; | ||
| 1353 | + *inptr = *input + newpos; | ||
| 1339 | 1354 | Py_UNICODE_COPY(*outptr, repptr, repsize); | |
| 1340 | 1355 | *outptr += repsize; | |
| 1341 | 1356 | *outpos += repsize; | |
| 1357 | + | ||
| 1342 | 1358 | /* we made it! */ | |
| 1343 | 1359 | res = 0; | |
| 1344 | 1360 | ||
@@ -1503,7 +1519,7 @@ PyObject *PyUnicode_DecodeUTF7(const char *s, | |||
| 1503 | 1519 | else if (SPECIAL(ch,0,0)) { | |
| 1504 | 1520 | errmsg = "unexpected special character"; | |
| 1505 | 1521 | s++; | |
| 1506 | - goto utf7Error; | ||
| 1522 | + goto utf7Error; | ||
| 1507 | 1523 | } | |
| 1508 | 1524 | else { | |
| 1509 | 1525 | *p++ = ch; | |
@@ -1516,7 +1532,7 @@ PyObject *PyUnicode_DecodeUTF7(const char *s, | |||
| 1516 | 1532 | if (unicode_decode_call_errorhandler( | |
| 1517 | 1533 | errors, &errorHandler, | |
| 1518 | 1534 | "utf7", errmsg, | |
| 1519 | - starts, size, &startinpos, &endinpos, &exc, &s, | ||
| 1535 | + &starts, &e, &startinpos, &endinpos, &exc, &s, | ||
| 1520 | 1536 | (PyObject **)&unicode, &outpos, &p)) | |
| 1521 | 1537 | goto onError; | |
| 1522 | 1538 | } | |
@@ -1527,7 +1543,7 @@ PyObject *PyUnicode_DecodeUTF7(const char *s, | |||
| 1527 | 1543 | if (unicode_decode_call_errorhandler( | |
| 1528 | 1544 | errors, &errorHandler, | |
| 1529 | 1545 | "utf7", "unterminated shift sequence", | |
| 1530 | - starts, size, &startinpos, &endinpos, &exc, &s, | ||
| 1546 | + &starts, &e, &startinpos, &endinpos, &exc, &s, | ||
| 1531 | 1547 | (PyObject **)&unicode, &outpos, &p)) | |
| 1532 | 1548 | goto onError; | |
| 1533 | 1549 | if (s < e) | |
@@ -1848,7 +1864,7 @@ PyObject *PyUnicode_DecodeUTF8Stateful(const char *s, | |||
| 1848 | 1864 | if (unicode_decode_call_errorhandler( | |
| 1849 | 1865 | errors, &errorHandler, | |
| 1850 | 1866 | "utf8", errmsg, | |
| 1851 | - starts, size, &startinpos, &endinpos, &exc, &s, | ||
| 1867 | + &starts, &e, &startinpos, &endinpos, &exc, &s, | ||
| 1852 | 1868 | (PyObject **)&unicode, &outpos, &p)) | |
| 1853 | 1869 | goto onError; | |
| 1854 | 1870 | } | |
@@ -2132,7 +2148,7 @@ PyUnicode_DecodeUTF16Stateful(const char *s, | |||
| 2132 | 2148 | if (unicode_decode_call_errorhandler( | |
| 2133 | 2149 | errors, &errorHandler, | |
| 2134 | 2150 | "utf16", errmsg, | |
| 2135 | - starts, size, &startinpos, &endinpos, &exc, (const char **)&q, | ||
| 2151 | + &starts, (const char **)&e, &startinpos, &endinpos, &exc, (const char **)&q, | ||
| 2136 | 2152 | (PyObject **)&unicode, &outpos, &p)) | |
| 2137 | 2153 | goto onError; | |
| 2138 | 2154 | } | |
@@ -2342,7 +2358,7 @@ PyObject *PyUnicode_DecodeUnicodeEscape(const char *s, | |||
| 2342 | 2358 | if (unicode_decode_call_errorhandler( | |
| 2343 | 2359 | errors, &errorHandler, | |
| 2344 | 2360 | "unicodeescape", "end of string in escape sequence", | |
| 2345 | - starts, size, &startinpos, &endinpos, &exc, &s, | ||
| 2361 | + &starts, &end, &startinpos, &endinpos, &exc, &s, | ||
| 2346 | 2362 | (PyObject **)&v, &outpos, &p)) | |
| 2347 | 2363 | goto onError; | |
| 2348 | 2364 | goto nextByte; | |
@@ -2354,7 +2370,7 @@ PyObject *PyUnicode_DecodeUnicodeEscape(const char *s, | |||
| 2354 | 2370 | if (unicode_decode_call_errorhandler( | |
| 2355 | 2371 | errors, &errorHandler, | |
| 2356 | 2372 | "unicodeescape", message, | |
| 2357 | - starts, size, &startinpos, &endinpos, &exc, &s, | ||
| 2373 | + &starts, &end, &startinpos, &endinpos, &exc, &s, | ||
| 2358 | 2374 | (PyObject **)&v, &outpos, &p)) | |
| 2359 | 2375 | goto onError; | |
| 2360 | 2376 | goto nextByte; | |
@@ -2393,7 +2409,7 @@ PyObject *PyUnicode_DecodeUnicodeEscape(const char *s, | |||
| 2393 | 2409 | if (unicode_decode_call_errorhandler( | |
| 2394 | 2410 | errors, &errorHandler, | |
| 2395 | 2411 | "unicodeescape", "illegal Unicode character", | |
| 2396 | - starts, size, &startinpos, &endinpos, &exc, &s, | ||
| 2412 | + &starts, &end, &startinpos, &endinpos, &exc, &s, | ||
| 2397 | 2413 | (PyObject **)&v, &outpos, &p)) | |
| 2398 | 2414 | goto onError; | |
| 2399 | 2415 | } | |
@@ -2435,7 +2451,7 @@ PyObject *PyUnicode_DecodeUnicodeEscape(const char *s, | |||
| 2435 | 2451 | if (unicode_decode_call_errorhandler( | |
| 2436 | 2452 | errors, &errorHandler, | |
| 2437 | 2453 | "unicodeescape", message, | |
| 2438 | - starts, size, &startinpos, &endinpos, &exc, &s, | ||
| 2454 | + &starts, &end, &startinpos, &endinpos, &exc, &s, | ||
| 2439 | 2455 | (PyObject **)&v, &outpos, &p)) | |
| 2440 | 2456 | goto onError; | |
| 2441 | 2457 | break; | |
@@ -2449,7 +2465,7 @@ PyObject *PyUnicode_DecodeUnicodeEscape(const char *s, | |||
| 2449 | 2465 | if (unicode_decode_call_errorhandler( | |
| 2450 | 2466 | errors, &errorHandler, | |
| 2451 | 2467 | "unicodeescape", message, | |
| 2452 | - starts, size, &startinpos, &endinpos, &exc, &s, | ||
| 2468 | + &starts, &end, &startinpos, &endinpos, &exc, &s, | ||
| 2453 | 2469 | (PyObject **)&v, &outpos, &p)) | |
| 2454 | 2470 | goto onError; | |
| 2455 | 2471 | } | |
@@ -2728,7 +2744,7 @@ PyObject *PyUnicode_DecodeRawUnicodeEscape(const char *s, | |||
| 2728 | 2744 | if (unicode_decode_call_errorhandler( | |
| 2729 | 2745 | errors, &errorHandler, | |
| 2730 | 2746 | "rawunicodeescape", "truncated \\uXXXX", | |
| 2731 | - starts, size, &startinpos, &endinpos, &exc, &s, | ||
| 2747 | + &starts, &end, &startinpos, &endinpos, &exc, &s, | ||
| 2732 | 2748 | (PyObject **)&v, &outpos, &p)) | |
| 2733 | 2749 | goto onError; | |
| 2734 | 2750 | goto nextByte; | |
@@ -2746,7 +2762,7 @@ PyObject *PyUnicode_DecodeRawUnicodeEscape(const char *s, | |||
| 2746 | 2762 | if (unicode_decode_call_errorhandler( | |
| 2747 | 2763 | errors, &errorHandler, | |
| 2748 | 2764 | "rawunicodeescape", "\\Uxxxxxxxx out of range", | |
| 2749 | - starts, size, &startinpos, &endinpos, &exc, &s, | ||
| 2765 | + &starts, &end, &startinpos, &endinpos, &exc, &s, | ||
| 2750 | 2766 | (PyObject **)&v, &outpos, &p)) | |
| 2751 | 2767 | goto onError; | |
| 2752 | 2768 | } | |
@@ -2897,7 +2913,7 @@ PyObject *_PyUnicode_DecodeUnicodeInternal(const char *s, | |||
| 2897 | 2913 | if (unicode_decode_call_errorhandler( | |
| 2898 | 2914 | errors, &errorHandler, | |
| 2899 | 2915 | "unicode_internal", reason, | |
| 2900 | - starts, size, &startinpos, &endinpos, &exc, &s, | ||
| 2916 | + &starts, &end, &startinpos, &endinpos, &exc, &s, | ||
| 2901 | 2917 | (PyObject **)&v, &outpos, &p)) { | |
| 2902 | 2918 | goto onError; | |
| 2903 | 2919 | } | |
@@ -3277,7 +3293,7 @@ PyObject *PyUnicode_DecodeASCII(const char *s, | |||
| 3277 | 3293 | if (unicode_decode_call_errorhandler( | |
| 3278 | 3294 | errors, &errorHandler, | |
| 3279 | 3295 | "ascii", "ordinal not in range(128)", | |
| 3280 | - starts, size, &startinpos, &endinpos, &exc, &s, | ||
| 3296 | + &starts, &e, &startinpos, &endinpos, &exc, &s, | ||
| 3281 | 3297 | (PyObject **)&v, &outpos, &p)) | |
| 3282 | 3298 | goto onError; | |
| 3283 | 3299 | } | |
@@ -3578,7 +3594,7 @@ PyObject *PyUnicode_DecodeCharmap(const char *s, | |||
| 3578 | 3594 | if (unicode_decode_call_errorhandler( | |
| 3579 | 3595 | errors, &errorHandler, | |
| 3580 | 3596 | "charmap", "character maps to <undefined>", | |
| 3581 | - starts, size, &startinpos, &endinpos, &exc, &s, | ||
| 3597 | + &starts, &e, &startinpos, &endinpos, &exc, &s, | ||
| 3582 | 3598 | (PyObject **)&v, &outpos, &p)) { | |
| 3583 | 3599 | goto onError; | |
| 3584 | 3600 | } | |
@@ -3628,7 +3644,7 @@ PyObject *PyUnicode_DecodeCharmap(const char *s, | |||
| 3628 | 3644 | if (unicode_decode_call_errorhandler( | |
| 3629 | 3645 | errors, &errorHandler, | |
| 3630 | 3646 | "charmap", "character maps to <undefined>", | |
| 3631 | - starts, size, &startinpos, &endinpos, &exc, &s, | ||
| 3647 | + &starts, &e, &startinpos, &endinpos, &exc, &s, | ||
| 3632 | 3648 | (PyObject **)&v, &outpos, &p)) { | |
| 3633 | 3649 | Py_DECREF(x); | |
| 3634 | 3650 | goto onError; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments