mirror of
https://github.com/morluto/rea.git
synced 2026-11-07 05:56:19 -10:00
fix(evm): reject repeated byte-string keys in Solidity metadata (#4024)
cborg's rejectDuplicateMapKeys compares Map keys by identity, and each byte-string key decodes to its own Uint8Array, so a terminal metadata map with the same byte key twice was reported as decoded. Compare the root map's scalar keys by kind and value and report a repeat as not-decoded, like repeated text keys.
This commit is contained in:
2 files changed
+30
-2
No files matched your search
@@ -107,12 +107,27 @@ it("keeps the compiler version beside a shortest-form empty text", () => {
|
||||
expect(result.entries).toHaveLength(2);
|
||||
});
|
||||
|
||||
it("decodes distinct byte keys and distinct nested-container keys", () => {
|
||||
expect(
|
||||
inspectSolidityMetadata(bytecode("a2410101410202")).entries.map(
|
||||
({ key }) => key,
|
||||
),
|
||||
).toEqual([
|
||||
{ kind: "bytes", value: "01" },
|
||||
{ kind: "bytes", value: "02" },
|
||||
]);
|
||||
expect(inspectSolidityMetadata(bytecode("a2810101810202"))).toMatchObject({
|
||||
status: "partial",
|
||||
});
|
||||
});
|
||||
|
||||
it.each([
|
||||
["invalid text", "a1617861ff"],
|
||||
["truncated value", "a16178"],
|
||||
["unsupported tag", "a16178c000"],
|
||||
["floating point", "a16178fa3f800000"],
|
||||
["duplicate key", "a2617801617802"],
|
||||
["duplicate byte key", "a2410101410102"],
|
||||
["excessive nesting", "a16178" + "81".repeat(65) + "00"],
|
||||
["impossible collection", "a161788a00"],
|
||||
])("keeps exact ranges and unavailable interpretation for %s", (_name, hex) => {
|
||||
|
||||
@@ -122,8 +122,21 @@ export const inspectSolidityMetadata = (
|
||||
});
|
||||
if (!(raw instanceof Map))
|
||||
throw new Error("Terminal CBOR candidate did not decode to a root map.");
|
||||
for (const [key, value] of raw as Map<unknown, unknown>)
|
||||
result.entries.push({ key: scalar(key), value: scalar(value) });
|
||||
// cborg compares Map keys by identity, so repeated byte-string keys (each
|
||||
// its own Uint8Array) pass its duplicate check; compare scalars by value.
|
||||
const seen = new Set<string>();
|
||||
for (const [key, value] of raw as Map<unknown, unknown>) {
|
||||
const entry = { key: scalar(key), value: scalar(value) };
|
||||
if (entry.key.kind !== "uninterpreted") {
|
||||
const identity = JSON.stringify(entry.key);
|
||||
if (seen.has(identity))
|
||||
throw new Error(
|
||||
`CBOR decode error: found repeat map key ${identity}`,
|
||||
);
|
||||
seen.add(identity);
|
||||
}
|
||||
result.entries.push(entry);
|
||||
}
|
||||
result.status = result.entries.some(
|
||||
({ key, value }) =>
|
||||
key.kind === "uninterpreted" || value.kind === "uninterpreted",
|
||||
|
||||
Reference in new issue
Block a user