diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2023-11-14 15:37:56 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-14 15:37:56 (GMT) |
commit | ee06fffd38cb51ce1c045da9d8336d9ce13c318a (patch) | |
tree | 764d92fd0d9f750b2973004c2e7f46c91299adbf /Modules/_io | |
parent | a519b87958da0b340caef48349d6e3c23c98e47e (diff) | |
download | cpython-ee06fffd38cb51ce1c045da9d8336d9ce13c318a.zip cpython-ee06fffd38cb51ce1c045da9d8336d9ce13c318a.tar.gz cpython-ee06fffd38cb51ce1c045da9d8336d9ce13c318a.tar.bz2 |
gh-111942: Fix crashes in TextIOWrapper.reconfigure() (GH-111976)
* Fix crash when encoding is not string or None.
* Fix crash when both line_buffering and write_through raise exception
when converted ti int.
* Add a number of tests for constructor and reconfigure() method
with invalid arguments.
Diffstat (limited to 'Modules/_io')
-rw-r--r-- | Modules/_io/textio.c | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index e6a971e..5c37e99 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -1284,30 +1284,40 @@ textiowrapper_change_encoding(textio *self, PyObject *encoding, errors = &_Py_ID(strict); } } + Py_INCREF(errors); + const char *c_encoding = PyUnicode_AsUTF8(encoding); + if (c_encoding == NULL) { + Py_DECREF(encoding); + Py_DECREF(errors); + return -1; + } const char *c_errors = PyUnicode_AsUTF8(errors); if (c_errors == NULL) { Py_DECREF(encoding); + Py_DECREF(errors); return -1; } // Create new encoder & decoder PyObject *codec_info = _PyCodec_LookupTextEncoding( - PyUnicode_AsUTF8(encoding), "codecs.open()"); + c_encoding, "codecs.open()"); if (codec_info == NULL) { Py_DECREF(encoding); + Py_DECREF(errors); return -1; } if (_textiowrapper_set_decoder(self, codec_info, c_errors) != 0 || _textiowrapper_set_encoder(self, codec_info, c_errors) != 0) { Py_DECREF(codec_info); Py_DECREF(encoding); + Py_DECREF(errors); return -1; } Py_DECREF(codec_info); Py_SETREF(self->encoding, encoding); - Py_SETREF(self->errors, Py_NewRef(errors)); + Py_SETREF(self->errors, errors); return _textiowrapper_fix_encoder_state(self); } @@ -1338,6 +1348,26 @@ _io_TextIOWrapper_reconfigure_impl(textio *self, PyObject *encoding, int write_through; const char *newline = NULL; + if (encoding != Py_None && !PyUnicode_Check(encoding)) { + PyErr_Format(PyExc_TypeError, + "reconfigure() argument 'encoding' must be str or None, not %s", + Py_TYPE(encoding)->tp_name); + return NULL; + } + if (errors != Py_None && !PyUnicode_Check(errors)) { + PyErr_Format(PyExc_TypeError, + "reconfigure() argument 'errors' must be str or None, not %s", + Py_TYPE(errors)->tp_name); + return NULL; + } + if (newline_obj != NULL && newline_obj != Py_None && + !PyUnicode_Check(newline_obj)) + { + PyErr_Format(PyExc_TypeError, + "reconfigure() argument 'newline' must be str or None, not %s", + Py_TYPE(newline_obj)->tp_name); + return NULL; + } /* Check if something is in the read buffer */ if (self->decoded_chars != NULL) { if (encoding != Py_None || errors != Py_None || newline_obj != NULL) { @@ -1357,9 +1387,12 @@ _io_TextIOWrapper_reconfigure_impl(textio *self, PyObject *encoding, line_buffering = convert_optional_bool(line_buffering_obj, self->line_buffering); + if (line_buffering < 0) { + return NULL; + } write_through = convert_optional_bool(write_through_obj, self->write_through); - if (line_buffering < 0 || write_through < 0) { + if (write_through < 0) { return NULL; } |