From 72b95c828a26ab52e8b79d407ecec44ebe5201c1 Mon Sep 17 00:00:00 2001 From: Albrecht Degering Date: Wed, 22 Jul 2026 19:59:59 +0200 Subject: [PATCH] fix: append large parser collections safely --- src/onenote/model/append.ts | 9 +++++++++ src/onenote/one/section.ts | 6 +++++- src/onenote/parser/parse-toc.ts | 3 ++- tests/append.test.ts | 21 +++++++++++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 src/onenote/model/append.ts create mode 100644 tests/append.test.ts diff --git a/src/onenote/model/append.ts b/src/onenote/model/append.ts new file mode 100644 index 0000000..60fc26b --- /dev/null +++ b/src/onenote/model/append.ts @@ -0,0 +1,9 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. +// SPDX-License-Identifier: MPL-2.0 + +/** Append a bounded collection without relying on the engine's argument cap. */ +export function appendItems(target: T[], items: readonly T[]): void { + for (const item of items) target.push(item); +} diff --git a/src/onenote/one/section.ts b/src/onenote/one/section.ts index 0430016..c9d8b7e 100644 --- a/src/onenote/one/section.ts +++ b/src/onenote/one/section.ts @@ -11,6 +11,7 @@ import { BinaryReader } from '../binary/BinaryReader.js'; import { filetimeToIso, oneNoteTimeToIso } from '../binary/time.js'; +import { appendItems } from '../model/append.js'; import type { ParserDiagnostic } from '../model/diagnostics.js'; import type { OneNotePageSummaryDto, OneNoteSectionDto } from '../model/dto.js'; import type { OneNoteParserLimits } from '../parser/limits.js'; @@ -341,7 +342,10 @@ function traverseReferences( ): string[] { const result: string[] = []; for (const id of ids) { - result.push(...extractGraphText(context, space, id, active, depth + 1)); + appendItems( + result, + extractGraphText(context, space, id, active, depth + 1) + ); } return result; } diff --git a/src/onenote/parser/parse-toc.ts b/src/onenote/parser/parse-toc.ts index b7c5f39..4a14660 100644 --- a/src/onenote/parser/parse-toc.ts +++ b/src/onenote/parser/parse-toc.ts @@ -4,6 +4,7 @@ import { BinaryReader } from '../binary/BinaryReader.js'; import { readGuid } from '../binary/guid.js'; +import { appendItems } from '../model/append.js'; import type { ParserDiagnostic } from '../model/diagnostics.js'; import { parseDesktopOneNoteTableOfContentsStore } from '../onestore/desktop-store.js'; import type { DesktopOneStore } from '../onestore/desktop-store.js'; @@ -171,7 +172,7 @@ function parseChildren( color: optionalColor(child), }); } else { - result.push(...parseChildren(context, child, depth + 1)); + appendItems(result, parseChildren(context, child, depth + 1)); } } finally { context.active.delete(key); diff --git a/tests/append.test.ts b/tests/append.test.ts new file mode 100644 index 0000000..bc4f5e8 --- /dev/null +++ b/tests/append.test.ts @@ -0,0 +1,21 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. +// SPDX-License-Identifier: MPL-2.0 + +import { describe, expect, it } from 'vitest'; + +import { appendItems } from '../src/onenote/model/append.js'; + +describe('bounded collection append', () => { + it('does not use a variadic call for argument-limit-sized collections', () => { + const source = Array.from({ length: 200_000 }, (_, index) => index); + const target = [-1]; + + appendItems(target, source); + + expect(target).toHaveLength(200_001); + expect(target[0]).toBe(-1); + expect(target.at(-1)).toBe(199_999); + }); +});