Skip to content

Fix out-of-bounds read in GetNameSectionSubsectionName - #2801

Open
aizu-m wants to merge 2 commits into
WebAssembly:mainfrom
aizu-m:name-subsection-name-oob
Open

Fix out-of-bounds read in GetNameSectionSubsectionName#2801
aizu-m wants to merge 2 commits into
WebAssembly:mainfrom
aizu-m:name-subsection-name-oob

Conversation

@aizu-m

@aizu-m aizu-m commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

ASan, wasm2wat -v on a valid module whose name section carries one
unknown subsection (type LEB 0xffffffff):

binary.cc:66 GetNameSectionSubsectionName
READ of size 8 ... 8 bytes before global 'wabt::NameSubsectionName' (size 96)

Worked back from the read to the subsection id. NameSectionSubsection
has no explicit underlying type, so it is a signed int. ReadNameSection
reads the id into a uint32_t, casts it, and only gates the
OnNameSubsection callback with type <= Last, a signed compare with no
lower bound. An id of 0xffffffff casts to a negative enum, passes the
gate, and reaches GetNameSectionSubsectionName, which indexed
NameSubsectionName[size_t(subsec)] with no range check. The logging
delegate then prints the returned wild const char* with %s.

The module is valid: an unknown name subsection is skipped, so this only
shows with verbose logging (wasm2wat -v, wasm-objdump -v,
wasm-interp -v). Found feeding fuzz-style name sections through
wasm2wat -v.

Fixed in the caller: ReadNameSection compares the raw name_type
against Last before the cast, so an out-of-range id is skipped as an
unknown subsection and never becomes a NameSectionSubsection.
GetNameSectionSubsectionName keeps the plain index and asserts the
in-range precondition. Regression test added under
src/test-binary-reader.cc.

NameSectionSubsection is a signed enum with no explicit underlying type, so a name subsection id >= 0x80000000 casts to a negative value that passes the `type <= Last` gate in ReadNameSection and indexes NameSubsectionName out of bounds when logged. Range-check the index like the sibling accessors GetKindName and GetRelocTypeName.
Comment thread src/binary.cc
};
// clang-format on

const char* GetNameSectionSubsectionName(NameSectionSubsection subsec) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we instead have the caller of this function (who creates the NameSectionSubsection from bytes) ensure that the subsec is valid?

Either that or have this function take an integer type rather then a NameSectionSubsection?

Basically I think its function take a enum as an argument it should a pre-condition that the enum is in-range.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

(In this case, an assert should still be added here)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Moved the check to the caller. ReadNameSection now compares the raw name_type before the cast, so an id past Last is skipped as an unknown subsection and never becomes a NameSectionSubsection in the first place (the cast itself was unspecified for those values anyway). The accessor is back to a plain index with an assert on the precondition, per @zherczeg.

Checked against the original module (subsection type LEB 0xffffffff): the assert fires with the old reader, and wasm2wat -v runs clean with the new one. Kept the regression test, it still covers that path.

Reject an out-of-range subsection id before it is cast, so
GetNameSectionSubsectionName is only ever handed an in-range enum, and
assert that precondition there rather than returning an error string.
Comment thread src/test-binary-reader.cc
// table when it is logged.
Result result = ReadBinary(data, &reader, options);
(void)result;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can this be a normal file-based test like name-section-location.txt?

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