Skip to content

fix: Read match arm members from the current section - #267

Open
scottanderson wants to merge 1 commit into
WerWolv:masterfrom
scottanderson:fix-match-section
Open

scottanderson wants to merge 1 commit into
WerWolv:masterfrom
scottanderson:fix-match-section

Conversation

@scottanderson

Copy link
Copy Markdown
Contributor

Problem

A primitive declared in a match arm reads its value from the main section. This occurs when its struct is placed in a custom section with @ ... in section. Members in an if body, in a try/catch body, and structs in a match arm read from the correct section.

struct S {
    u32 plain;
    match (plain) { (_): u32 inMatch; }
    if (true) { u32 inIf; }
};
S s @ 0 in section;

Here s.plain and s.inIf read from section, but s.inMatch reads from the main section at the same offset. The value is wrong during evaluation (for example std::print) and afterwards (for example the JSON formatter).

This breaks palworld.hexpat in ImHex-Patterns. It inflates a save into a section and parses it with gvas.hexpat. Each IntProperty, FloatProperty and similar property there is a primitive in a match arm.

Summary

ASTNodeConditionalStatement::createPatterns and ASTNodeTryCatchStatement::createPatterns set the current section on each new pattern before they push it into the scope. ASTNodeMatchStatement::createPatterns did not. This PR adds the same line:

 for (auto &pattern : newPatterns) {
+    pattern->setSection(evaluator->getSectionId());
     scope.push_back(std::move(pattern));
 }

No other statement node has this gap. Compound statements and multi-variable declarations do not push into the scope. They return their patterns to the enclosing struct or union, which sets the section.

The new SectionStatements test places a struct in a section whose bytes differ from the main data. It asserts that each of these reads from the section: a plain member, a primitive in a match arm, an if body, a try body, a catch body, a nested struct, and a struct in a match arm.

Evidence

  • Without the fix, SectionStatements fails with assertion failed "Match arm member did not read from section". All other tests pass.
  • With the fix, all 80 tests pass.

Merge Danger

Door: two-way

A primitive in a match arm in a custom section now reads from that section. Reverting gives back the old behavior.

Blast Radius: small

Only patterns that place a struct in a custom section and declare a primitive directly in a match arm see a change. Those patterns read wrong values today.

A primitive in a match arm read its value from the main section.
This occurred when its struct was placed in a custom section.
The match statement did not set the section on its patterns.
The if and try/catch statements already do this.

This branch has not been deployed

No deployments
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