Skip to content

struct: fix infinite loop in grow_buffer() for small sizes - #471

Merged
jow- merged 1 commit into
masterfrom
fix/struct-buf-put-empty
Oct 8, 2026
Merged

jow- merged 1 commit into
masterfrom
fix/struct-buf-put-empty

Conversation

@jow-

@jow- jow- commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator

The growth step in grow_buffer() was n += ((n >> 1) + 7u) & ~7u which adds 0 when new_size is small (<= 15), since (n>>1)+7 lands in [3,14] and rounding down to an 8-byte boundary yields 0. The loop then spins forever.

This is hit when a buffer is first grown with a zero-length size (which allocates a chunk but leaves capacity at 0), and then a subsequent put() needs to grow from that 0 capacity. e.g.:
b = struct.buffer()
b.put("", "") # grow to 0 -> data != NULL, capacity stays 0
b.put("
", "x") # grow from 0 -> infinite loop

Use +8u (not +7u) so the growth step is always >= 8 bytes and the loop always makes progress.

Fixes ucode -lstruct -p 'b=struct.buffer(); b.put("*",""); b.put("*","x")' hanging.

The growth step in grow_buffer() was `n += ((n >> 1) + 7u) & ~7u`
which adds 0 when new_size is small (<= 15), since (n>>1)+7 lands in
[3,14] and rounding down to an 8-byte boundary yields 0. The loop then
spins forever.

This is hit when a buffer is first grown with a zero-length size (which
allocates a chunk but leaves capacity at 0), and then a subsequent
put() needs to grow from that 0 capacity. e.g.:
    b = struct.buffer()
    b.put("*", "")   # grow to 0 -> data != NULL, capacity stays 0
    b.put("*", "x")  # grow from 0 -> infinite loop

Use +8u (not +7u) so the growth step is always >= 8 bytes and the loop
always makes progress.

Fixes `ucode -lstruct -p 'b=struct.buffer(); b.put("*",""); b.put("*","x")'`
hanging.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
@jow-
jow- merged commit 0102932 into master Oct 8, 2026
3 checks passed
@jow-
jow- deleted the fix/struct-buf-put-empty branch October 8, 2026 13:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant