Skip to content

fix(reliability): validate Hangul engine structural counts before traversal #367

Description

@seonghobae

Buyer-visible Hangul reliability boundary

Draft PR #320 / branch feat/hwp-hwpx-authoring remains the single writer for src/hangul/index.ts. Protected shipped truth is independently resolved main@3b38ead2d00f44eb578d0689087b9293b3dabe1e; current exact Draft head is 5ee6e4d0c3b2a804f39a8d186a8bdd7c2a38a782.

The public adapter consumed host-engine getSectionCount(), getParagraphCount(), and getParagraphLength() values as traversal/index authority. Earlier repairs rejected fractional/negative metadata and stabilized the section loop, but accepting every non-negative safe integer still left a resource-integrity defect: a hostile engine could return Number.MAX_SAFE_INTEGER and drive effectively unbounded traversal/allocation or pass enormous paragraph indexes/offsets back across the host boundary.

The host owns the HWP/HWPX engine; Inkspan owns bounded validation of values crossing that boundary before using them as work/index authority.

Test-first lineage

  • Original RED 6610482f5c9456274befe43dfde024da6975220d: CI 31996622632, build/test job 95289331283 reached the intended malformed-metadata regressions and failed because operations resolved instead of rejecting.
  • RED c5615c9b28b741343fc234599a662eb117e50e7b: CI 31996779187, job 95289741025 proved valid single-section characterization called getSectionCount() twice rather than once.
  • RED extension f99891581dcdaae37bd8ccbf5136785f461af086: added export-side fractional paragraph-length coverage before source changed.
  • Resource-bound RED 030512a5496c8fa869fc0cb1c79724334d6919b1: exact-checkout CI 32394561877, build-and-test job 96508269729 typechecked, entered pnpm coverage, then exhausted the Node/Vitest heap near 4 GiB while exercising the forged enormous structural metadata (FATAL ERROR: ... heap out of memory, followed by ERR_IPC_CHANNEL_CLOSED). This demonstrates that safe-integer validation alone did not bound work; the run is deliberately non-passing evidence.
  • Narrow source fix 88936bd85345ec81daba1eaa497ed21418ce6dab makes structural metadata fail closed above 4,096 sections, 1,000,000 paragraphs per section, or 16,777,216 UTF-16 code units per paragraph before child traversal, host selection, deletion, or paste mutation. These are Inkspan safety ceilings, not HWP/HWPX format maxima.
  • Current head 5ee6e4d0c3b2a804f39a8d186a8bdd7c2a38a782 also binds those ceilings into docs/HANGUL.md, ADR 0030, and a machine-checkable documentation contract. Unknown engine failures remain stable and payload-redacted.

Exact-current-head evidence

Live base remains main@3b38ead2d00f44eb578d0689087b9293b3dabe1e. For exact current head 5ee6e4d0c3b2a804f39a8d186a8bdd7c2a38a782 at the latest fresh refetch:

  • CI 32395091285: completed / success;
  • build-and-test 96510085342: exact-current-head checkout, 161 test files / 898 tests, 100% statements / branches / functions / lines, package verification and builds successful;
  • Office Python 3.11-3.14 and cross-engine Playwright jobs: completed / success;
  • Security Scan 32395091192: completed / success;
  • SAST Semgrep 32395091052: completed / success;
  • qualifying latest-push independent approval remains absent.

All observed repository-owned exact-head workflows are terminal success; the absent qualifying independent approval remains non-passing. Predecessor-head success is not transferred.

Acceptance / integration

The finite-bound behavior is GREEN under the repository CI/coverage/package/browser/Office/security/SAST suite on the unchanged exact head, but overall integration acceptance remains non-passing because qualifying review and then-live governance are unsatisfied. This issue stays open until PR #320 eventually integrates. Keep #320 Draft/unmerged while #118 owns v0.6.0 release acceptance and live merge governance remains unsatisfied. Any head/base movement invalidates the current exact-head classification. Do not create another Hangul source writer or weaken the resource limits/gates to obtain a green result.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: apiAPI, protocol, event, or external contractarea: authAuthentication, authorization, identity, or tenant isolationarea: ci-cdCI, GitHub Actions, checks, release, or supply chainarea: securitySecurity boundary, hardening, or vulnerability preventionpriority: mediumNormal-priority or P2 workstatus: triagedOpen issue has an organization taxonomy assignmenttype: bugDefect or incorrect behavior

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions