Skip to content

gh-154387: validate PyStructSequence_Desc field invariants#154684

Open
XuehaiPan wants to merge 2 commits into
python:mainfrom
XuehaiPan:fix-structseq-validate-desc
Open

gh-154387: validate PyStructSequence_Desc field invariants#154684
XuehaiPan wants to merge 2 commits into
python:mainfrom
XuehaiPan:fix-structseq-validate-desc

Conversation

@XuehaiPan

@XuehaiPan XuehaiPan commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

The current PyStructSequence related code is heavily under the assumptions:

  • {any unnamed field} in {visible range}
  • n_unnamed <= n_in_sequence and n_in_sequence <= n_fields

but we never validate these constraints. Data can be silently lost (unaccessible) if an unnamed field is defined out of the visible range, i.e., the data cannot be accessed either from slicing seq[i] or member lookup seq.name.

This PR enforces the constraints mentioned above. count_members() now raises SystemError (returning -1) when a struct sequence descriptor places an unnamed field outside the visible sequence fields, or when n_in_sequence exceeds the total number of fields; such descriptors previously built a malformed type. The failure is propagated by PyStructSequence_NewType(), PyStructSequence_InitType() and PyStructSequence_InitType2().

Add _testcapi helpers and regression tests for both rejected cases, and document the invariants in the C API reference.

`count_members()` now raises `SystemError` (returning `-1`) when a struct
sequence descriptor places an unnamed field outside the visible sequence
fields, or when `n_in_sequence` exceeds the total number of fields; such
descriptors previously built a malformed type. The failure is propagated by
`PyStructSequence_NewType()`, `PyStructSequence_InitType()` and
`PyStructSequence_InitType2()`.

Add `_testcapi` helpers and regression tests for both rejected cases, and
document the invariants in the C API reference.
@read-the-docs-community

read-the-docs-community Bot commented Jul 25, 2026

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #33755524 | 📁 Comparing a06b349 against main (bff0051)

  🔍 Preview build  

2 files changed
± c-api/tuple.html
± whatsnew/changelog.html

…ifiers

count_members() now rejects a PyStructSequence_Desc whose n_in_sequence is
negative, completing the bounds check (only n_in_sequence <= n_fields was
enforced before). A negative value otherwise inflated tp_basicsize and failed
later with a cryptic SystemError from PyTuple_New().

Also fix the two existing error messages: n_in_sequence is an int but was
printed with %zd (Py_ssize_t), which is undefined behavior in a variadic call.

Add a _testcapi helper and regression test for the negative case, and document
the non-negative constraint.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant