mirror of
https://github.com/python/cpython.git
synced 2026-01-06 15:32:22 +00:00
[3.11] bpo-31718: Fix io.IncrementalNewlineDecoder SystemErrors and segfaults (GH-18640) (#99841)
Co-authored-by: Oren Milman <orenmn@gmail.com>
Co-authored-by: Zackery Spytz <zspytz@gmail.com>
Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
(cherry picked from commit 53eef27133)
This commit is contained in:
parent
1e327059a3
commit
6f658dd60d
3 changed files with 32 additions and 11 deletions
|
|
@ -3931,7 +3931,15 @@ def test_translate(self):
|
|||
self.assertEqual(decoder.decode(b"\r\r\n"), "\r\r\n")
|
||||
|
||||
class CIncrementalNewlineDecoderTest(IncrementalNewlineDecoderTest):
|
||||
pass
|
||||
@support.cpython_only
|
||||
def test_uninitialized(self):
|
||||
uninitialized = self.IncrementalNewlineDecoder.__new__(
|
||||
self.IncrementalNewlineDecoder)
|
||||
self.assertRaises(ValueError, uninitialized.decode, b'bar')
|
||||
self.assertRaises(ValueError, uninitialized.getstate)
|
||||
self.assertRaises(ValueError, uninitialized.setstate, (b'foo', 0))
|
||||
self.assertRaises(ValueError, uninitialized.reset)
|
||||
|
||||
|
||||
class PyIncrementalNewlineDecoderTest(IncrementalNewlineDecoderTest):
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
Raise :exc:`ValueError` instead of :exc:`SystemError` when methods of
|
||||
uninitialized :class:`io.IncrementalNewlineDecoder` objects are called.
|
||||
Patch by Oren Milman.
|
||||
|
|
@ -231,17 +231,16 @@ _io_IncrementalNewlineDecoder___init___impl(nldecoder_object *self,
|
|||
PyObject *errors)
|
||||
/*[clinic end generated code: output=fbd04d443e764ec2 input=89db6b19c6b126bf]*/
|
||||
{
|
||||
self->decoder = decoder;
|
||||
Py_INCREF(decoder);
|
||||
|
||||
if (errors == NULL) {
|
||||
self->errors = &_Py_ID(strict);
|
||||
errors = Py_NewRef(&_Py_ID(strict));
|
||||
}
|
||||
else {
|
||||
self->errors = errors;
|
||||
errors = Py_NewRef(errors);
|
||||
}
|
||||
Py_INCREF(self->errors);
|
||||
|
||||
Py_XSETREF(self->errors, errors);
|
||||
Py_XSETREF(self->decoder, Py_NewRef(decoder));
|
||||
self->translate = translate ? 1 : 0;
|
||||
self->seennl = 0;
|
||||
self->pendingcr = 0;
|
||||
|
|
@ -276,6 +275,13 @@ check_decoded(PyObject *decoded)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define CHECK_INITIALIZED_DECODER(self) \
|
||||
if (self->errors == NULL) { \
|
||||
PyErr_SetString(PyExc_ValueError, \
|
||||
"IncrementalNewlineDecoder.__init__() not called"); \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
#define SEEN_CR 1
|
||||
#define SEEN_LF 2
|
||||
#define SEEN_CRLF 4
|
||||
|
|
@ -289,11 +295,7 @@ _PyIncrementalNewlineDecoder_decode(PyObject *myself,
|
|||
Py_ssize_t output_len;
|
||||
nldecoder_object *self = (nldecoder_object *) myself;
|
||||
|
||||
if (self->decoder == NULL) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"IncrementalNewlineDecoder.__init__ not called");
|
||||
return NULL;
|
||||
}
|
||||
CHECK_INITIALIZED_DECODER(self);
|
||||
|
||||
/* decode input (with the eventual \r from a previous pass) */
|
||||
if (self->decoder != Py_None) {
|
||||
|
|
@ -507,6 +509,8 @@ _io_IncrementalNewlineDecoder_getstate_impl(nldecoder_object *self)
|
|||
PyObject *buffer;
|
||||
unsigned long long flag;
|
||||
|
||||
CHECK_INITIALIZED_DECODER(self);
|
||||
|
||||
if (self->decoder != Py_None) {
|
||||
PyObject *state = PyObject_CallMethodNoArgs(self->decoder,
|
||||
&_Py_ID(getstate));
|
||||
|
|
@ -551,6 +555,8 @@ _io_IncrementalNewlineDecoder_setstate(nldecoder_object *self,
|
|||
PyObject *buffer;
|
||||
unsigned long long flag;
|
||||
|
||||
CHECK_INITIALIZED_DECODER(self);
|
||||
|
||||
if (!PyTuple_Check(state)) {
|
||||
PyErr_SetString(PyExc_TypeError, "state argument must be a tuple");
|
||||
return NULL;
|
||||
|
|
@ -581,6 +587,8 @@ static PyObject *
|
|||
_io_IncrementalNewlineDecoder_reset_impl(nldecoder_object *self)
|
||||
/*[clinic end generated code: output=32fa40c7462aa8ff input=728678ddaea776df]*/
|
||||
{
|
||||
CHECK_INITIALIZED_DECODER(self);
|
||||
|
||||
self->seennl = 0;
|
||||
self->pendingcr = 0;
|
||||
if (self->decoder != Py_None)
|
||||
|
|
@ -592,6 +600,8 @@ _io_IncrementalNewlineDecoder_reset_impl(nldecoder_object *self)
|
|||
static PyObject *
|
||||
incrementalnewlinedecoder_newlines_get(nldecoder_object *self, void *context)
|
||||
{
|
||||
CHECK_INITIALIZED_DECODER(self);
|
||||
|
||||
switch (self->seennl) {
|
||||
case SEEN_CR:
|
||||
return PyUnicode_FromString("\r");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue