fix(browser): reject overlapping indexed source maps

Fixes #6562
This commit is contained in:
morluto
2026-10-23 18:00:47 +08:00
parent 553262443a
commit ba7c3dafab
8 changed files with 151 additions and 23 deletions
@@ -5,7 +5,7 @@ import {
} from "./SourceMapFormat.js";
/** Determine whether a leaf-local mapping falls before its enclosing boundary. */
export const isBeforeSourceMapLeafStop = (
const isBeforeSourceMapLeafStop = (
leaf: SourceMapLeaf,
line: number,
column: number,
@@ -40,6 +40,11 @@ export const decodeValidatedSourceMapLeaves = (
const generatedLine = leaf.offset.line + line;
const generatedColumn =
segment[0] + (line === 0 ? leaf.offset.column : 0);
if (!isBeforeSourceMapLeafStop(leaf, line, segment[0]))
throw new SourceMapFormatFailure(
"section-overlap",
"Embedded source-map mappings overlap the following section boundary.",
);
if (
!Number.isSafeInteger(generatedLine) ||
!Number.isSafeInteger(generatedColumn) ||
@@ -50,7 +50,11 @@ const execute = async (): Promise<string> => {
throw cause;
return JSON.stringify({
state: "failure",
reason: cause instanceof SourceMapFormatFailure ? cause.reason : "format",
reason:
cause instanceof SourceMapFormatFailure &&
cause.reason !== "section-overlap"
? cause.reason
: "format",
message: cause.message,
});
}
+1 -1
View File
@@ -55,7 +55,7 @@ export interface SourceMapStructureOptions {
/** A decoder-profile failure with an actionable producer constraint. */
export class SourceMapFormatFailure extends Error {
constructor(
readonly reason: "format" | "unsupported" | "limit",
readonly reason: "format" | "unsupported" | "limit" | "section-overlap",
message: string,
) {
super(message);
@@ -310,7 +310,7 @@ describe("source-map layout admission", () => {
{ offset: { line: 0, column: 5 }, map: leaf },
],
}),
).toThrow(/overlap/u);
).toThrow(expect.objectContaining({ reason: "section-overlap" }));
});
it("accepts absent optional names and null contents without changing reported identity", () => {
expect(
+1 -12
View File
@@ -22,10 +22,7 @@ import {
SourceMapFormatFailure,
type SourceMapSourceDeclaration,
} from "./SourceMapFormat.js";
import {
decodeValidatedSourceMapLeaves,
isBeforeSourceMapLeafStop,
} from "./DecodedSourceMap.js";
import { decodeValidatedSourceMapLeaves } from "./DecodedSourceMap.js";
/** Decode with the pinned upstream codec; preserve every equal-position candidate. */
export const traceSourceMap = (
@@ -35,14 +32,6 @@ export const traceSourceMap = (
): WebSourceMapReport => {
const inspected = inspectSourceMap(text);
const decodedLeaves = decodeValidatedSourceMapLeaves(inspected.leaves, url);
for (const { leaf, rows } of decodedLeaves)
for (const [line, row] of rows.entries())
for (const segment of row)
if (!isBeforeSourceMapLeafStop(leaf, line, segment[0]))
throw new SourceMapFormatFailure(
"format",
"Embedded source-map mappings overlap the following section boundary.",
);
let map: TraceMap;
if (inspected.format === "regular") {
const decoded = decodedLeaves[0];