Skip to content

Commit d69416d

Browse files
committed
gh-142831: Fix UAF in _json module
1 parent 89729f2 commit d69416d

File tree

1 file changed

+11
-25
lines changed

1 file changed

+11
-25
lines changed

Modules/_json.c

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1733,15 +1733,14 @@ _encoder_iterate_mapping_lock_held(PyEncoderObject *s, PyUnicodeWriter *writer,
17331733
PyObject *key, *value;
17341734
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(items); i++) {
17351735
PyObject *item = PyList_GET_ITEM(items, i);
1736-
#ifdef Py_GIL_DISABLED
1737-
// gh-119438: in the free-threading build the critical section on items can get suspended
1736+
1737+
// GH-142831: The item must be strong-referenced to avoid UAF
1738+
// if the user code modifies the list during iteration.
17381739
Py_INCREF(item);
1739-
#endif
1740+
17401741
if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 2) {
17411742
PyErr_SetString(PyExc_ValueError, "items must return 2-tuples");
1742-
#ifdef Py_GIL_DISABLED
17431743
Py_DECREF(item);
1744-
#endif
17451744
return -1;
17461745
}
17471746

@@ -1750,14 +1749,10 @@ _encoder_iterate_mapping_lock_held(PyEncoderObject *s, PyUnicodeWriter *writer,
17501749
if (encoder_encode_key_value(s, writer, first, dct, key, value,
17511750
indent_level, indent_cache,
17521751
separator) < 0) {
1753-
#ifdef Py_GIL_DISABLED
17541752
Py_DECREF(item);
1755-
#endif
17561753
return -1;
17571754
}
1758-
#ifdef Py_GIL_DISABLED
17591755
Py_DECREF(item);
1760-
#endif
17611756
}
17621757

17631758
return 0;
@@ -1772,24 +1767,20 @@ _encoder_iterate_dict_lock_held(PyEncoderObject *s, PyUnicodeWriter *writer,
17721767
PyObject *key, *value;
17731768
Py_ssize_t pos = 0;
17741769
while (PyDict_Next(dct, &pos, &key, &value)) {
1775-
#ifdef Py_GIL_DISABLED
1776-
// gh-119438: in the free-threading build the critical section on dct can get suspended
1770+
// GH-142831: The key and value must be strong-referenced to avoid UAF
1771+
// if the user code modifies the dict during iteration.
17771772
Py_INCREF(key);
17781773
Py_INCREF(value);
1779-
#endif
1774+
17801775
if (encoder_encode_key_value(s, writer, first, dct, key, value,
17811776
indent_level, indent_cache,
17821777
separator) < 0) {
1783-
#ifdef Py_GIL_DISABLED
17841778
Py_DECREF(key);
17851779
Py_DECREF(value);
1786-
#endif
17871780
return -1;
17881781
}
1789-
#ifdef Py_GIL_DISABLED
17901782
Py_DECREF(key);
17911783
Py_DECREF(value);
1792-
#endif
17931784
}
17941785
return 0;
17951786
}
@@ -1893,28 +1884,23 @@ _encoder_iterate_fast_seq_lock_held(PyEncoderObject *s, PyUnicodeWriter *writer,
18931884
{
18941885
for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(s_fast); i++) {
18951886
PyObject *obj = PySequence_Fast_GET_ITEM(s_fast, i);
1896-
#ifdef Py_GIL_DISABLED
1897-
// gh-119438: in the free-threading build the critical section on s_fast can get suspended
1887+
1888+
// GH-142831: The object must be strong-referenced to avoid UAF
1889+
// if the user code modifies the sequence during iteration.
18981890
Py_INCREF(obj);
1899-
#endif
1891+
19001892
if (i) {
19011893
if (PyUnicodeWriter_WriteStr(writer, separator) < 0) {
1902-
#ifdef Py_GIL_DISABLED
19031894
Py_DECREF(obj);
1904-
#endif
19051895
return -1;
19061896
}
19071897
}
19081898
if (encoder_listencode_obj(s, writer, obj, indent_level, indent_cache)) {
19091899
_PyErr_FormatNote("when serializing %T item %zd", seq, i);
1910-
#ifdef Py_GIL_DISABLED
19111900
Py_DECREF(obj);
1912-
#endif
19131901
return -1;
19141902
}
1915-
#ifdef Py_GIL_DISABLED
19161903
Py_DECREF(obj);
1917-
#endif
19181904
}
19191905
return 0;
19201906
}

0 commit comments

Comments
 (0)