Skip to content

Commit f5e2fff

Browse files
committed
fix(importer): skip GPIF tempo automations on missing master bars
GpifParser._buildModel iterated _masterTrackAutomations and dereferenced score.masterBars[barNumber] without checking that the index was within range. Real-world GP7/8 files (off-by-one indexing, scores edited to fewer bars) reference bar numbers past the masterBars list, producing: TypeError: Cannot read properties of undefined (reading 'tempoAutomations') Skip the automation if the master bar is absent. The fixture test-data/guitarpro8/orphan-tempo-automation.gp has 100 master bars and a tempo automation targeting bar 100 (off-by-one) that previously crashed the importer.
1 parent f8ef24f commit f5e2fff

3 files changed

Lines changed: 15 additions & 1 deletion

File tree

packages/alphatab/src/importer/GpifParser.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2892,7 +2892,11 @@ export class GpifParser {
28922892

28932893
// build masterbar automations
28942894
for (const [barNumber, automations] of this._masterTrackAutomations) {
2895-
const masterBar: MasterBar = this.score.masterBars[barNumber];
2895+
const masterBar: MasterBar | undefined = this.score.masterBars[barNumber];
2896+
if (!masterBar) {
2897+
// automation references a bar that is not in the score's masterBars list
2898+
continue;
2899+
}
28962900
for (let i: number = 0, j: number = automations.length; i < j; i++) {
28972901
const automation: Automation = automations[i];
28982902
switch (automation.type) {
Binary file not shown.

packages/alphatab/test/importer/Gp8Importer.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,4 +510,14 @@ describe('Gp8ImporterTest', () => {
510510
const score = reader.readScore();
511511
GpImporterTestHelper.checkHarmonics(score);
512512
});
513+
514+
it('orphan-tempo-automation', async () => {
515+
// GPIF tempo automations can reference bar indices that are not
516+
// present in the score's masterBars list (e.g. off-by-one or after
517+
// bar deletion). Should be skipped instead of null-dereferencing.
518+
const reader = await prepareImporterWithFile('guitarpro8/orphan-tempo-automation.gp');
519+
const score = reader.readScore();
520+
expect(score.masterBars.length).to.equal(100);
521+
expect(score.tracks.length).to.equal(3);
522+
});
513523
});

0 commit comments

Comments
 (0)