Skip to content

CPython: struct fields take dicts, and a wrong type raises instead of segfaulting - #23

Merged
bdbarnett merged 1 commit into
mainfrom
fix/21-struct-value-type
Sep 26, 2026
Merged

bdbarnett merged 1 commit into
mainfrom
fix/21-struct-value-type

Conversation

@bdbarnett

Copy link
Copy Markdown
Contributor

Fixes #21.

On CPython, lv.image_dsc_t({"header": {"w": 4}}), dsc.header = {"w": 4} and dsc.header = 5 all segfaulted. The by-value macro mp_write_<struct>(value) was *(T*)mp_write_ptr_<struct>(value), and the pointer function returns NULL for anything that isn't that struct type.

What it does now (CPython emitter only; MicroPython and CircuitPython output is unchanged):

  • A dict builds the struct the way the type's own constructor does, and the copy goes in. MicroPython already does this, and both give the same result: dsc.header = {"w": 7} leaves w=7, h=0 on each.
  • Anything else, None included, raises TypeError and yields a zeroed scratch copy, so nothing dereferences NULL. Function wrappers already returned NULL on PyErr_Occurred(). Setters now do the same, and they first put the struct back as it was, because the placeholder has already been stored by then. The first version of this missed that, and the smoke test caught it.
  • A struct with no fields keeps the old macro, since there's no size to give a scratch copy.

What I ran:

  • pytest tests: 111 passed. The two new generator tests fail on main.
  • ./regenerate_all.sh --check: all generated artifacts match.
  • Built the CPython extension from lvgl-python main with this lvgl_python.c, on Linux with Python 3.12. tools/test_lvgl_smoke.py, with the new test_struct_value_from_dict, printed "All LVGL smoke tests passed.", and lvgl-python's unit tests passed (6 OK). The same smoke test dumps core on the current 9.5.47 build.
  • The issue's repro on the new build: the nested dict constructs 4 3 12, and 5, None and "x" each raise TypeError.
  • MicroPython unix, on the released bindings: the new smoke test passes. It accepts MicroPython's own exception type for a wrong value, which is SyntaxError.

Not run: the Windows (MSVC) and Pyodide builds. The new C uses only the Python 3.11 C API and standard C.

The fix reaches users when lvgl-python syncs past this commit and a release is cut.

…faults

The by-value macro dereferenced mp_write_ptr_*'s NULL whenever the value
wasn't an instance of the struct's type. It now takes a dict the way the
type's constructor does, as MicroPython does, and for anything else sets
TypeError and yields a zeroed scratch copy that is never kept: a setter
puts the struct back as it was and returns -1, and function wrappers
already return NULL on PyErr_Occurred().

Fixes #21
@bdbarnett
bdbarnett merged commit 7316c48 into main Sep 26, 2026
4 checks passed
@bdbarnett
bdbarnett deleted the fix/21-struct-value-type branch September 26, 2026 22:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

CPython: a struct field set from a dict (or any wrong type) segfaults

1 participant