summaryrefslogtreecommitdiffstats
path: root/Modules/_io
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2023-11-14 15:37:56 (GMT)
committerGitHub <noreply@github.com>2023-11-14 15:37:56 (GMT)
commitee06fffd38cb51ce1c045da9d8336d9ce13c318a (patch)
tree764d92fd0d9f750b2973004c2e7f46c91299adbf /Modules/_io
parenta519b87958da0b340caef48349d6e3c23c98e47e (diff)
downloadcpython-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.c39
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;
}