8000 Undefined behavior with %q format specifier on LP64 and I16LP32 targets · Issue #17540 · micropython/micropython · GitHub
[go: up one dir, main page]

Skip to content
Undefined behavior with %q format specifier on LP64 and I16LP32 targets #17540
Open
@jepler

Description

@jepler

Port, board and/or hardware

Windows x64

MicroPython version

MicroPython v1.26.0-preview.265.gd134cdb9a3.dirty build-vs (x64, Debug, dev, 2017)

Reproduction

  1. Enable sys_settrace in a windows build
  2. run a program that prints a frame object

Expected behaviour

The frame object can be printed.

Observed behaviour

Frequently, this will cause an assertion error, as it did in this run of #17538 which adds a test of frame object printing.

Run python run-tests.py --print-failures
--- D:/a/micropython/micropython/tests/results\misc_sys_settrace_cov.py.exp	2025-06-20 18:41:30.413152600 +0000
+++ D:/a/micropython/micropython/tests/results\misc_sys_settrace_cov.py.out	2025-06-20 18:41:30.413152600 +0000
@@ -1,2 +1,2 @@
-FRAME <frame at 0x\[0-9a-f\]\+, file 'misc/sys_settrace_repr\.py', line \\d\+, code f>
-LASTI \\d\+
+FRAME <frame at 0xe06df4a0, file 'D:/a/micropython/micropython/tests/misc/sys_settrace_cov.py', line 20, code Assertion failed: *q < pool->len, file d:\a\micropython\micropython\py\qstr.c, line 198
+CRASH
\ No newline at end of file

FAILURE D:/a/micropython/micropython/tests/results\misc_sys_settrace_cov.py```

### Additional Information

I think there is a pervasive problem with %q in format strings depending on undefined behavior, at least on systems where sizeof(intptr_t) != sizeof(int).

Take for example this line in `objtype.c`:
```c
mp_printf(print, "<class '%q'>", self->name);

The type of the expression self->name is uint16_t. when it is passed through ... it is promoted according to "default argument promotions". On all platforms of interest, I think this means that it is promoted to int.

In mp_vprintf, it is retrieved with a type of size_t, due to typedef size_t qstr in qstr.h:

            case 'q': {
                qstr qst = va_arg(args, qstr);

However, on platforms like x64 windows ("LP64"), these are two distinct integer types of different size.

In practice, the actual argument passing practice of msvc prevents an overt misbehavior in many cases, except for this one in the frame printing code for sys_settrace with one specific msvc version.

The same problem would affect I16LP32 ports. I encountered this trying to create an I16LP32 port based on m68k where the problem seems to affect just about any use of %q with an int16 argument. for example, the int object is unprintable in the repl due to this.

Code of Conduct

Yes, I agree

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0