Avoid undefined pointer subtraction when flushNumber/flushString are called at EOF with dataBegin/buf/writeBuf set to nullptr. Compute the scalar length by casting the pointers to intptr_t before subtracting, which is well-defined and matches the desired byte offset (zero when both pointers are null). Keep the empty-string fallback for the callback data pointer when it would otherwise be null.
Closes #40
Avoid undefined pointer subtraction when `flushNumber`/`flushString` are called at EOF with `dataBegin`/`buf`/`writeBuf` set to `nullptr`. Compute the scalar length by casting the pointers to `intptr_t` before subtracting, which is well-defined and matches the desired byte offset (zero when both pointers are null). Keep the empty-string fallback for the callback data pointer when it would otherwise be null.
When a scalar ends exactly at a chunk boundary, Parser3::parse resets
dataBegin and writeBuf to the new buf at the start of every call. On the
EOF call buf is null, so both pointers become null. The final
flushNumber/flushString then computed len as buf - dataBegin, i.e.
nullptr - nullptr, which is undefined behaviour in C++.
Compute the flush length safely: if dataBegin is null (or, for raw mode,
buf is null), treat the length as zero. Use an empty string literal as a
non-null data pointer for the zero-length, done=true callback so callers
still receive the completion signal.
Add a regression test covering a number that fills its chunk exactly and
is finalized by an EOF call.
Fixes#40
andrew
requested changes 2026-06-29 18:36:49 +00:00
This is giving us slightly worse codegen. Does the UB go away if we cast to uintptr_t or intptr_t before subtracting?
Actually apparently this isn't even UB[0]. Just add a comment so we don't file this issue again.
[0]:
5.7 Additive operators [expr.add]
...
8 If the value 0 is added to or subtracted from a pointer value, the
result compares equal to the original pointer value. If two pointers
point to the same object or function or both point one past the end of
the same array or both are null, and the two pointers are subtracted,
the result compares equal to the value 0 converted to the type
ptrdiff_t.
~~This is giving us slightly worse codegen. Does the UB go away if we cast to uintptr_t or intptr_t before subtracting?~~
Actually apparently this isn't even UB[0]. Just add a comment so we don't file this issue again.
[0]:
```
5.7 Additive operators [expr.add]
...
8 If the value 0 is added to or subtracted from a pointer value, the
result compares equal to the original pointer value. If two pointers
point to the same object or function or both point one past the end of
the same array or both are null, and the two pointers are subtracted,
the result compares equal to the value 0 converted to the type
ptrdiff_t.
```
Andrew's review on the previous fix noted that the nullptr checks produced slightly worse codegen. Replace the pointer subtraction with intptr_t subtraction, which avoids the undefined behaviour of subtracting two null pointers without introducing extra branches.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #40
Avoid undefined pointer subtraction when
flushNumber/flushStringare called at EOF withdataBegin/buf/writeBufset tonullptr. Compute the scalar length by casting the pointers tointptr_tbefore subtracting, which is well-defined and matches the desired byte offset (zero when both pointers are null). Keep the empty-string fallback for the callback data pointer when it would otherwise be null.This is giving us slightly worse codegen. Does the UB go away if we cast to uintptr_t or intptr_t before subtracting?Actually apparently this isn't even UB[0]. Just add a comment so we don't file this issue again.
[0]:
Pull request closed