Skip to content

Commit 52c00eb

Browse files
Fix structseq_repr indexing to prevent unnamed fields mislabeling
1 parent 7eb8c27 commit 52c00eb

2 files changed

Lines changed: 24 additions & 12 deletions

File tree

Lib/test/test_structseq.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,15 @@ def test_repr(self):
4848
self.assertIn("st_ino=", rep)
4949
self.assertIn("st_dev=", rep)
5050

51+
# Issue #154387: unnamed fields should not be mislabeled with named field names.
52+
st = os.stat_result(range(10))
53+
rep = repr(st)
54+
self.assertEqual(
55+
rep,
56+
"os.stat_result(st_mode=0, st_ino=1, st_dev=2, st_nlink=3, "
57+
"st_uid=4, st_gid=5, st_size=6, 7, 8, 9)"
58+
)
59+
5160
def test_concat(self):
5261
t1 = time.gmtime()
5362
t2 = t1 + tuple(t1)

Objects/structseq.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -305,20 +305,23 @@ structseq_repr(PyObject *op)
305305
}
306306

307307
// Write name
308-
const char *name_utf8 = typ->tp_members[i].name;
309-
if (name_utf8 == NULL) {
310-
PyErr_Format(PyExc_SystemError,
311-
"In structseq_repr(), member %zd name is NULL"
312-
" for type %.500s", i, typ->tp_name);
313-
goto error;
314-
}
315-
if (PyUnicodeWriter_WriteUTF8(writer, name_utf8, -1) < 0) {
316-
goto error;
308+
const char *name_utf8 = NULL;
309+
Py_ssize_t expected_offset = offsetof(PyStructSequence, ob_item) + i * sizeof(PyObject*);
310+
for (Py_ssize_t k = 0; typ->tp_members[k].name != NULL; k++) {
311+
if (typ->tp_members[k].offset == expected_offset) {
312+
name_utf8 = typ->tp_members[k].name;
313+
break;
314+
}
317315
}
318316

319-
// Write "=" + repr(value)
320-
if (PyUnicodeWriter_WriteChar(writer, '=') < 0) {
321-
goto error;
317+
if (name_utf8 != NULL) {
318+
if (PyUnicodeWriter_WriteUTF8(writer, name_utf8, -1) < 0) {
319+
goto error;
320+
}
321+
// Write "="
322+
if (PyUnicodeWriter_WriteChar(writer, '=') < 0) {
323+
goto error;
324+
}
322325
}
323326
PyObject *value = PyStructSequence_GetItem((PyObject*)obj, i);
324327
assert(value != NULL);

0 commit comments

Comments
 (0)