Skip to content

🐞 Fix Base58 decodeWord sanitizer ordering - #1544

Merged
atarpara merged 1 commit into
Vectorized:base58-fixfrom
cristianizzo:fix/base58-decodeword-sanitizer-ordering
Aug 2, 2026
Merged

🐞 Fix Base58 decodeWord sanitizer ordering#1544
atarpara merged 1 commit into
Vectorized:base58-fixfrom
cristianizzo:fix/base58-decodeword-sanitizer-ordering

Conversation

@cristianizzo

@cristianizzo cristianizzo commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Fixes #1543.

Base58.decodeWord performed mload(c) (the lookup-table read) before validating that the input character is a valid Base58 character. For an input byte below '1' (0x31) — e.g. '0' (0x30) — the index c = byte - 49 underflows to ~2²⁵⁶, so mload(c) expands memory past the block gas limit and the call reverts with out-of-gas instead of a clean Base58DecodingError.

This mirrors the ordering already used in decode: validate the character with the shl(c, 1) bitmask check before mload(c), then perform the multiplication/addition overflow check.

Test

Added testDecodeWordLowCharacterReverts, which asserts decodeWord("0") (and a \x00 byte) now revert with Base58DecodingError. It fails on the current code (the call OOGs, reverting without the selector) and passes with this fix. The existing differential, overflow, and fuzz tests continue to pass under both the default and --via-ir profiles.

Note

The character check must gate mload(c), so the two conditions can't be folded back into the original single masked check without reintroducing the ordering bug. I kept them as two Base58DecodingError reverts for clarity/correctness — happy to golf the second revert block if you'd prefer.

Copilot AI review requested due to automatic review settings July 25, 2026 23:07

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

Fixes a sanitizer ordering bug in Base58.decodeWord where an out-of-bounds lookup-table read (mload(c)) could occur before validating the input character, causing pathological memory expansion and out-of-gas instead of reverting with Base58DecodingError.

Changes:

  • Reorders decodeWord validation to check the Base58 character bitmask before the lookup-table read.
  • Separates character validation from overflow checks for clearer failure modes.
  • Adds a regression test asserting low ASCII bytes (e.g. "0" and 0x00) revert cleanly with Base58DecodingError.

Reviewed changes

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

File Description
src/utils/Base58.sol Validates the character before table lookup in decodeWord to prevent OOG on underflowed indices.
test/Base58.t.sol Adds a regression test ensuring low-character inputs revert with Base58DecodingError.

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

`decodeWord` performed `mload(c)` before validating the character, so an
input byte below `'1'` (0x31) underflowed the lookup index and expanded
memory, reverting with out-of-gas instead of a clean `Base58DecodingError`.
Validate the character before the load (as `decode` already does), then
perform the multiplication/addition overflow check.
@cristianizzo
cristianizzo force-pushed the fix/base58-decodeword-sanitizer-ordering branch from 34f981e to 13703dc Compare July 26, 2026 12:42
@atarpara
atarpara changed the base branch from main to base58-fix August 2, 2026 05:58
@atarpara
atarpara merged commit 5ecd2c1 into Vectorized:base58-fix Aug 2, 2026
atarpara added a commit that referenced this pull request Aug 2, 2026
* 🐞 Fix Base58 `decodeWord` sanitizer ordering (#1544)

* Added TestCase

---------

Co-authored-by: 0x1220c <cristianizzo@me.com>
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.

🐞 Incorrect Sanitizer Ordering for Base58 decodeWord

3 participants