fix(vm): tag binary-op result with the wider operand type (Susie's outfit crash)#360
Open
Ananim353 wants to merge 1 commit into
Open
fix(vm): tag binary-op result with the wider operand type (Susie's outfit crash)#360Ananim353 wants to merge 1 commit into
Ananim353 wants to merge 1 commit into
Conversation
The arithmetic and bitwise handlers tagged the result slot's gmlStackType
with instrType2(instr). A numeric binary op's result should take the WIDER
of the two operand types; when type1 is wider than type2 (e.g. add.v.i,
Variable + int) the result was mis-tagged as the narrow type (INT32, 4B)
instead of Variable (16B). gmlStackType drives the byte-count model in
bytesToSlotCount (used by the Dup swap variant and BC17 BREAK sub-opcodes),
so the mismatch makes the byte walk overshoot a slot boundary and abort at
require(remaining == 0).
Reproduces in DELTARUNE Chapter 5, Susie's outfit ("thrashfit") menu:
option.init(id, label, names, flag, 170 + ja_offset) compiles the last
argument to add.v.i with no following Conv, feeding a .v Dup-swap arg list;
the mis-tagged INT32 slot makes the 5 args sum to 68 bytes instead of 80.
Introduce binaryResultType() and use it at every binary-op result-tag site.
It differs from instrType2 only when type1 is strictly wider than type2 (the
buggy case), so it cannot regress code that currently works. gmlStackType is
read only by bytesToSlotCount, so widening the tag never changes a value's
runtime interpretation.
Collaborator
|
Can confirm this fixes the crash |
Collaborator
|
How did you find this was the issue? |
Author
To be honest, I spent several hours creating this fix using AI, so the answer below comes from it. On a PSP port it was a silent |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Arithmetic and bitwise handlers tag the result slot's
gmlStackTypewithinstrType2(instr)(OP_ADD/SUB/MUL fast+slow, handleDiv/Rem/Mod, the bitwisemacro). A numeric binary op's result should take the wider of the two
operand types. When
type1is wider thantype2— e.g.add.v.i(Variable +int) — the result is mis-tagged as the narrow type (INT32, 4 bytes) instead of
Variable (16 bytes). Since
gmlStackTypedrives the byte-count model inbytesToSlotCount(used by theDupswap variant and BC17BREAKsub-opcodes), the mismatch makes the byte walk overshoot a slot boundary and
abort at
require(remaining == 0).Reproduce
DELTARUNE Chapter 5, Susie's outfit ("thrashfit") menu —
obj_ch5_LW07_thrashfit_menu.show_menucallsoption.init(id, label, names, flag, 170 + ja_offset). The last argument170 + ja_offsetcompiles toadd.v.iwith no followingConvand flowsstraight into the
dup.vswap that arranges the 5-argument method call. Theswap expects
5 * sizeof(Variable) = 80bytes; the mis-tagged INT32 argumentmakes the real slots sum to
4 + 16*4 = 68→remaining = -4→ abort. Thepreceding 4-argument
init(all Variables,64 = 4*16) is fine, so it abortsprecisely on the first right-column option.
Fix
Used at every binary-op result-tag site. It differs from
instrType2onlywhen
type1is strictly wider thantype2(the buggy case), so it cannotregress working code.
gmlStackTypeis read only bybytesToSlotCount, sowidening the tag never changes a value's runtime interpretation — only the
byte-count model.
Relation to #340
Fixes the same crash as #340 ("Susie's outfit"), but at the root cause — the
mis-tagged operand — instead of changing the
Dupswap decoding. Because itleaves the
Dup/bytesToSlotCountbyte-count model untouched, it does notaffect legitimate mixed-width
Dup-swaps, so it should avoid the save-menu /save-deletion regression noted on #340.
Verification
object-index-iteration,struct-get-names,simple-structs-methods-and-dynamic-methods).previously aborted at
require(remaining == 0), now opens correctly.