fix(python): walk slice members in the code hashability stack

The key resolver followed slice members, but the explicit-stack hashability
walk skipped them, so a code object reached through a slice constant started
a recursive hashability check. A 3,000-link slice-wrapped TYPE_REF code chain
overflowed the JavaScript stack. Push slice members onto the same explicit
stack as tuple and frozenset members.

Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
This commit is contained in:
gensokyo-devandgensokyo-dev authored and Ysopwnable committed 2026-11-14 13:37:55 +01:00
1 parent ca147d7c4d
commit 2caa2598d3
2 files changed
+44 -1

No files matched your search

+41
View File
@@ -1668,6 +1668,47 @@ it("hashes shallow TYPE_REF code chains without using the JavaScript stack", ()
});
});
it("hashes slice-wrapped TYPE_REF code chains without using the JavaScript stack", () => {
const links = 3000;
const none = Buffer.from([0x4e]);
const codes = Array.from({ length: links }, (_, index) =>
marshalCode("py311", {
flagged: true,
name: "f",
consts:
index === 0
? [none]
: [
Buffer.concat([
Buffer.from([0x3a]),
marshalRef(index - 1),
none,
none,
]),
],
}),
);
const bytes = Buffer.concat([
pythonPycHeader(3627),
marshalCode("py311", {
constsObject: Buffer.concat([
Buffer.from([0x28]),
u32(links + 1),
...codes,
Buffer.from([0x3c]),
u32(1),
marshalRef(links - 1),
]),
}),
]);
const report = parseWith(bytes, { max_objects: 65_536 });
expect(root(report).consts.at(-1)).toEqual({ kind: "set", length: 1 });
expect(report.coverage).toMatchObject({
status: "complete",
code_objects: links + 1,
});
});
it("rejects code CPython treats as corrupt instead of complete coverage", () => {
const file = (
layout: "py37" | "py38" | "py311",
+3 -1
View File
@@ -1413,7 +1413,9 @@ class MarshalReader {
malformed("Code object is missing equality material.")
).constsTuple,
]
: value.kind === "tuple" || value.kind === "frozenset"
: value.kind === "tuple" ||
value.kind === "frozenset" ||
value.kind === "slice"
? value.items
: [];
gray.add(identity);