Skip to content

fix(alphatex): prevent TypeError crashes on malformed bend/whammy properties - #2796

Open
otherwiseguy wants to merge 1 commit into
CoderLine:developfrom
otherwiseguy:feature/alphatex-handler-crash-fixes
Open

fix(alphatex): prevent TypeError crashes on malformed bend/whammy properties#2796
otherwiseguy wants to merge 1 commit into
CoderLine:developfrom
otherwiseguy:feature/alphatex-handler-crash-fixes

Conversation

@otherwiseguy

@otherwiseguy otherwiseguy commented Jul 25, 2026

Copy link
Copy Markdown

Sorry for the wordy noise, I was definitely not ready to submit this. I was running through test framework seeing if AI could generate a Rust port of the alphaTex parser. I told it I wanted to record any bugs we found for upstream PRs, and it instead immediately did one on my behalf before I could read it and verify the legitimacy of the issues.

Feel free to close if this isn't useful. Sorry again for sending an un-human-verified PR.

Problem

Three malformed alphaTex inputs raise an uncaught TypeError out of readScore():

C4 {b invalid (0 4)}       TypeError: Cannot read properties of undefined (reading 'arguments')
C4 {b bend invalid (0 4)}  TypeError: Cannot read properties of undefined (reading 'nodeType')
C4 {tb invalid (0 1)}      TypeError: Cannot read properties of undefined (reading 'arguments')

Every sibling case in the same test block — {dy invalid}, {ot invalid}, {gr (invalid)}, {beam invalid} and a dozen more — reports a proper diagnostic instead, so this looks unintended rather than by design.

Cause

The bend (b/be) and whammy (tb/tbe) branches of AlphaTex1LanguageHandler scan leading type/style identifiers with an unbounded loop:

while (typeAndStyle) {
    switch (p.arguments!.arguments[tbi].nodeType) {

Argument parsing only absorbs identifiers that are known values for the property, so an unknown word such as invalid starts a new property rather than being consumed as an argument. That leaves the bend/whammy property either with no argument list at all (p.arguments undefined → first crash) or with every argument already consumed as a type/style word (tbi past the end → second crash).

Fix

Bound the loop by the actual argument count, and return early from _getBendPoints when the property has no argument list (12 lines total). Malformed input now flows through the normal diagnostic path; parsed-bend behaviour is untouched.

Before / after for the three inputs: uncaught TypeErrorAT212 "Unrecogized property 'invalid'" with a source position.

Tests

The three affected cases live in errors > at219 and previously snapshotted empty diagnostic arrays, because importErrorTest records whatever readScore() produces — including a crash — so the suite stayed green. Their snapshots now contain the emitted diagnostic.

Worth noting: the recorded code is AT212 (unknown property), not the block's AT219 (invalid enum value). The invalid word never reaches the bend handler as an argument, so it cannot currently be reported as a bad enum value — if AT219 is the desired diagnostic for these inputs, that would be a follow-up in argument parsing rather than the handler. Happy to move or rename the tests if you'd prefer them outside the at219 block.

test/importer, test/model and test/audio pass (1115 tests).

…perties

The bend (b/be) and whammy (tb/tbe) handler branches scan leading
type/style identifiers with an unbounded loop:

    while (typeAndStyle) {
        switch (p.arguments!.arguments[tbi].nodeType) {

Two malformed inputs escape this loop's assumptions and raise an
uncaught TypeError out of readScore():

  C4 {b invalid (0 4)}       TypeError: Cannot read properties of
                             undefined (reading 'arguments')
  C4 {b bend invalid (0 4)}  TypeError: Cannot read properties of
                             undefined (reading 'nodeType')
  C4 {tb invalid (0 1)}      (same as the first, whammy branch)

Cause: argument parsing only absorbs identifiers that are known values
for the property, so an unknown word such as `invalid` starts a new
property instead. That leaves the bend/whammy property either with no
argument list at all (p.arguments undefined) or with every argument
consumed as a type/style word (index past the end).

Bound the loop by the actual argument count, and return early from
_getBendPoints when the property has no argument list. Malformed input
now flows through the normal diagnostic path (AT212, "Unrecogized
property 'invalid'", with a source position) instead of crashing, and
the parsed-bend paths are untouched.

The three affected tests live in the `errors > at219` block and
previously snapshotted empty diagnostic arrays, because importErrorTest
records whatever readScore() produces — including a crash. Their
snapshots now contain the emitted diagnostic. Note the code is AT212
rather than the block's AT219: the invalid word never reaches the bend
handler as an argument, so it is reported as an unknown property.

All 1115 tests in test/importer, test/model and test/audio pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant