Skip to content

Commit b96a879

Browse files
committed
Implement out-of-bounds checking for names/kind
1 parent 85c95df commit b96a879

File tree

2 files changed

+54
-20
lines changed

2 files changed

+54
-20
lines changed

src/decode/decode.test.ts

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ describe("decode", () => {
108108
assertEquals(decode(map), info);
109109
});
110110

111-
it("ignores wrong 'name' indices", () => {
111+
it("ignores wrong 'name' indices in lax mode", () => {
112112
const encoder = new ItemEncoder();
113113
encoder.addUnsignedVLQs(
114114
Tag.ORIGINAL_SCOPE_START,
@@ -122,10 +122,10 @@ describe("decode", () => {
122122
const info = decode(map);
123123

124124
assertExists(info.scopes[0]);
125-
assertStrictEquals(info.scopes[0].name, undefined);
125+
assertStrictEquals(info.scopes[0].name, "");
126126
});
127127

128-
it("ignores wrong 'kind' indices", () => {
128+
it("ignores wrong 'kind' indices in lax mode", () => {
129129
const encoder = new ItemEncoder();
130130
encoder.addUnsignedVLQs(
131131
Tag.ORIGINAL_SCOPE_START,
@@ -139,7 +139,7 @@ describe("decode", () => {
139139
const info = decode(map);
140140

141141
assertExists(info.scopes[0]);
142-
assertStrictEquals(info.scopes[0].kind, undefined);
142+
assertStrictEquals(info.scopes[0].kind, "");
143143
});
144144

145145
it("throws when encountering an ORIGINAL_SCOPE_END without start in strict mode", () => {
@@ -258,7 +258,7 @@ describe("decode", () => {
258258
assertEquals(info.scopes, []);
259259
});
260260

261-
it("throws if ORIGINAL_SCOPE_VARIABLES indices are out-of-bounds (upper)", () => {
261+
it("throws if ORIGINAL_SCOPE_VARIABLES indices are out-of-bounds (upper) in strict mode", () => {
262262
const encoder = new ItemEncoder();
263263
encoder.addUnsignedVLQs(Tag.ORIGINAL_SCOPE_START, 0, 0, 0).finishItem();
264264
encoder.addUnsignedVLQs(Tag.ORIGINAL_SCOPE_VARIABLES);
@@ -273,7 +273,7 @@ describe("decode", () => {
273273
);
274274
});
275275

276-
it("throws if ORIGINAL_SCOPE_VARIABLES indices are out-of-bounds (lower)", () => {
276+
it("throws if ORIGINAL_SCOPE_VARIABLES indices are out-of-bounds (lower) in strict mode", () => {
277277
const encoder = new ItemEncoder();
278278
encoder.addUnsignedVLQs(Tag.ORIGINAL_SCOPE_START, 0, 0, 0).finishItem();
279279
encoder.addUnsignedVLQs(Tag.ORIGINAL_SCOPE_VARIABLES);
@@ -288,7 +288,7 @@ describe("decode", () => {
288288
);
289289
});
290290

291-
it("ignores if ORIGINAL_SCOPE_VARIABLES indices are out-of-bounds (upper)", () => {
291+
it("ignores if ORIGINAL_SCOPE_VARIABLES indices are out-of-bounds (upper) in lax mode", () => {
292292
const encoder = new ItemEncoder();
293293
encoder.addUnsignedVLQs(Tag.ORIGINAL_SCOPE_START, 0, 0, 0).finishItem();
294294
encoder.addUnsignedVLQs(Tag.ORIGINAL_SCOPE_VARIABLES);
@@ -301,7 +301,7 @@ describe("decode", () => {
301301
assertEquals(info.scopes[0]?.variables, ["foo", ""]);
302302
});
303303

304-
it("ignores if ORIGINAL_SCOPE_VARIABLES indices are out-of-bounds (lower)", () => {
304+
it("ignores if ORIGINAL_SCOPE_VARIABLES indices are out-of-bounds (lower) in lax mode", () => {
305305
const encoder = new ItemEncoder();
306306
encoder.addUnsignedVLQs(Tag.ORIGINAL_SCOPE_START, 0, 0, 0).finishItem();
307307
encoder.addUnsignedVLQs(Tag.ORIGINAL_SCOPE_VARIABLES);
@@ -313,4 +313,40 @@ describe("decode", () => {
313313

314314
assertEquals(info.scopes[0]?.variables, ["foo", ""]);
315315
});
316+
317+
it("throws if ORIGINAL_SCOPE_START.name is out-of-bounds in strict mode", () => {
318+
const encoder = new ItemEncoder();
319+
encoder.addUnsignedVLQs(
320+
Tag.ORIGINAL_SCOPE_START,
321+
OriginalScopeFlags.HAS_NAME,
322+
0,
323+
0,
324+
).addSignedVLQs(1).finishItem(); // The last '1' is the illegal name index.
325+
encoder.addUnsignedVLQs(Tag.ORIGINAL_SCOPE_END, 1, 0).finishItem();
326+
const map = createMap(encoder.encode(), ["foo"]);
327+
328+
assertThrows(
329+
() => decode(map, { mode: DecodeMode.STRICT }),
330+
Error,
331+
"index into the 'names' array",
332+
);
333+
});
334+
335+
it("throws if ORIGINAL_SCOPE_START.kind is out-of-bounds in strict mode", () => {
336+
const encoder = new ItemEncoder();
337+
encoder.addUnsignedVLQs(
338+
Tag.ORIGINAL_SCOPE_START,
339+
OriginalScopeFlags.HAS_KIND,
340+
0,
341+
0,
342+
).addSignedVLQs(1).finishItem(); // The last '1' is the illegal name index.
343+
encoder.addUnsignedVLQs(Tag.ORIGINAL_SCOPE_END, 1, 0).finishItem();
344+
const map = createMap(encoder.encode(), ["foo"]);
345+
346+
assertThrows(
347+
() => decode(map, { mode: DecodeMode.STRICT }),
348+
Error,
349+
"index into the 'names' array",
350+
);
351+
});
316352
});

src/decode/decode.ts

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -219,11 +219,11 @@ class Decoder {
219219

220220
if (item.nameIdx !== undefined) {
221221
this.#scopeState.name += item.nameIdx;
222-
scope.name = this.#names[this.#scopeState.name];
222+
scope.name = this.resolveName(this.#scopeState.name);
223223
}
224224
if (item.kindIdx !== undefined) {
225225
this.#scopeState.kind += item.kindIdx;
226-
scope.kind = this.#names[this.#scopeState.kind];
226+
scope.kind = this.resolveName(this.#scopeState.kind);
227227
}
228228

229229
scope.isStackFrame = Boolean(
@@ -245,16 +245,7 @@ class Decoder {
245245

246246
for (const variableIdx of variableIdxs) {
247247
this.#scopeState.variable += variableIdx;
248-
249-
if (
250-
this.#scopeState.variable < 0 ||
251-
this.#scopeState.variable >= this.#names.length
252-
) {
253-
this.#throwInStrictMode(
254-
"ORIGINAL_SCOPE_VARIABLE is not a valid index into the 'names' array",
255-
);
256-
}
257-
scope.variables.push(this.#names[this.#scopeState.variable] ?? "");
248+
scope.variables.push(this.resolveName(this.#scopeState.variable));
258249
}
259250
}
260251

@@ -366,4 +357,11 @@ class Decoder {
366357
Object.assign(this.#rangeState, DEFAULT_RANGE_STATE);
367358
}
368359
}
360+
361+
protected resolveName(index: number): string {
362+
if (index < 0 || index >= this.#names.length) {
363+
this.#throwInStrictMode("Illegal index into the 'names' array");
364+
}
365+
return this.#names[index] ?? "";
366+
}
369367
}

0 commit comments

Comments
 (0)