Repository navigation
bugc: compare bytes and strings by contents - #391
Merged
Merged
Conversation
Contributor
|
gnidan
added a commit
that referenced
this pull request
Oct 15, 2026
`==` and `!=` on dynamic bytes or strings compared the two memory addresses, so equal contents in two places compared unequal. Compare the keccak256 of each operand's data instead.
Code generation and constant folding each encoded a string constant from its text: folding hashed a long hex literal as ASCII, and code generation decoded a string starting with "0x" as hex. Both now use one function that encodes by the constant's type.
gnidan
added a commit
that referenced
this pull request
Oct 15, 2026
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.
==and!=on dynamicbytesorstringcompiled to a comparison of the two memory addresses, so equal contents in two places compared unequal. Inexamples/advanced/token-registry.bug, every selector check comparesbytescopied from calldata againstbytessliced from a hash, so no selector ever matched.The type checker already accepts
==between twobytesor twostringvalues in memory (and rejects them in calldata), and the token registry example is written to compare contents, as is amapping<bytes, …>key. So this makes the operator do what the language already says it does, instead of rejecting it: irgen now emits ahashof each operand's data and compares the two hashes. Thehashinstruction already hashes the data of a single memory reference, so evmgen needs no change. Different lengths give different hashes, so there is no separate length check.bytesNare values and still compare as words.Comparing against literals exposed a second bug, fixed here too. Code generation and constant folding each turned a
bytesorstringconstant into bytes from its text alone: folding hashed a hex literal longer than 32 bytes as ASCII text (sob == 0x<33 bytes>andkeccak256(0x<33 bytes>)were wrong at O1–O3), and code generation decoded a string literal that starts with "0x", such as"0x12", as hex (wrong at O0). Both now use one function,Ir.Utils.constantBytes, which encodes by the constant's type: astringas UTF-8,bytesfrom their hex.Tests run
==and!=at O0–O3 onbytesandstringcopies from calldata (equal and unequal contents, different lengths, empty, and lengths around 32 bytes), against a string literal, and against a string in storage. Others compare and hash a 33-byte hex literal and the string"0x12"(also cast tobytes), with the same results at every level. The type checker tests cover the accepted forms and the errors forbytes == stringandbytes == bytes4. The case study gains a short "Equality" section, and says to cast or copy bytes in calldata to memory before comparing them.The only program whose code changes is
token-registry.bug, at every level (the activation-pairing digest snapshot is updated for it). With this change and #388, its selectors match at O0–O3, so the example can lose its@wipmarker in a follow-up.