]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
fix thread safety of `io.StringIO.truncate` (#133732)
authorKumar Aditya <kumaraditya@python.org>
Fri, 9 May 2025 07:59:17 +0000 (13:29 +0530)
committerGitHub <noreply@github.com>
Fri, 9 May 2025 07:59:17 +0000 (07:59 +0000)
Modules/_io/clinic/stringio.c.h
Modules/_io/stringio.c

index 8e8cd8df9ab8a15ce19c08a8d05f52f665d9e877..83165e5f7ad08bfd5b8304491ed324c0fe7aabf5 100644 (file)
@@ -149,13 +149,13 @@ PyDoc_STRVAR(_io_StringIO_truncate__doc__,
     {"truncate", _PyCFunction_CAST(_io_StringIO_truncate), METH_FASTCALL, _io_StringIO_truncate__doc__},
 
 static PyObject *
-_io_StringIO_truncate_impl(stringio *self, Py_ssize_t size);
+_io_StringIO_truncate_impl(stringio *self, PyObject *pos);
 
 static PyObject *
 _io_StringIO_truncate(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
 {
     PyObject *return_value = NULL;
-    Py_ssize_t size = ((stringio *)self)->pos;
+    PyObject *pos = Py_None;
 
     if (!_PyArg_CheckPositional("truncate", nargs, 0, 1)) {
         goto exit;
@@ -163,12 +163,10 @@ _io_StringIO_truncate(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
     if (nargs < 1) {
         goto skip_optional;
     }
-    if (!_Py_convert_optional_to_ssize_t(args[0], &size)) {
-        goto exit;
-    }
+    pos = args[0];
 skip_optional:
     Py_BEGIN_CRITICAL_SECTION(self);
-    return_value = _io_StringIO_truncate_impl((stringio *)self, size);
+    return_value = _io_StringIO_truncate_impl((stringio *)self, pos);
     Py_END_CRITICAL_SECTION();
 
 exit:
@@ -552,4 +550,4 @@ _io_StringIO_newlines_get(PyObject *self, void *Py_UNUSED(context))
 
     return return_value;
 }
-/*[clinic end generated code: output=5bfaaab7f41ee6b5 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=bccc25ef8e6ce9ef input=a9049054013a1b77]*/
index 9d1bfa3ea05ceab67663680678d623a961cb7b56..56913fafefba8b0670f4e1eeb39867c88b0a28ed 100644 (file)
@@ -444,7 +444,7 @@ stringio_iternext(PyObject *op)
 /*[clinic input]
 @critical_section
 _io.StringIO.truncate
-    pos as size: Py_ssize_t(accept={int, NoneType}, c_default="((stringio *)self)->pos") = None
+    pos: object = None
     /
 
 Truncate size to pos.
@@ -455,16 +455,26 @@ Returns the new absolute position.
 [clinic start generated code]*/
 
 static PyObject *
-_io_StringIO_truncate_impl(stringio *self, Py_ssize_t size)
-/*[clinic end generated code: output=eb3aef8e06701365 input=fa8a6c98bb2ba780]*/
+_io_StringIO_truncate_impl(stringio *self, PyObject *pos)
+/*[clinic end generated code: output=c76c43b5ecfaf4e2 input=d59fd2ee49757ae6]*/
 {
     CHECK_INITIALIZED(self);
     CHECK_CLOSED(self);
 
-    if (size < 0) {
-        PyErr_Format(PyExc_ValueError,
-                     "Negative size value %zd", size);
-        return NULL;
+    Py_ssize_t size;
+    if (pos == Py_None) {
+        size = self->pos;
+    }
+    else {
+        size = PyLong_AsLong(pos);
+        if (size == -1 && PyErr_Occurred()) {
+            return NULL;
+        }
+        if (size < 0) {
+            PyErr_Format(PyExc_ValueError,
+                         "negative pos value %zd", size);
+            return NULL;
+        }
     }
 
     if (size < self->string_size) {