Skip to content

Conversation

@cfallin
Copy link
Member

@cfallin cfallin commented Apr 1, 2025

In #196, various breaks and early returns` out of a main allocator loop were changed to pass through a point that returned scratch storage to a context for later reuse.

Unfortunately, this refactor introduced a bug: a break became a break 'outer, and the latter meant that we were skipping some checks.

Fortunately this only happens in a code-path where the given allocation problem has too many constraints, and it means that we get a panic rather than a TooManyLiveRegs error cleanly returned, so this is not a security issue. However, it has me a little paranoid and we should carefully re-audit #196's changes when we get a chance.

(Discovered while making changes to ABI code that caused too many defs constrained to regs, resulting in an un-allocatable input; not reachable from mainline Cranelift.)

cc @jakubDoka

In bytecodealliance#196, various `break`s and early returns` out of a main allocator
loop were changed to pass through a point that returned scratch storage
to a context for later reuse.

Unfortunately, this refactor introduced a bug: a `break` became a `break
'outer`, and the latter meant that we were skipping some checks.

Fortunately this only happens in a code-path where the given allocation
problem has too many constraints, and it means that we get a panic
rather than a `TooManyLiveRegs` error cleanly returned, so this is not a
security issue. However, it has me a little paranoid and we should
carefully re-audit bytecodealliance#196's changes when we get a chance.

(Discovered while making changes to ABI code that caused too many defs
constrained to regs, resulting in an un-allocatable input; not reachable
from mainline Cranelift.)
@cfallin cfallin requested a review from fitzgen April 1, 2025 07:00
Copy link
Member

@fitzgen fitzgen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know why the checker didn't catch this during fuzzing?

@cfallin
Copy link
Member Author

cfallin commented Apr 1, 2025

That's a great question; I suspect it has to do with our fuzzing function generator which adds up to four operands to any instruction and up to five clobbers. That would be sufficient to hit this if we had a smaller register environment but we have 32 registers per class. All of this provides sufficient coverage for everything but calls; and I suspect we haven't had any hits from higher-level fuzzing because the use-cases we generate were shaped in a particular way (only defs are fixed defs, per the ABI, so everything fits). I'll poke at this when I get some more time.

@cfallin cfallin merged commit a5a80be into bytecodealliance:main Apr 1, 2025
6 checks passed
@cfallin cfallin deleted the fix-broken-break-that-breaks-in-a-broken-way branch April 1, 2025 17:19
@cfallin cfallin mentioned this pull request Apr 1, 2025
cfallin added a commit that referenced this pull request Apr 1, 2025
Includes fix from #212.
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.

2 participants