Branch data Line data Source code
1 : : /* ------------------------------------------------------------------------
2 : :
3 : : Python Codec Registry and support functions
4 : :
5 : : Written by Marc-Andre Lemburg (mal@lemburg.com).
6 : :
7 : : Copyright (c) Corporation for National Research Initiatives.
8 : :
9 : : ------------------------------------------------------------------------ */
10 : :
11 : : #include "Python.h"
12 : : #include "pycore_call.h" // _PyObject_CallNoArgs()
13 : : #include "pycore_interp.h" // PyInterpreterState.codec_search_path
14 : : #include "pycore_pystate.h" // _PyInterpreterState_GET()
15 : : #include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI
16 : : #include <ctype.h>
17 : :
18 : : const char *Py_hexdigits = "0123456789abcdef";
19 : :
20 : : /* --- Codec Registry ----------------------------------------------------- */
21 : :
22 : : /* Import the standard encodings package which will register the first
23 : : codec search function.
24 : :
25 : : This is done in a lazy way so that the Unicode implementation does
26 : : not downgrade startup time of scripts not needing it.
27 : :
28 : : ImportErrors are silently ignored by this function. Only one try is
29 : : made.
30 : :
31 : : */
32 : :
33 : : static int _PyCodecRegistry_Init(void); /* Forward */
34 : :
35 : 3416 : int PyCodec_Register(PyObject *search_function)
36 : : {
37 : 3416 : PyInterpreterState *interp = _PyInterpreterState_GET();
38 [ - + - - ]: 3416 : if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
39 : 0 : goto onError;
40 [ - + ]: 3416 : if (search_function == NULL) {
41 : 0 : PyErr_BadArgument();
42 : 0 : goto onError;
43 : : }
44 [ + + ]: 3416 : if (!PyCallable_Check(search_function)) {
45 : 1 : PyErr_SetString(PyExc_TypeError, "argument must be callable");
46 : 1 : goto onError;
47 : : }
48 : 3415 : return PyList_Append(interp->codec_search_path, search_function);
49 : :
50 : 1 : onError:
51 : 1 : return -1;
52 : : }
53 : :
54 : : int
55 : 280 : PyCodec_Unregister(PyObject *search_function)
56 : : {
57 : 280 : PyInterpreterState *interp = PyInterpreterState_Get();
58 : 280 : PyObject *codec_search_path = interp->codec_search_path;
59 : : /* Do nothing if codec_search_path is not created yet or was cleared. */
60 [ - + ]: 280 : if (codec_search_path == NULL) {
61 : 0 : return 0;
62 : : }
63 : :
64 : : assert(PyList_CheckExact(codec_search_path));
65 : 280 : Py_ssize_t n = PyList_GET_SIZE(codec_search_path);
66 [ + - ]: 560 : for (Py_ssize_t i = 0; i < n; i++) {
67 : 560 : PyObject *item = PyList_GET_ITEM(codec_search_path, i);
68 [ + + ]: 560 : if (item == search_function) {
69 [ + - ]: 280 : if (interp->codec_search_cache != NULL) {
70 : : assert(PyDict_CheckExact(interp->codec_search_cache));
71 : 280 : PyDict_Clear(interp->codec_search_cache);
72 : : }
73 : 280 : return PyList_SetSlice(codec_search_path, i, i+1, NULL);
74 : : }
75 : : }
76 : 0 : return 0;
77 : : }
78 : :
79 : : extern int _Py_normalize_encoding(const char *, char *, size_t);
80 : :
81 : : /* Convert a string to a normalized Python string(decoded from UTF-8): all characters are
82 : : converted to lower case, spaces and hyphens are replaced with underscores. */
83 : :
84 : : static
85 : 1582476 : PyObject *normalizestring(const char *string)
86 : : {
87 : 1582476 : size_t len = strlen(string);
88 : : char *encoding;
89 : : PyObject *v;
90 : :
91 [ - + ]: 1582476 : if (len > PY_SSIZE_T_MAX) {
92 : 0 : PyErr_SetString(PyExc_OverflowError, "string is too large");
93 : 0 : return NULL;
94 : : }
95 : :
96 : 1582476 : encoding = PyMem_Malloc(len + 1);
97 [ - + ]: 1582476 : if (encoding == NULL)
98 : : return PyErr_NoMemory();
99 : :
100 [ - + ]: 1582476 : if (!_Py_normalize_encoding(string, encoding, len + 1))
101 : : {
102 : 0 : PyErr_SetString(PyExc_RuntimeError, "_Py_normalize_encoding() failed");
103 : 0 : PyMem_Free(encoding);
104 : 0 : return NULL;
105 : : }
106 : :
107 : 1582476 : v = PyUnicode_FromString(encoding);
108 : 1582476 : PyMem_Free(encoding);
109 : 1582476 : return v;
110 : : }
111 : :
112 : : /* Lookup the given encoding and return a tuple providing the codec
113 : : facilities.
114 : :
115 : : The encoding string is looked up converted to all lower-case
116 : : characters. This makes encodings looked up through this mechanism
117 : : effectively case-insensitive.
118 : :
119 : : If no codec is found, a LookupError is set and NULL returned.
120 : :
121 : : As side effect, this tries to load the encodings package, if not
122 : : yet done. This is part of the lazy load strategy for the encodings
123 : : package.
124 : :
125 : : */
126 : :
127 : 1582476 : PyObject *_PyCodec_Lookup(const char *encoding)
128 : : {
129 [ - + ]: 1582476 : if (encoding == NULL) {
130 : 0 : PyErr_BadArgument();
131 : 0 : return NULL;
132 : : }
133 : :
134 : 1582476 : PyInterpreterState *interp = _PyInterpreterState_GET();
135 [ + + - + ]: 1582476 : if (interp->codec_search_path == NULL && _PyCodecRegistry_Init()) {
136 : 0 : return NULL;
137 : : }
138 : :
139 : : /* Convert the encoding to a normalized Python string: all
140 : : characters are converted to lower case, spaces and hyphens are
141 : : replaced with underscores. */
142 : 1582476 : PyObject *v = normalizestring(encoding);
143 [ - + ]: 1582476 : if (v == NULL) {
144 : 0 : return NULL;
145 : : }
146 : 1582476 : PyUnicode_InternInPlace(&v);
147 : :
148 : : /* First, try to lookup the name in the registry dictionary */
149 : 1582476 : PyObject *result = PyDict_GetItemWithError(interp->codec_search_cache, v);
150 [ + + ]: 1582476 : if (result != NULL) {
151 : 1577853 : Py_INCREF(result);
152 : 1577853 : Py_DECREF(v);
153 : 1577853 : return result;
154 : : }
155 [ - + ]: 4623 : else if (PyErr_Occurred()) {
156 : 0 : goto onError;
157 : : }
158 : :
159 : : /* Next, scan the search functions in order of registration */
160 : 4623 : const Py_ssize_t len = PyList_Size(interp->codec_search_path);
161 [ - + ]: 4623 : if (len < 0)
162 : 0 : goto onError;
163 [ - + ]: 4623 : if (len == 0) {
164 : 0 : PyErr_SetString(PyExc_LookupError,
165 : : "no codec search functions registered: "
166 : : "can't find encoding");
167 : 0 : goto onError;
168 : : }
169 : :
170 : : Py_ssize_t i;
171 [ + + ]: 4714 : for (i = 0; i < len; i++) {
172 : : PyObject *func;
173 : :
174 : 4652 : func = PyList_GetItem(interp->codec_search_path, i);
175 [ - + ]: 4652 : if (func == NULL)
176 : 0 : goto onError;
177 : 4652 : result = PyObject_CallOneArg(func, v);
178 [ - + ]: 4652 : if (result == NULL)
179 : 0 : goto onError;
180 [ + + ]: 4652 : if (result == Py_None) {
181 : 91 : Py_DECREF(result);
182 : 91 : continue;
183 : : }
184 [ + + - + ]: 4561 : if (!PyTuple_Check(result) || PyTuple_GET_SIZE(result) != 4) {
185 : 1 : PyErr_SetString(PyExc_TypeError,
186 : : "codec search functions must return 4-tuples");
187 : 1 : Py_DECREF(result);
188 : 1 : goto onError;
189 : : }
190 : 4560 : break;
191 : : }
192 [ + + ]: 4622 : if (i == len) {
193 : : /* XXX Perhaps we should cache misses too ? */
194 : 62 : PyErr_Format(PyExc_LookupError,
195 : : "unknown encoding: %s", encoding);
196 : 62 : goto onError;
197 : : }
198 : :
199 : : /* Cache and return the result */
200 [ - + ]: 4560 : if (PyDict_SetItem(interp->codec_search_cache, v, result) < 0) {
201 : 0 : Py_DECREF(result);
202 : 0 : goto onError;
203 : : }
204 : 4560 : Py_DECREF(v);
205 : 4560 : return result;
206 : :
207 : 63 : onError:
208 : 63 : Py_DECREF(v);
209 : 63 : return NULL;
210 : : }
211 : :
212 : : /* Codec registry encoding check API. */
213 : :
214 : 0 : int PyCodec_KnownEncoding(const char *encoding)
215 : : {
216 : : PyObject *codecs;
217 : :
218 : 0 : codecs = _PyCodec_Lookup(encoding);
219 [ # # ]: 0 : if (!codecs) {
220 : 0 : PyErr_Clear();
221 : 0 : return 0;
222 : : }
223 : : else {
224 : 0 : Py_DECREF(codecs);
225 : 0 : return 1;
226 : : }
227 : : }
228 : :
229 : : static
230 : 1515204 : PyObject *args_tuple(PyObject *object,
231 : : const char *errors)
232 : : {
233 : : PyObject *args;
234 : :
235 [ + + ]: 1515204 : args = PyTuple_New(1 + (errors != NULL));
236 [ - + ]: 1515204 : if (args == NULL)
237 : 0 : return NULL;
238 : 1515204 : Py_INCREF(object);
239 : 1515204 : PyTuple_SET_ITEM(args,0,object);
240 [ + + ]: 1515204 : if (errors) {
241 : : PyObject *v;
242 : :
243 : 1049268 : v = PyUnicode_FromString(errors);
244 [ - + ]: 1049268 : if (v == NULL) {
245 : 0 : Py_DECREF(args);
246 : 0 : return NULL;
247 : : }
248 : 1049268 : PyTuple_SET_ITEM(args, 1, v);
249 : : }
250 : 1515204 : return args;
251 : : }
252 : :
253 : : /* Helper function to get a codec item */
254 : :
255 : : static
256 : 10028 : PyObject *codec_getitem(const char *encoding, int index)
257 : : {
258 : : PyObject *codecs;
259 : : PyObject *v;
260 : :
261 : 10028 : codecs = _PyCodec_Lookup(encoding);
262 [ + + ]: 10028 : if (codecs == NULL)
263 : 3 : return NULL;
264 : 10025 : v = PyTuple_GET_ITEM(codecs, index);
265 : 10025 : Py_DECREF(codecs);
266 : 10025 : Py_INCREF(v);
267 : 10025 : return v;
268 : : }
269 : :
270 : : /* Helper functions to create an incremental codec. */
271 : : static
272 : 40494 : PyObject *codec_makeincrementalcodec(PyObject *codec_info,
273 : : const char *errors,
274 : : const char *attrname)
275 : : {
276 : : PyObject *ret, *inccodec;
277 : :
278 : 40494 : inccodec = PyObject_GetAttrString(codec_info, attrname);
279 [ - + ]: 40494 : if (inccodec == NULL)
280 : 0 : return NULL;
281 [ + + ]: 40494 : if (errors)
282 : 40294 : ret = PyObject_CallFunction(inccodec, "s", errors);
283 : : else
284 : 200 : ret = _PyObject_CallNoArgs(inccodec);
285 : 40494 : Py_DECREF(inccodec);
286 : 40494 : return ret;
287 : : }
288 : :
289 : : static
290 : 398 : PyObject *codec_getincrementalcodec(const char *encoding,
291 : : const char *errors,
292 : : const char *attrname)
293 : : {
294 : : PyObject *codec_info, *ret;
295 : :
296 : 398 : codec_info = _PyCodec_Lookup(encoding);
297 [ - + ]: 398 : if (codec_info == NULL)
298 : 0 : return NULL;
299 : 398 : ret = codec_makeincrementalcodec(codec_info, errors, attrname);
300 : 398 : Py_DECREF(codec_info);
301 : 398 : return ret;
302 : : }
303 : :
304 : : /* Helper function to create a stream codec. */
305 : :
306 : : static
307 : 0 : PyObject *codec_getstreamcodec(const char *encoding,
308 : : PyObject *stream,
309 : : const char *errors,
310 : : const int index)
311 : : {
312 : : PyObject *codecs, *streamcodec, *codeccls;
313 : :
314 : 0 : codecs = _PyCodec_Lookup(encoding);
315 [ # # ]: 0 : if (codecs == NULL)
316 : 0 : return NULL;
317 : :
318 : 0 : codeccls = PyTuple_GET_ITEM(codecs, index);
319 [ # # ]: 0 : if (errors != NULL)
320 : 0 : streamcodec = PyObject_CallFunction(codeccls, "Os", stream, errors);
321 : : else
322 : 0 : streamcodec = PyObject_CallOneArg(codeccls, stream);
323 : 0 : Py_DECREF(codecs);
324 : 0 : return streamcodec;
325 : : }
326 : :
327 : : /* Helpers to work with the result of _PyCodec_Lookup
328 : :
329 : : */
330 : 15624 : PyObject *_PyCodecInfo_GetIncrementalDecoder(PyObject *codec_info,
331 : : const char *errors)
332 : : {
333 : 15624 : return codec_makeincrementalcodec(codec_info, errors,
334 : : "incrementaldecoder");
335 : : }
336 : :
337 : 24472 : PyObject *_PyCodecInfo_GetIncrementalEncoder(PyObject *codec_info,
338 : : const char *errors)
339 : : {
340 : 24472 : return codec_makeincrementalcodec(codec_info, errors,
341 : : "incrementalencoder");
342 : : }
343 : :
344 : :
345 : : /* Convenience APIs to query the Codec registry.
346 : :
347 : : All APIs return a codec object with incremented refcount.
348 : :
349 : : */
350 : :
351 : 9987 : PyObject *PyCodec_Encoder(const char *encoding)
352 : : {
353 : 9987 : return codec_getitem(encoding, 0);
354 : : }
355 : :
356 : 41 : PyObject *PyCodec_Decoder(const char *encoding)
357 : : {
358 : 41 : return codec_getitem(encoding, 1);
359 : : }
360 : :
361 : 199 : PyObject *PyCodec_IncrementalEncoder(const char *encoding,
362 : : const char *errors)
363 : : {
364 : 199 : return codec_getincrementalcodec(encoding, errors, "incrementalencoder");
365 : : }
366 : :
367 : 199 : PyObject *PyCodec_IncrementalDecoder(const char *encoding,
368 : : const char *errors)
369 : : {
370 : 199 : return codec_getincrementalcodec(encoding, errors, "incrementaldecoder");
371 : : }
372 : :
373 : 0 : PyObject *PyCodec_StreamReader(const char *encoding,
374 : : PyObject *stream,
375 : : const char *errors)
376 : : {
377 : 0 : return codec_getstreamcodec(encoding, stream, errors, 2);
378 : : }
379 : :
380 : 0 : PyObject *PyCodec_StreamWriter(const char *encoding,
381 : : PyObject *stream,
382 : : const char *errors)
383 : : {
384 : 0 : return codec_getstreamcodec(encoding, stream, errors, 3);
385 : : }
386 : :
387 : : /* Helper that tries to ensure the reported exception chain indicates the
388 : : * codec that was invoked to trigger the failure without changing the type
389 : : * of the exception raised.
390 : : */
391 : : static void
392 : 141 : wrap_codec_error(const char *operation,
393 : : const char *encoding)
394 : : {
395 : : /* TrySetFromCause will replace the active exception with a suitably
396 : : * updated clone if it can, otherwise it will leave the original
397 : : * exception alone.
398 : : */
399 : 141 : _PyErr_TrySetFromCause("%s with '%s' codec failed",
400 : : operation, encoding);
401 : 141 : }
402 : :
403 : : /* Encode an object (e.g. a Unicode object) using the given encoding
404 : : and return the resulting encoded object (usually a Python string).
405 : :
406 : : errors is passed to the encoder factory as argument if non-NULL. */
407 : :
408 : : static PyObject *
409 : 1269846 : _PyCodec_EncodeInternal(PyObject *object,
410 : : PyObject *encoder,
411 : : const char *encoding,
412 : : const char *errors)
413 : : {
414 : 1269846 : PyObject *args = NULL, *result = NULL;
415 : 1269846 : PyObject *v = NULL;
416 : :
417 : 1269846 : args = args_tuple(object, errors);
418 [ - + ]: 1269846 : if (args == NULL)
419 : 0 : goto onError;
420 : :
421 : 1269846 : result = PyObject_Call(encoder, args, NULL);
422 [ + + ]: 1269846 : if (result == NULL) {
423 : 63 : wrap_codec_error("encoding", encoding);
424 : 63 : goto onError;
425 : : }
426 : :
427 [ + + - + ]: 2539565 : if (!PyTuple_Check(result) ||
428 : 1269782 : PyTuple_GET_SIZE(result) != 2) {
429 : 1 : PyErr_SetString(PyExc_TypeError,
430 : : "encoder must return a tuple (object, integer)");
431 : 1 : goto onError;
432 : : }
433 : 1269782 : v = PyTuple_GET_ITEM(result,0);
434 : 1269782 : Py_INCREF(v);
435 : : /* We don't check or use the second (integer) entry. */
436 : :
437 : 1269782 : Py_DECREF(args);
438 : 1269782 : Py_DECREF(encoder);
439 : 1269782 : Py_DECREF(result);
440 : 1269782 : return v;
441 : :
442 : 64 : onError:
443 : 64 : Py_XDECREF(result);
444 : 64 : Py_XDECREF(args);
445 : 64 : Py_XDECREF(encoder);
446 : 64 : return NULL;
447 : : }
448 : :
449 : : /* Decode an object (usually a Python string) using the given encoding
450 : : and return an equivalent object (e.g. a Unicode object).
451 : :
452 : : errors is passed to the decoder factory as argument if non-NULL. */
453 : :
454 : : static PyObject *
455 : 245358 : _PyCodec_DecodeInternal(PyObject *object,
456 : : PyObject *decoder,
457 : : const char *encoding,
458 : : const char *errors)
459 : : {
460 : 245358 : PyObject *args = NULL, *result = NULL;
461 : : PyObject *v;
462 : :
463 : 245358 : args = args_tuple(object, errors);
464 [ - + ]: 245358 : if (args == NULL)
465 : 0 : goto onError;
466 : :
467 : 245358 : result = PyObject_Call(decoder, args, NULL);
468 [ + + ]: 245358 : if (result == NULL) {
469 : 78 : wrap_codec_error("decoding", encoding);
470 : 78 : goto onError;
471 : : }
472 [ + + - + ]: 490559 : if (!PyTuple_Check(result) ||
473 : 245279 : PyTuple_GET_SIZE(result) != 2) {
474 : 1 : PyErr_SetString(PyExc_TypeError,
475 : : "decoder must return a tuple (object,integer)");
476 : 1 : goto onError;
477 : : }
478 : 245279 : v = PyTuple_GET_ITEM(result,0);
479 : 245279 : Py_INCREF(v);
480 : : /* We don't check or use the second (integer) entry. */
481 : :
482 : 245279 : Py_DECREF(args);
483 : 245279 : Py_DECREF(decoder);
484 : 245279 : Py_DECREF(result);
485 : 245279 : return v;
486 : :
487 : 79 : onError:
488 : 79 : Py_XDECREF(args);
489 : 79 : Py_XDECREF(decoder);
490 : 79 : Py_XDECREF(result);
491 : 79 : return NULL;
492 : : }
493 : :
494 : : /* Generic encoding/decoding API */
495 : 9987 : PyObject *PyCodec_Encode(PyObject *object,
496 : : const char *encoding,
497 : : const char *errors)
498 : : {
499 : : PyObject *encoder;
500 : :
501 : 9987 : encoder = PyCodec_Encoder(encoding);
502 [ + + ]: 9987 : if (encoder == NULL)
503 : 2 : return NULL;
504 : :
505 : 9985 : return _PyCodec_EncodeInternal(object, encoder, encoding, errors);
506 : : }
507 : :
508 : 41 : PyObject *PyCodec_Decode(PyObject *object,
509 : : const char *encoding,
510 : : const char *errors)
511 : : {
512 : : PyObject *decoder;
513 : :
514 : 41 : decoder = PyCodec_Decoder(encoding);
515 [ + + ]: 41 : if (decoder == NULL)
516 : 1 : return NULL;
517 : :
518 : 40 : return _PyCodec_DecodeInternal(object, decoder, encoding, errors);
519 : : }
520 : :
521 : : /* Text encoding/decoding API */
522 : 1542016 : PyObject * _PyCodec_LookupTextEncoding(const char *encoding,
523 : : const char *alternate_command)
524 : : {
525 : : PyObject *codec;
526 : : PyObject *attr;
527 : : int is_text_codec;
528 : :
529 : 1542016 : codec = _PyCodec_Lookup(encoding);
530 [ + + ]: 1542016 : if (codec == NULL)
531 : 34 : return NULL;
532 : :
533 : : /* Backwards compatibility: assume any raw tuple describes a text
534 : : * encoding, and the same for anything lacking the private
535 : : * attribute.
536 : : */
537 [ + + ]: 1541982 : if (!PyTuple_CheckExact(codec)) {
538 [ - + ]: 1541963 : if (_PyObject_LookupAttr(codec, &_Py_ID(_is_text_encoding), &attr) < 0) {
539 : 0 : Py_DECREF(codec);
540 : 0 : return NULL;
541 : : }
542 [ + - ]: 1541963 : if (attr != NULL) {
543 : 1541963 : is_text_codec = PyObject_IsTrue(attr);
544 : 1541963 : Py_DECREF(attr);
545 [ + + ]: 1541963 : if (is_text_codec <= 0) {
546 : 22 : Py_DECREF(codec);
547 [ + - ]: 22 : if (!is_text_codec)
548 : 22 : PyErr_Format(PyExc_LookupError,
549 : : "'%.400s' is not a text encoding; "
550 : : "use %s to handle arbitrary codecs",
551 : : encoding, alternate_command);
552 : 22 : return NULL;
553 : : }
554 : : }
555 : : }
556 : :
557 : : /* This appears to be a valid text encoding */
558 : 1541960 : return codec;
559 : : }
560 : :
561 : :
562 : : static
563 : 1505230 : PyObject *codec_getitem_checked(const char *encoding,
564 : : const char *alternate_command,
565 : : int index)
566 : : {
567 : : PyObject *codec;
568 : : PyObject *v;
569 : :
570 : 1505230 : codec = _PyCodec_LookupTextEncoding(encoding, alternate_command);
571 [ + + ]: 1505230 : if (codec == NULL)
572 : 51 : return NULL;
573 : :
574 : 1505179 : v = PyTuple_GET_ITEM(codec, index);
575 : 1505179 : Py_INCREF(v);
576 : 1505179 : Py_DECREF(codec);
577 : 1505179 : return v;
578 : : }
579 : :
580 : 1259873 : static PyObject * _PyCodec_TextEncoder(const char *encoding)
581 : : {
582 : 1259873 : return codec_getitem_checked(encoding, "codecs.encode()", 0);
583 : : }
584 : :
585 : 245357 : static PyObject * _PyCodec_TextDecoder(const char *encoding)
586 : : {
587 : 245357 : return codec_getitem_checked(encoding, "codecs.decode()", 1);
588 : : }
589 : :
590 : 1259873 : PyObject *_PyCodec_EncodeText(PyObject *object,
591 : : const char *encoding,
592 : : const char *errors)
593 : : {
594 : : PyObject *encoder;
595 : :
596 : 1259873 : encoder = _PyCodec_TextEncoder(encoding);
597 [ + + ]: 1259873 : if (encoder == NULL)
598 : 12 : return NULL;
599 : :
600 : 1259861 : return _PyCodec_EncodeInternal(object, encoder, encoding, errors);
601 : : }
602 : :
603 : 245357 : PyObject *_PyCodec_DecodeText(PyObject *object,
604 : : const char *encoding,
605 : : const char *errors)
606 : : {
607 : : PyObject *decoder;
608 : :
609 : 245357 : decoder = _PyCodec_TextDecoder(encoding);
610 [ + + ]: 245357 : if (decoder == NULL)
611 : 39 : return NULL;
612 : :
613 : 245318 : return _PyCodec_DecodeInternal(object, decoder, encoding, errors);
614 : : }
615 : :
616 : : /* Register the error handling callback function error under the name
617 : : name. This function will be called by the codec when it encounters
618 : : an unencodable characters/undecodable bytes and doesn't know the
619 : : callback name, when name is specified as the error parameter
620 : : in the call to the encode/decode function.
621 : : Return 0 on success, -1 on error */
622 : 25307 : int PyCodec_RegisterError(const char *name, PyObject *error)
623 : : {
624 : 25307 : PyInterpreterState *interp = _PyInterpreterState_GET();
625 [ - + - - ]: 25307 : if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
626 : 0 : return -1;
627 [ + + ]: 25307 : if (!PyCallable_Check(error)) {
628 : 1 : PyErr_SetString(PyExc_TypeError, "handler must be callable");
629 : 1 : return -1;
630 : : }
631 : 25306 : return PyDict_SetItemString(interp->codec_error_registry,
632 : : name, error);
633 : : }
634 : :
635 : : /* Lookup the error handling callback function registered under the
636 : : name error. As a special case NULL can be passed, in which case
637 : : the error handling callback for strict encoding will be returned. */
638 : 28001 : PyObject *PyCodec_LookupError(const char *name)
639 : : {
640 : 28001 : PyObject *handler = NULL;
641 : :
642 : 28001 : PyInterpreterState *interp = _PyInterpreterState_GET();
643 [ - + - - ]: 28001 : if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
644 : 0 : return NULL;
645 : :
646 [ + + ]: 28001 : if (name==NULL)
647 : 3827 : name = "strict";
648 : 28001 : handler = _PyDict_GetItemStringWithError(interp->codec_error_registry, name);
649 [ + + ]: 28001 : if (handler) {
650 : 27966 : Py_INCREF(handler);
651 : : }
652 [ + - ]: 35 : else if (!PyErr_Occurred()) {
653 : 35 : PyErr_Format(PyExc_LookupError, "unknown error handler name '%.400s'", name);
654 : : }
655 : 28001 : return handler;
656 : : }
657 : :
658 : 62 : static void wrong_exception_type(PyObject *exc)
659 : : {
660 : 62 : PyErr_Format(PyExc_TypeError,
661 : : "don't know how to handle %.200s in error callback",
662 : 62 : Py_TYPE(exc)->tp_name);
663 : 62 : }
664 : :
665 : 5649 : PyObject *PyCodec_StrictErrors(PyObject *exc)
666 : : {
667 [ + + ]: 5649 : if (PyExceptionInstance_Check(exc))
668 : 5645 : PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
669 : : else
670 : 4 : PyErr_SetString(PyExc_TypeError, "codec must pass exception instance");
671 : 5649 : return NULL;
672 : : }
673 : :
674 : :
675 : 4012 : PyObject *PyCodec_IgnoreErrors(PyObject *exc)
676 : : {
677 : : Py_ssize_t end;
678 : :
679 [ + + ]: 4012 : if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
680 [ - + ]: 3423 : if (PyUnicodeEncodeError_GetEnd(exc, &end))
681 : 0 : return NULL;
682 : : }
683 [ + + ]: 589 : else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) {
684 [ - + ]: 580 : if (PyUnicodeDecodeError_GetEnd(exc, &end))
685 : 0 : return NULL;
686 : : }
687 [ + + ]: 9 : else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) {
688 [ - + ]: 1 : if (PyUnicodeTranslateError_GetEnd(exc, &end))
689 : 0 : return NULL;
690 : : }
691 : : else {
692 : 8 : wrong_exception_type(exc);
693 : 8 : return NULL;
694 : : }
695 : 4004 : return Py_BuildValue("(Nn)", PyUnicode_New(0, 0), end);
696 : : }
697 : :
698 : :
699 : 1966 : PyObject *PyCodec_ReplaceErrors(PyObject *exc)
700 : : {
701 : : Py_ssize_t start, end, i, len;
702 : :
703 [ + + ]: 1966 : if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
704 : : PyObject *res;
705 : : Py_UCS1 *outp;
706 [ + + ]: 1024 : if (PyUnicodeEncodeError_GetStart(exc, &start))
707 : 1 : return NULL;
708 [ - + ]: 1023 : if (PyUnicodeEncodeError_GetEnd(exc, &end))
709 : 0 : return NULL;
710 : 1023 : len = end - start;
711 : 1023 : res = PyUnicode_New(len, '?');
712 [ - + ]: 1023 : if (res == NULL)
713 : 0 : return NULL;
714 : : assert(PyUnicode_KIND(res) == PyUnicode_1BYTE_KIND);
715 : 1023 : outp = PyUnicode_1BYTE_DATA(res);
716 [ + + ]: 6042 : for (i = 0; i < len; ++i)
717 : 5019 : outp[i] = '?';
718 : : assert(_PyUnicode_CheckConsistency(res, 1));
719 : 1023 : return Py_BuildValue("(Nn)", res, end);
720 : : }
721 [ + + ]: 942 : else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) {
722 [ + + ]: 933 : if (PyUnicodeDecodeError_GetEnd(exc, &end))
723 : 1 : return NULL;
724 : 932 : return Py_BuildValue("(Cn)",
725 : : (int)Py_UNICODE_REPLACEMENT_CHARACTER,
726 : : end);
727 : : }
728 [ + + ]: 9 : else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) {
729 : : PyObject *res;
730 : : Py_UCS2 *outp;
731 [ - + ]: 1 : if (PyUnicodeTranslateError_GetStart(exc, &start))
732 : 0 : return NULL;
733 [ - + ]: 1 : if (PyUnicodeTranslateError_GetEnd(exc, &end))
734 : 0 : return NULL;
735 : 1 : len = end - start;
736 : 1 : res = PyUnicode_New(len, Py_UNICODE_REPLACEMENT_CHARACTER);
737 [ - + ]: 1 : if (res == NULL)
738 : 0 : return NULL;
739 : : assert(PyUnicode_KIND(res) == PyUnicode_2BYTE_KIND);
740 : 1 : outp = PyUnicode_2BYTE_DATA(res);
741 [ + + ]: 2 : for (i = 0; i < len; i++)
742 : 1 : outp[i] = Py_UNICODE_REPLACEMENT_CHARACTER;
743 : : assert(_PyUnicode_CheckConsistency(res, 1));
744 : 1 : return Py_BuildValue("(Nn)", res, end);
745 : : }
746 : : else {
747 : 8 : wrong_exception_type(exc);
748 : 8 : return NULL;
749 : : }
750 : : }
751 : :
752 : 1077 : PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc)
753 : : {
754 [ + + ]: 1077 : if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
755 : : PyObject *restuple;
756 : : PyObject *object;
757 : : Py_ssize_t i;
758 : : Py_ssize_t start;
759 : : Py_ssize_t end;
760 : : PyObject *res;
761 : : Py_UCS1 *outp;
762 : : Py_ssize_t ressize;
763 : : Py_UCS4 ch;
764 [ - + ]: 1067 : if (PyUnicodeEncodeError_GetStart(exc, &start))
765 : 0 : return NULL;
766 [ - + ]: 1067 : if (PyUnicodeEncodeError_GetEnd(exc, &end))
767 : 0 : return NULL;
768 [ - + ]: 1067 : if (!(object = PyUnicodeEncodeError_GetObject(exc)))
769 : 0 : return NULL;
770 [ - + ]: 1067 : if (end - start > PY_SSIZE_T_MAX / (2+7+1))
771 : 0 : end = start + PY_SSIZE_T_MAX / (2+7+1);
772 [ + + ]: 6159 : for (i = start, ressize = 0; i < end; ++i) {
773 : : /* object is guaranteed to be "ready" */
774 : 5092 : ch = PyUnicode_READ_CHAR(object, i);
775 [ + + ]: 5092 : if (ch<10)
776 : 3 : ressize += 2+1+1;
777 [ + + ]: 5089 : else if (ch<100)
778 : 2 : ressize += 2+2+1;
779 [ + + ]: 5087 : else if (ch<1000)
780 : 1004 : ressize += 2+3+1;
781 [ + + ]: 4083 : else if (ch<10000)
782 : 60 : ressize += 2+4+1;
783 [ + + ]: 4023 : else if (ch<100000)
784 : 4014 : ressize += 2+5+1;
785 [ + + ]: 9 : else if (ch<1000000)
786 : 6 : ressize += 2+6+1;
787 : : else
788 : 3 : ressize += 2+7+1;
789 : : }
790 : : /* allocate replacement */
791 : 1067 : res = PyUnicode_New(ressize, 127);
792 [ - + ]: 1067 : if (res == NULL) {
793 : 0 : Py_DECREF(object);
794 : 0 : return NULL;
795 : : }
796 : 1067 : outp = PyUnicode_1BYTE_DATA(res);
797 : : /* generate replacement */
798 [ + + ]: 6159 : for (i = start; i < end; ++i) {
799 : : int digits;
800 : : int base;
801 : 5092 : ch = PyUnicode_READ_CHAR(object, i);
802 : 5092 : *outp++ = '&';
803 : 5092 : *outp++ = '#';
804 [ + + ]: 5092 : if (ch<10) {
805 : 3 : digits = 1;
806 : 3 : base = 1;
807 : : }
808 [ + + ]: 5089 : else if (ch<100) {
809 : 2 : digits = 2;
810 : 2 : base = 10;
811 : : }
812 [ + + ]: 5087 : else if (ch<1000) {
813 : 1004 : digits = 3;
814 : 1004 : base = 100;
815 : : }
816 [ + + ]: 4083 : else if (ch<10000) {
817 : 60 : digits = 4;
818 : 60 : base = 1000;
819 : : }
820 [ + + ]: 4023 : else if (ch<100000) {
821 : 4014 : digits = 5;
822 : 4014 : base = 10000;
823 : : }
824 [ + + ]: 9 : else if (ch<1000000) {
825 : 6 : digits = 6;
826 : 6 : base = 100000;
827 : : }
828 : : else {
829 : 3 : digits = 7;
830 : 3 : base = 1000000;
831 : : }
832 [ + + ]: 28478 : while (digits-->0) {
833 : 23386 : *outp++ = '0' + ch/base;
834 : 23386 : ch %= base;
835 : 23386 : base /= 10;
836 : : }
837 : 5092 : *outp++ = ';';
838 : : }
839 : : assert(_PyUnicode_CheckConsistency(res, 1));
840 : 1067 : restuple = Py_BuildValue("(Nn)", res, end);
841 : 1067 : Py_DECREF(object);
842 : 1067 : return restuple;
843 : : }
844 : : else {
845 : 10 : wrong_exception_type(exc);
846 : 10 : return NULL;
847 : : }
848 : : }
849 : :
850 : 1121 : PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc)
851 : : {
852 : : PyObject *object;
853 : : Py_ssize_t i;
854 : : Py_ssize_t start;
855 : : Py_ssize_t end;
856 : : PyObject *res;
857 : : Py_UCS1 *outp;
858 : : int ressize;
859 : : Py_UCS4 c;
860 : :
861 [ + + ]: 1121 : if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) {
862 : : const unsigned char *p;
863 [ - + ]: 60 : if (PyUnicodeDecodeError_GetStart(exc, &start))
864 : 0 : return NULL;
865 [ - + ]: 60 : if (PyUnicodeDecodeError_GetEnd(exc, &end))
866 : 0 : return NULL;
867 [ - + ]: 60 : if (!(object = PyUnicodeDecodeError_GetObject(exc)))
868 : 0 : return NULL;
869 : 60 : p = (const unsigned char*)PyBytes_AS_STRING(object);
870 : 60 : res = PyUnicode_New(4 * (end - start), 127);
871 [ - + ]: 60 : if (res == NULL) {
872 : 0 : Py_DECREF(object);
873 : 0 : return NULL;
874 : : }
875 : 60 : outp = PyUnicode_1BYTE_DATA(res);
876 [ + + ]: 174 : for (i = start; i < end; i++, outp += 4) {
877 : 114 : unsigned char c = p[i];
878 : 114 : outp[0] = '\\';
879 : 114 : outp[1] = 'x';
880 : 114 : outp[2] = Py_hexdigits[(c>>4)&0xf];
881 : 114 : outp[3] = Py_hexdigits[c&0xf];
882 : : }
883 : :
884 : : assert(_PyUnicode_CheckConsistency(res, 1));
885 : 60 : Py_DECREF(object);
886 : 60 : return Py_BuildValue("(Nn)", res, end);
887 : : }
888 [ + + ]: 1061 : if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
889 [ - + ]: 1041 : if (PyUnicodeEncodeError_GetStart(exc, &start))
890 : 0 : return NULL;
891 [ - + ]: 1041 : if (PyUnicodeEncodeError_GetEnd(exc, &end))
892 : 0 : return NULL;
893 [ - + ]: 1041 : if (!(object = PyUnicodeEncodeError_GetObject(exc)))
894 : 0 : return NULL;
895 : : }
896 [ + + ]: 20 : else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) {
897 [ - + ]: 12 : if (PyUnicodeTranslateError_GetStart(exc, &start))
898 : 0 : return NULL;
899 [ - + ]: 12 : if (PyUnicodeTranslateError_GetEnd(exc, &end))
900 : 0 : return NULL;
901 [ - + ]: 12 : if (!(object = PyUnicodeTranslateError_GetObject(exc)))
902 : 0 : return NULL;
903 : : }
904 : : else {
905 : 8 : wrong_exception_type(exc);
906 : 8 : return NULL;
907 : : }
908 : :
909 [ - + ]: 1053 : if (end - start > PY_SSIZE_T_MAX / (1+1+8))
910 : 0 : end = start + PY_SSIZE_T_MAX / (1+1+8);
911 [ + + ]: 7108 : for (i = start, ressize = 0; i < end; ++i) {
912 : : /* object is guaranteed to be "ready" */
913 : 6055 : c = PyUnicode_READ_CHAR(object, i);
914 [ + + ]: 6055 : if (c >= 0x10000) {
915 : 7 : ressize += 1+1+8;
916 : : }
917 [ + + ]: 6048 : else if (c >= 0x100) {
918 : 5030 : ressize += 1+1+4;
919 : : }
920 : : else
921 : 1018 : ressize += 1+1+2;
922 : : }
923 : 1053 : res = PyUnicode_New(ressize, 127);
924 [ - + ]: 1053 : if (res == NULL) {
925 : 0 : Py_DECREF(object);
926 : 0 : return NULL;
927 : : }
928 : 1053 : outp = PyUnicode_1BYTE_DATA(res);
929 [ + + ]: 7108 : for (i = start; i < end; ++i) {
930 : 6055 : c = PyUnicode_READ_CHAR(object, i);
931 : 6055 : *outp++ = '\\';
932 [ + + ]: 6055 : if (c >= 0x00010000) {
933 : 7 : *outp++ = 'U';
934 : 7 : *outp++ = Py_hexdigits[(c>>28)&0xf];
935 : 7 : *outp++ = Py_hexdigits[(c>>24)&0xf];
936 : 7 : *outp++ = Py_hexdigits[(c>>20)&0xf];
937 : 7 : *outp++ = Py_hexdigits[(c>>16)&0xf];
938 : 7 : *outp++ = Py_hexdigits[(c>>12)&0xf];
939 : 7 : *outp++ = Py_hexdigits[(c>>8)&0xf];
940 : : }
941 [ + + ]: 6048 : else if (c >= 0x100) {
942 : 5030 : *outp++ = 'u';
943 : 5030 : *outp++ = Py_hexdigits[(c>>12)&0xf];
944 : 5030 : *outp++ = Py_hexdigits[(c>>8)&0xf];
945 : : }
946 : : else
947 : 1018 : *outp++ = 'x';
948 : 6055 : *outp++ = Py_hexdigits[(c>>4)&0xf];
949 : 6055 : *outp++ = Py_hexdigits[c&0xf];
950 : : }
951 : :
952 : : assert(_PyUnicode_CheckConsistency(res, 1));
953 : 1053 : Py_DECREF(object);
954 : 1053 : return Py_BuildValue("(Nn)", res, end);
955 : : }
956 : :
957 : : static _PyUnicode_Name_CAPI *ucnhash_capi = NULL;
958 : :
959 : 2039 : PyObject *PyCodec_NameReplaceErrors(PyObject *exc)
960 : : {
961 [ + + ]: 2039 : if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
962 : : PyObject *restuple;
963 : : PyObject *object;
964 : : Py_ssize_t i;
965 : : Py_ssize_t start;
966 : : Py_ssize_t end;
967 : : PyObject *res;
968 : : Py_UCS1 *outp;
969 : : Py_ssize_t ressize;
970 : : int replsize;
971 : : Py_UCS4 c;
972 : : char buffer[256]; /* NAME_MAXLEN */
973 [ - + ]: 2029 : if (PyUnicodeEncodeError_GetStart(exc, &start))
974 : 0 : return NULL;
975 [ - + ]: 2029 : if (PyUnicodeEncodeError_GetEnd(exc, &end))
976 : 0 : return NULL;
977 [ - + ]: 2029 : if (!(object = PyUnicodeEncodeError_GetObject(exc)))
978 : 0 : return NULL;
979 [ + + ]: 2029 : if (!ucnhash_capi) {
980 : : /* load the unicode data module */
981 : 2 : ucnhash_capi = (_PyUnicode_Name_CAPI *)PyCapsule_Import(
982 : : PyUnicodeData_CAPSULE_NAME, 1);
983 [ - + ]: 2 : if (!ucnhash_capi) {
984 : 0 : return NULL;
985 : : }
986 : : }
987 [ + + ]: 12059 : for (i = start, ressize = 0; i < end; ++i) {
988 : : /* object is guaranteed to be "ready" */
989 : 10030 : c = PyUnicode_READ_CHAR(object, i);
990 [ + + ]: 10030 : if (ucnhash_capi->getname(c, buffer, sizeof(buffer), 1)) {
991 : 10013 : replsize = 1+1+1+(int)strlen(buffer)+1;
992 : : }
993 [ + + ]: 17 : else if (c >= 0x10000) {
994 : 4 : replsize = 1+1+8;
995 : : }
996 [ + + ]: 13 : else if (c >= 0x100) {
997 : 12 : replsize = 1+1+4;
998 : : }
999 : : else
1000 : 1 : replsize = 1+1+2;
1001 [ - + ]: 10030 : if (ressize > PY_SSIZE_T_MAX - replsize)
1002 : 0 : break;
1003 : 10030 : ressize += replsize;
1004 : : }
1005 : 2029 : end = i;
1006 : 2029 : res = PyUnicode_New(ressize, 127);
1007 [ - + ]: 2029 : if (res==NULL)
1008 : 0 : return NULL;
1009 : 2029 : for (i = start, outp = PyUnicode_1BYTE_DATA(res);
1010 [ + + ]: 12059 : i < end; ++i) {
1011 : 10030 : c = PyUnicode_READ_CHAR(object, i);
1012 : 10030 : *outp++ = '\\';
1013 [ + + ]: 10030 : if (ucnhash_capi->getname(c, buffer, sizeof(buffer), 1)) {
1014 : 10013 : *outp++ = 'N';
1015 : 10013 : *outp++ = '{';
1016 : 10013 : strcpy((char *)outp, buffer);
1017 : 10013 : outp += strlen(buffer);
1018 : 10013 : *outp++ = '}';
1019 : 10013 : continue;
1020 : : }
1021 [ + + ]: 17 : if (c >= 0x00010000) {
1022 : 4 : *outp++ = 'U';
1023 : 4 : *outp++ = Py_hexdigits[(c>>28)&0xf];
1024 : 4 : *outp++ = Py_hexdigits[(c>>24)&0xf];
1025 : 4 : *outp++ = Py_hexdigits[(c>>20)&0xf];
1026 : 4 : *outp++ = Py_hexdigits[(c>>16)&0xf];
1027 : 4 : *outp++ = Py_hexdigits[(c>>12)&0xf];
1028 : 4 : *outp++ = Py_hexdigits[(c>>8)&0xf];
1029 : : }
1030 [ + + ]: 13 : else if (c >= 0x100) {
1031 : 12 : *outp++ = 'u';
1032 : 12 : *outp++ = Py_hexdigits[(c>>12)&0xf];
1033 : 12 : *outp++ = Py_hexdigits[(c>>8)&0xf];
1034 : : }
1035 : : else
1036 : 1 : *outp++ = 'x';
1037 : 17 : *outp++ = Py_hexdigits[(c>>4)&0xf];
1038 : 17 : *outp++ = Py_hexdigits[c&0xf];
1039 : : }
1040 : :
1041 : : assert(outp == PyUnicode_1BYTE_DATA(res) + ressize);
1042 : : assert(_PyUnicode_CheckConsistency(res, 1));
1043 : 2029 : restuple = Py_BuildValue("(Nn)", res, end);
1044 : 2029 : Py_DECREF(object);
1045 : 2029 : return restuple;
1046 : : }
1047 : : else {
1048 : 10 : wrong_exception_type(exc);
1049 : 10 : return NULL;
1050 : : }
1051 : : }
1052 : :
1053 : : #define ENC_UNKNOWN -1
1054 : : #define ENC_UTF8 0
1055 : : #define ENC_UTF16BE 1
1056 : : #define ENC_UTF16LE 2
1057 : : #define ENC_UTF32BE 3
1058 : : #define ENC_UTF32LE 4
1059 : :
1060 : : static int
1061 : 1401 : get_standard_encoding(const char *encoding, int *bytelength)
1062 : : {
1063 [ + + ]: 1401 : if (Py_TOLOWER(encoding[0]) == 'u' &&
1064 [ + - ]: 1398 : Py_TOLOWER(encoding[1]) == 't' &&
1065 [ + - ]: 1398 : Py_TOLOWER(encoding[2]) == 'f') {
1066 : 1398 : encoding += 3;
1067 [ - + - - ]: 1398 : if (*encoding == '-' || *encoding == '_' )
1068 : 1398 : encoding++;
1069 [ + + + - ]: 1398 : if (encoding[0] == '8' && encoding[1] == '\0') {
1070 : 1282 : *bytelength = 3;
1071 : 1282 : return ENC_UTF8;
1072 : : }
1073 [ + + + - ]: 116 : else if (encoding[0] == '1' && encoding[1] == '6') {
1074 : 50 : encoding += 2;
1075 : 50 : *bytelength = 2;
1076 [ + + ]: 50 : if (*encoding == '\0') {
1077 : : #ifdef WORDS_BIGENDIAN
1078 : : return ENC_UTF16BE;
1079 : : #else
1080 : 5 : return ENC_UTF16LE;
1081 : : #endif
1082 : : }
1083 [ + + - + ]: 45 : if (*encoding == '-' || *encoding == '_' )
1084 : 29 : encoding++;
1085 [ + - + - ]: 45 : if (Py_TOLOWER(encoding[1]) == 'e' && encoding[2] == '\0') {
1086 [ + + ]: 45 : if (Py_TOLOWER(encoding[0]) == 'b')
1087 : 18 : return ENC_UTF16BE;
1088 [ + - ]: 27 : if (Py_TOLOWER(encoding[0]) == 'l')
1089 : 27 : return ENC_UTF16LE;
1090 : : }
1091 : : }
1092 [ + - + - ]: 66 : else if (encoding[0] == '3' && encoding[1] == '2') {
1093 : 66 : encoding += 2;
1094 : 66 : *bytelength = 4;
1095 [ + + ]: 66 : if (*encoding == '\0') {
1096 : : #ifdef WORDS_BIGENDIAN
1097 : : return ENC_UTF32BE;
1098 : : #else
1099 : 5 : return ENC_UTF32LE;
1100 : : #endif
1101 : : }
1102 [ + + - + ]: 61 : if (*encoding == '-' || *encoding == '_' )
1103 : 45 : encoding++;
1104 [ + - + - ]: 61 : if (Py_TOLOWER(encoding[1]) == 'e' && encoding[2] == '\0') {
1105 [ + + ]: 61 : if (Py_TOLOWER(encoding[0]) == 'b')
1106 : 22 : return ENC_UTF32BE;
1107 [ + - ]: 39 : if (Py_TOLOWER(encoding[0]) == 'l')
1108 : 39 : return ENC_UTF32LE;
1109 : : }
1110 : : }
1111 : : }
1112 [ - + ]: 3 : else if (strcmp(encoding, "CP_UTF8") == 0) {
1113 : 0 : *bytelength = 3;
1114 : 0 : return ENC_UTF8;
1115 : : }
1116 : 3 : return ENC_UNKNOWN;
1117 : : }
1118 : :
1119 : : /* This handler is declared static until someone demonstrates
1120 : : a need to call it directly. */
1121 : : static PyObject *
1122 : 1410 : PyCodec_SurrogatePassErrors(PyObject *exc)
1123 : : {
1124 : : PyObject *restuple;
1125 : : PyObject *object;
1126 : : PyObject *encode;
1127 : : const char *encoding;
1128 : : int code;
1129 : : int bytelength;
1130 : : Py_ssize_t i;
1131 : : Py_ssize_t start;
1132 : : Py_ssize_t end;
1133 : : PyObject *res;
1134 : :
1135 [ + + ]: 1410 : if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
1136 : : unsigned char *outp;
1137 [ - + ]: 53 : if (PyUnicodeEncodeError_GetStart(exc, &start))
1138 : 0 : return NULL;
1139 [ - + ]: 53 : if (PyUnicodeEncodeError_GetEnd(exc, &end))
1140 : 0 : return NULL;
1141 [ - + ]: 53 : if (!(object = PyUnicodeEncodeError_GetObject(exc)))
1142 : 0 : return NULL;
1143 [ - + ]: 53 : if (!(encode = PyUnicodeEncodeError_GetEncoding(exc))) {
1144 : 0 : Py_DECREF(object);
1145 : 0 : return NULL;
1146 : : }
1147 [ - + ]: 53 : if (!(encoding = PyUnicode_AsUTF8(encode))) {
1148 : 0 : Py_DECREF(object);
1149 : 0 : Py_DECREF(encode);
1150 : 0 : return NULL;
1151 : : }
1152 : 53 : code = get_standard_encoding(encoding, &bytelength);
1153 : 53 : Py_DECREF(encode);
1154 [ + + ]: 53 : if (code == ENC_UNKNOWN) {
1155 : : /* Not supported, fail with original exception */
1156 : 3 : PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
1157 : 3 : Py_DECREF(object);
1158 : 3 : return NULL;
1159 : : }
1160 : :
1161 [ - + ]: 50 : if (end - start > PY_SSIZE_T_MAX / bytelength)
1162 : 0 : end = start + PY_SSIZE_T_MAX / bytelength;
1163 : 50 : res = PyBytes_FromStringAndSize(NULL, bytelength*(end-start));
1164 [ - + ]: 50 : if (!res) {
1165 : 0 : Py_DECREF(object);
1166 : 0 : return NULL;
1167 : : }
1168 : 50 : outp = (unsigned char*)PyBytes_AsString(res);
1169 [ + + ]: 100 : for (i = start; i < end; i++) {
1170 : : /* object is guaranteed to be "ready" */
1171 : 55 : Py_UCS4 ch = PyUnicode_READ_CHAR(object, i);
1172 [ + + ]: 55 : if (!Py_UNICODE_IS_SURROGATE(ch)) {
1173 : : /* Not a surrogate, fail with original exception */
1174 : 5 : PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
1175 : 5 : Py_DECREF(res);
1176 : 5 : Py_DECREF(object);
1177 : 5 : return NULL;
1178 : : }
1179 [ + + + + : 50 : switch (code) {
+ - ]
1180 : 4 : case ENC_UTF8:
1181 : 4 : *outp++ = (unsigned char)(0xe0 | (ch >> 12));
1182 : 4 : *outp++ = (unsigned char)(0x80 | ((ch >> 6) & 0x3f));
1183 : 4 : *outp++ = (unsigned char)(0x80 | (ch & 0x3f));
1184 : 4 : break;
1185 : 14 : case ENC_UTF16LE:
1186 : 14 : *outp++ = (unsigned char) ch;
1187 : 14 : *outp++ = (unsigned char)(ch >> 8);
1188 : 14 : break;
1189 : 9 : case ENC_UTF16BE:
1190 : 9 : *outp++ = (unsigned char)(ch >> 8);
1191 : 9 : *outp++ = (unsigned char) ch;
1192 : 9 : break;
1193 : 14 : case ENC_UTF32LE:
1194 : 14 : *outp++ = (unsigned char) ch;
1195 : 14 : *outp++ = (unsigned char)(ch >> 8);
1196 : 14 : *outp++ = (unsigned char)(ch >> 16);
1197 : 14 : *outp++ = (unsigned char)(ch >> 24);
1198 : 14 : break;
1199 : 9 : case ENC_UTF32BE:
1200 : 9 : *outp++ = (unsigned char)(ch >> 24);
1201 : 9 : *outp++ = (unsigned char)(ch >> 16);
1202 : 9 : *outp++ = (unsigned char)(ch >> 8);
1203 : 9 : *outp++ = (unsigned char) ch;
1204 : 9 : break;
1205 : : }
1206 : : }
1207 : 45 : restuple = Py_BuildValue("(On)", res, end);
1208 : 45 : Py_DECREF(res);
1209 : 45 : Py_DECREF(object);
1210 : 45 : return restuple;
1211 : : }
1212 [ + + ]: 1357 : else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) {
1213 : : const unsigned char *p;
1214 : 1348 : Py_UCS4 ch = 0;
1215 [ - + ]: 1348 : if (PyUnicodeDecodeError_GetStart(exc, &start))
1216 : 0 : return NULL;
1217 [ - + ]: 1348 : if (PyUnicodeDecodeError_GetEnd(exc, &end))
1218 : 0 : return NULL;
1219 [ - + ]: 1348 : if (!(object = PyUnicodeDecodeError_GetObject(exc)))
1220 : 0 : return NULL;
1221 : 1348 : p = (const unsigned char*)PyBytes_AS_STRING(object);
1222 [ - + ]: 1348 : if (!(encode = PyUnicodeDecodeError_GetEncoding(exc))) {
1223 : 0 : Py_DECREF(object);
1224 : 0 : return NULL;
1225 : : }
1226 [ - + ]: 1348 : if (!(encoding = PyUnicode_AsUTF8(encode))) {
1227 : 0 : Py_DECREF(object);
1228 : 0 : Py_DECREF(encode);
1229 : 0 : return NULL;
1230 : : }
1231 : 1348 : code = get_standard_encoding(encoding, &bytelength);
1232 : 1348 : Py_DECREF(encode);
1233 [ - + ]: 1348 : if (code == ENC_UNKNOWN) {
1234 : : /* Not supported, fail with original exception */
1235 : 0 : PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
1236 : 0 : Py_DECREF(object);
1237 : 0 : return NULL;
1238 : : }
1239 : :
1240 : : /* Try decoding a single surrogate character. If
1241 : : there are more, let the codec call us again. */
1242 : 1348 : p += start;
1243 [ + + ]: 1348 : if (PyBytes_GET_SIZE(object) - start >= bytelength) {
1244 [ + + + + : 1345 : switch (code) {
+ - ]
1245 : 1275 : case ENC_UTF8:
1246 [ + + ]: 1275 : if ((p[0] & 0xf0) == 0xe0 &&
1247 [ + - ]: 1273 : (p[1] & 0xc0) == 0x80 &&
1248 [ + + ]: 1273 : (p[2] & 0xc0) == 0x80) {
1249 : : /* it's a three-byte code */
1250 : 1271 : ch = ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6) + (p[2] & 0x3f);
1251 : : }
1252 : 1275 : break;
1253 : 18 : case ENC_UTF16LE:
1254 : 18 : ch = p[1] << 8 | p[0];
1255 : 18 : break;
1256 : 9 : case ENC_UTF16BE:
1257 : 9 : ch = p[0] << 8 | p[1];
1258 : 9 : break;
1259 : 30 : case ENC_UTF32LE:
1260 : 30 : ch = (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
1261 : 30 : break;
1262 : 13 : case ENC_UTF32BE:
1263 : 13 : ch = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
1264 : 13 : break;
1265 : : }
1266 : : }
1267 : :
1268 : 1348 : Py_DECREF(object);
1269 [ + + ]: 1348 : if (!Py_UNICODE_IS_SURROGATE(ch)) {
1270 : : /* it's not a surrogate - fail */
1271 : 11 : PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
1272 : 11 : return NULL;
1273 : : }
1274 : 1337 : res = PyUnicode_FromOrdinal(ch);
1275 [ - + ]: 1337 : if (res == NULL)
1276 : 0 : return NULL;
1277 : 1337 : return Py_BuildValue("(Nn)", res, start + bytelength);
1278 : : }
1279 : : else {
1280 : 9 : wrong_exception_type(exc);
1281 : 9 : return NULL;
1282 : : }
1283 : : }
1284 : :
1285 : : static PyObject *
1286 : 75 : PyCodec_SurrogateEscapeErrors(PyObject *exc)
1287 : : {
1288 : : PyObject *restuple;
1289 : : PyObject *object;
1290 : : Py_ssize_t i;
1291 : : Py_ssize_t start;
1292 : : Py_ssize_t end;
1293 : : PyObject *res;
1294 : :
1295 [ + + ]: 75 : if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
1296 : : char *outp;
1297 [ - + ]: 63 : if (PyUnicodeEncodeError_GetStart(exc, &start))
1298 : 0 : return NULL;
1299 [ - + ]: 63 : if (PyUnicodeEncodeError_GetEnd(exc, &end))
1300 : 0 : return NULL;
1301 [ - + ]: 63 : if (!(object = PyUnicodeEncodeError_GetObject(exc)))
1302 : 0 : return NULL;
1303 : 63 : res = PyBytes_FromStringAndSize(NULL, end-start);
1304 [ - + ]: 63 : if (!res) {
1305 : 0 : Py_DECREF(object);
1306 : 0 : return NULL;
1307 : : }
1308 : 63 : outp = PyBytes_AsString(res);
1309 [ + + ]: 65 : for (i = start; i < end; i++) {
1310 : : /* object is guaranteed to be "ready" */
1311 : 63 : Py_UCS4 ch = PyUnicode_READ_CHAR(object, i);
1312 [ + + + + ]: 63 : if (ch < 0xdc80 || ch > 0xdcff) {
1313 : : /* Not a UTF-8b surrogate, fail with original exception */
1314 : 61 : PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
1315 : 61 : Py_DECREF(res);
1316 : 61 : Py_DECREF(object);
1317 : 61 : return NULL;
1318 : : }
1319 : 2 : *outp++ = ch - 0xdc00;
1320 : : }
1321 : 2 : restuple = Py_BuildValue("(On)", res, end);
1322 : 2 : Py_DECREF(res);
1323 : 2 : Py_DECREF(object);
1324 : 2 : return restuple;
1325 : : }
1326 [ + + ]: 12 : else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) {
1327 : : PyObject *str;
1328 : : const unsigned char *p;
1329 : : Py_UCS2 ch[4]; /* decode up to 4 bad bytes. */
1330 : 3 : int consumed = 0;
1331 [ - + ]: 3 : if (PyUnicodeDecodeError_GetStart(exc, &start))
1332 : 0 : return NULL;
1333 [ - + ]: 3 : if (PyUnicodeDecodeError_GetEnd(exc, &end))
1334 : 0 : return NULL;
1335 [ - + ]: 3 : if (!(object = PyUnicodeDecodeError_GetObject(exc)))
1336 : 0 : return NULL;
1337 : 3 : p = (const unsigned char*)PyBytes_AS_STRING(object);
1338 [ + - + + ]: 5 : while (consumed < 4 && consumed < end-start) {
1339 : : /* Refuse to escape ASCII bytes. */
1340 [ + + ]: 3 : if (p[start+consumed] < 128)
1341 : 1 : break;
1342 : 2 : ch[consumed] = 0xdc00 + p[start+consumed];
1343 : 2 : consumed++;
1344 : : }
1345 : 3 : Py_DECREF(object);
1346 [ + + ]: 3 : if (!consumed) {
1347 : : /* codec complained about ASCII byte. */
1348 : 1 : PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
1349 : 1 : return NULL;
1350 : : }
1351 : 2 : str = PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, ch, consumed);
1352 [ - + ]: 2 : if (str == NULL)
1353 : 0 : return NULL;
1354 : 2 : return Py_BuildValue("(Nn)", str, start+consumed);
1355 : : }
1356 : : else {
1357 : 9 : wrong_exception_type(exc);
1358 : 9 : return NULL;
1359 : : }
1360 : : }
1361 : :
1362 : :
1363 : 4361 : static PyObject *strict_errors(PyObject *self, PyObject *exc)
1364 : : {
1365 : 4361 : return PyCodec_StrictErrors(exc);
1366 : : }
1367 : :
1368 : :
1369 : 4012 : static PyObject *ignore_errors(PyObject *self, PyObject *exc)
1370 : : {
1371 : 4012 : return PyCodec_IgnoreErrors(exc);
1372 : : }
1373 : :
1374 : :
1375 : 1966 : static PyObject *replace_errors(PyObject *self, PyObject *exc)
1376 : : {
1377 : 1966 : return PyCodec_ReplaceErrors(exc);
1378 : : }
1379 : :
1380 : :
1381 : 1077 : static PyObject *xmlcharrefreplace_errors(PyObject *self, PyObject *exc)
1382 : : {
1383 : 1077 : return PyCodec_XMLCharRefReplaceErrors(exc);
1384 : : }
1385 : :
1386 : :
1387 : 1121 : static PyObject *backslashreplace_errors(PyObject *self, PyObject *exc)
1388 : : {
1389 : 1121 : return PyCodec_BackslashReplaceErrors(exc);
1390 : : }
1391 : :
1392 : 2039 : static PyObject *namereplace_errors(PyObject *self, PyObject *exc)
1393 : : {
1394 : 2039 : return PyCodec_NameReplaceErrors(exc);
1395 : : }
1396 : :
1397 : 1410 : static PyObject *surrogatepass_errors(PyObject *self, PyObject *exc)
1398 : : {
1399 : 1410 : return PyCodec_SurrogatePassErrors(exc);
1400 : : }
1401 : :
1402 : 75 : static PyObject *surrogateescape_errors(PyObject *self, PyObject *exc)
1403 : : {
1404 : 75 : return PyCodec_SurrogateEscapeErrors(exc);
1405 : : }
1406 : :
1407 : 3134 : static int _PyCodecRegistry_Init(void)
1408 : : {
1409 : : static struct {
1410 : : const char *name;
1411 : : PyMethodDef def;
1412 : : } methods[] =
1413 : : {
1414 : : {
1415 : : "strict",
1416 : : {
1417 : : "strict_errors",
1418 : : strict_errors,
1419 : : METH_O,
1420 : : PyDoc_STR("Implements the 'strict' error handling, which "
1421 : : "raises a UnicodeError on coding errors.")
1422 : : }
1423 : : },
1424 : : {
1425 : : "ignore",
1426 : : {
1427 : : "ignore_errors",
1428 : : ignore_errors,
1429 : : METH_O,
1430 : : PyDoc_STR("Implements the 'ignore' error handling, which "
1431 : : "ignores malformed data and continues.")
1432 : : }
1433 : : },
1434 : : {
1435 : : "replace",
1436 : : {
1437 : : "replace_errors",
1438 : : replace_errors,
1439 : : METH_O,
1440 : : PyDoc_STR("Implements the 'replace' error handling, which "
1441 : : "replaces malformed data with a replacement marker.")
1442 : : }
1443 : : },
1444 : : {
1445 : : "xmlcharrefreplace",
1446 : : {
1447 : : "xmlcharrefreplace_errors",
1448 : : xmlcharrefreplace_errors,
1449 : : METH_O,
1450 : : PyDoc_STR("Implements the 'xmlcharrefreplace' error handling, "
1451 : : "which replaces an unencodable character with the "
1452 : : "appropriate XML character reference.")
1453 : : }
1454 : : },
1455 : : {
1456 : : "backslashreplace",
1457 : : {
1458 : : "backslashreplace_errors",
1459 : : backslashreplace_errors,
1460 : : METH_O,
1461 : : PyDoc_STR("Implements the 'backslashreplace' error handling, "
1462 : : "which replaces malformed data with a backslashed "
1463 : : "escape sequence.")
1464 : : }
1465 : : },
1466 : : {
1467 : : "namereplace",
1468 : : {
1469 : : "namereplace_errors",
1470 : : namereplace_errors,
1471 : : METH_O,
1472 : : PyDoc_STR("Implements the 'namereplace' error handling, "
1473 : : "which replaces an unencodable character with a "
1474 : : "\\N{...} escape sequence.")
1475 : : }
1476 : : },
1477 : : {
1478 : : "surrogatepass",
1479 : : {
1480 : : "surrogatepass",
1481 : : surrogatepass_errors,
1482 : : METH_O
1483 : : }
1484 : : },
1485 : : {
1486 : : "surrogateescape",
1487 : : {
1488 : : "surrogateescape",
1489 : : surrogateescape_errors,
1490 : : METH_O
1491 : : }
1492 : : }
1493 : : };
1494 : :
1495 : 3134 : PyInterpreterState *interp = _PyInterpreterState_GET();
1496 : : PyObject *mod;
1497 : :
1498 [ - + ]: 3134 : if (interp->codec_search_path != NULL)
1499 : 0 : return 0;
1500 : :
1501 : 3134 : interp->codec_search_path = PyList_New(0);
1502 [ - + ]: 3134 : if (interp->codec_search_path == NULL) {
1503 : 0 : return -1;
1504 : : }
1505 : :
1506 : 3134 : interp->codec_search_cache = PyDict_New();
1507 [ - + ]: 3134 : if (interp->codec_search_cache == NULL) {
1508 : 0 : return -1;
1509 : : }
1510 : :
1511 : 3134 : interp->codec_error_registry = PyDict_New();
1512 [ - + ]: 3134 : if (interp->codec_error_registry == NULL) {
1513 : 0 : return -1;
1514 : : }
1515 : :
1516 [ + + ]: 28206 : for (size_t i = 0; i < Py_ARRAY_LENGTH(methods); ++i) {
1517 : 25072 : PyObject *func = PyCFunction_NewEx(&methods[i].def, NULL, NULL);
1518 [ - + ]: 25072 : if (!func) {
1519 : 0 : return -1;
1520 : : }
1521 : :
1522 : 25072 : int res = PyCodec_RegisterError(methods[i].name, func);
1523 : 25072 : Py_DECREF(func);
1524 [ - + ]: 25072 : if (res) {
1525 : 0 : return -1;
1526 : : }
1527 : : }
1528 : :
1529 : 3134 : mod = PyImport_ImportModule("encodings");
1530 [ - + ]: 3134 : if (mod == NULL) {
1531 : 0 : return -1;
1532 : : }
1533 : 3134 : Py_DECREF(mod);
1534 : 3134 : interp->codecs_initialized = 1;
1535 : 3134 : return 0;
1536 : : }
|