Skip to content

Match wide local variable instruction length to dumped bytes#525

Merged
garydgregory merged 1 commit into
apache:masterfrom
rootvector2:wide-localvar-length
Jul 18, 2026
Merged

Match wide local variable instruction length to dumped bytes#525
garydgregory merged 1 commit into
apache:masterfrom
rootvector2:wide-localvar-length

Conversation

@rootvector2

Copy link
Copy Markdown
Contributor

LocalVariableInstruction.initFromFile hardcodes length 4 for any wide-prefixed load or store, but dump() writes the wide prefix only when the index is above Const.MAX_BYTE. A wide iload 5 is legal bytecode whose index fits in a byte, so it parses with getLength() 4 while dump() emits 2 bytes. I hit this auditing wide handling against RET and IINC, which persist the parsed flag and keep the two in sync.

InstructionList.setPositions accumulates getLength(), so rebuilding a parsed method that carries one of these instructions shifts every following instruction 2 bytes and corrupts the branch offsets that span it. Deriving the parsed length from the same wide() test dump() already uses keeps length and emitted bytes in agreement, leaving the compact and non-wide paths untouched.

  • Read the contribution guidelines for this project.
  • Read the ASF Generative Tooling Guidance if you use Artificial Intelligence (AI).
  • I used AI to create any part of, or all of, this pull request. Which AI tool was used to create this pull request, and to what extent did it contribute?
  • Run a successful build using the default Maven goal with mvn; that's mvn on the command line by itself.
  • Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible, but it is a best practice.
  • Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
  • Each commit in the pull request should have a meaningful subject line and body.

@garydgregory garydgregory changed the title match wide local variable instruction length to dumped bytes Match wide local variable instruction length to dumped bytes Jul 18, 2026
@garydgregory
garydgregory requested a review from Copilot July 18, 2026 14:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a bytecode round-tripping inconsistency for wide-prefixed local-variable load/store instructions by ensuring the parsed instruction length matches what dump() will actually emit. This prevents InstructionList.setPositions() from accumulating an incorrect length and shifting subsequent instruction offsets when rebuilding methods.

Changes:

  • Update LocalVariableInstruction.initFromFile() to set length based on the same wide() condition used by dump(), instead of always forcing length 4 for wide-prefixed parses.
  • Add JUnit tests covering wide iload/istore cases where the parsed encoding is 4 bytes but the dumped encoding can be 2 bytes when the index fits in a byte.
  • Ensure large-index wide instructions remain 4 bytes and round-trip consistently.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/main/java/org/apache/bcel/generic/LocalVariableInstruction.java Aligns parsed length with emitted bytes by deriving length from wide() after reading the index.
src/test/java/org/apache/bcel/generic/LocalVariableInstructionTest.java Adds regression tests asserting getLength() matches dump() output for wide/non-wide edge cases.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@garydgregory
garydgregory merged commit 88916be into apache:master Jul 18, 2026
21 of 22 checks passed
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.

3 participants