fix(python): preserve marshal scalar identity and decode limits

This commit is contained in:
morluto committed 2026-10-24 02:35:21 +08:00
1 parent a47788a6a4
commit 06032237c6
7 files changed
+164 -25

No files matched your search

+36 -1
View File
@@ -335,23 +335,58 @@ it("decodes marshal strings with CPython surrogatepass rules", () => {
).toThrow(PythonPycFormatFailure);
});
it("keeps non-finite float and complex constants JSON-safe", () => {
it.each([0x73, 0x74, 0x75, 0x61, 0x41, 0x28, 0x5b, 0x3c, 0x3e])(
"classifies a negative signed marshal count (tag %i) before applying limits",
(tag) => {
expect(() =>
parse(withConsts([Buffer.concat([Buffer.from([tag]), i32(-1)])])),
).toThrow(PythonPycFormatFailure);
},
);
it("keeps signed zero and non-finite float and complex constants JSON-safe", () => {
const report = parse(
withConsts([
Buffer.concat([Buffer.from([0x67]), f64(Infinity)]),
Buffer.concat([Buffer.from([0x79]), f64(0), f64(-Infinity)]),
Buffer.concat([Buffer.from([0x67]), f64(Number.NaN)]),
Buffer.concat([Buffer.from([0x67]), f64(-0)]),
Buffer.concat([Buffer.from([0x67]), f64(0)]),
Buffer.concat([Buffer.from([0x79]), f64(-0), f64(-0)]),
]),
);
expect(root(report).consts).toEqual([
{ kind: "float", value: "inf" },
{ kind: "complex", real: 0, imag: "-inf" },
{ kind: "float", value: "nan" },
{ kind: "float", value: "-0.0" },
{ kind: "float", value: 0 },
{ kind: "complex", real: "-0.0", imag: "-0.0" },
]);
expect(pythonPycSchema.safeParse(report).success).toBe(true);
expect(JSON.parse(JSON.stringify(report))).toEqual(report);
});
it("truncates string previews without introducing a lone surrogate", () => {
const prefix = "x".repeat(79);
const report = parse(
withConsts([
marshalUnicode(Buffer.from(`${prefix}😀tail`)),
marshalUnicode(
Buffer.concat([
Buffer.from(prefix),
Buffer.from("eda080", "hex"),
Buffer.from("tail"),
]),
),
]),
);
expect(root(report).consts).toEqual([
{ kind: "str", bytes: 87, truncated: true, value: prefix },
{ kind: "str", bytes: 86, truncated: true, value: `${prefix}\ud800` },
]);
});
it("accepts an empty co_filename", () => {
const report = parse(
Buffer.concat([