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