Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the vulnerability found in issue #3861 #3863

Merged
merged 15 commits into from
Feb 10, 2025

Conversation

Lexterl33t
Copy link
Contributor

Fix the vulnerability found in issue #3861

Description

This PR addresses the non-compliance issue with the PUSHN opcodes in EthereumJS, as described in issue #3861.

Previously, when a PUSH instruction had fewer bytes available than required, the missing bytes were not properly zero-padded to align with the Ethereum Yellow Paper specification.

This led to inconsistencies between EthereumJS and other EVM implementations like REVM and SputnikVM, which correctly apply right-aligned zero-padding.


Fix Implemented

  • Ensured that PUSHN opcodes always zero-pad missing bytes, right-aligning the values as per the Yellow Paper.
  • Added a test case to validate that the stack correctly returns the padded value.

mhoste51 and others added 2 commits February 3, 2025 16:24
Co-authored-by: Lexterl33t <bryton@fuzzinglabs.com>
Co-authored-by: mhoste51 <mathieu@fuzzinglabs.com>
Copy link

codecov bot commented Feb 4, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 75.51%. Comparing base (1774df6) to head (707c90f).
Report is 1 commits behind head on master.

Additional details and impacted files

Impacted file tree graph

Flag Coverage Δ
block 76.87% <ø> (ø)
blockchain 85.69% <ø> (ø)
client 66.26% <ø> (ø)
common 90.31% <ø> (ø)
devp2p 76.21% <ø> (-0.07%) ⬇️
ethash 81.04% <ø> (ø)
evm 69.39% <100.00%> (+0.04%) ⬆️
genesis 99.84% <ø> (ø)
mpt 59.92% <ø> (-0.21%) ⬇️
rlp 69.70% <ø> (ø)
statemanager 70.15% <ø> (ø)
tx 80.52% <ø> (ø)
util 85.16% <ø> (ø)
vm 57.81% <ø> (ø)
wallet 83.78% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Copy link
Member

@jochem-brouwer jochem-brouwer left a comment

Choose a reason for hiding this comment

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

Some initial comments! 😄 👍

jochem-brouwer
jochem-brouwer previously approved these changes Feb 10, 2025
@jochem-brouwer
Copy link
Member

LGTM, thanks, will leave this open for one more review. Have changed the code to run minimal extra logic per PUSH (only a length check) and in the edge case of the PUSH being at the end of the code, then setLengthRight will be called on the bytes. Have also expanded the tests to test all PUSH opcodes PUSH1-PUSH32 for this case.

@jochem-brouwer jochem-brouwer linked an issue Feb 10, 2025 that may be closed by this pull request
@jochem-brouwer jochem-brouwer dismissed their stale review February 10, 2025 18:27

Wait, never mind, this does not fix the case if jump analysis has been done:

      if (!runState.shouldDoJumpAnalysis) {
        runState.stack.push(runState.cachedPushes[runState.programCounter])
        runState.programCounter += numToPush
// This case is still wrong
      } else {
        let loadedBytes = runState.code.subarray(
          runState.programCounter,
          runState.programCounter + numToPush,
        )
        if (loadedBytes.length < numToPush) {
          loadedBytes = setLengthRight(loadedBytes, numToPush)
        }

        runState.programCounter += numToPush
        runState.stack.push(bytesToBigInt(loadedBytes))
      }
@jochem-brouwer
Copy link
Member

Ok, interesting, I just realized that the original code only fixes in the case if there is no JUMPDEST analysis being done. In practice / live networks, this is always done: it is necessary to find if the target we are JUMPing to is a valid JUMPDEST (and not a byte which looks like JUMPDEST but which is actually part of a PUSH opcode). So once a contract hits their first (succesful) JUMP we have to do the analysis. This is a more complex test case than the simple test case of "just" the code of truncated PUSH opcodes, but it would be interesting to see if the fuzzer would also find this, more complex case :)

Copy link
Contributor

@acolytec3 acolytec3 left a comment

Choose a reason for hiding this comment

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

LGTM

@jochem-brouwer jochem-brouwer merged commit a1f5de0 into ethereumjs:master Feb 10, 2025
40 of 41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[SECURITY] Ethereumjs PUSHN Opcode Non-Compliance
5 participants