diff --git a/packages/alphatab/src/importer/GpifParser.ts b/packages/alphatab/src/importer/GpifParser.ts index b7bd46907..f5954de2c 100644 --- a/packages/alphatab/src/importer/GpifParser.ts +++ b/packages/alphatab/src/importer/GpifParser.ts @@ -2892,6 +2892,10 @@ export class GpifParser { // build masterbar automations for (const [barNumber, automations] of this._masterTrackAutomations) { + if (barNumber < 0 || barNumber >= this.score.masterBars.length) { + // automation references a bar that is not in the score's masterBars list + continue; + } const masterBar: MasterBar = this.score.masterBars[barNumber]; for (let i: number = 0, j: number = automations.length; i < j; i++) { const automation: Automation = automations[i]; diff --git a/packages/alphatab/test-data/guitarpro8/orphan-tempo-automation.gp b/packages/alphatab/test-data/guitarpro8/orphan-tempo-automation.gp new file mode 100755 index 000000000..76543653b Binary files /dev/null and b/packages/alphatab/test-data/guitarpro8/orphan-tempo-automation.gp differ diff --git a/packages/alphatab/test/importer/Gp8Importer.test.ts b/packages/alphatab/test/importer/Gp8Importer.test.ts index 0ef7ffa1d..7f0dac5a6 100644 --- a/packages/alphatab/test/importer/Gp8Importer.test.ts +++ b/packages/alphatab/test/importer/Gp8Importer.test.ts @@ -510,4 +510,14 @@ describe('Gp8ImporterTest', () => { const score = reader.readScore(); GpImporterTestHelper.checkHarmonics(score); }); + + it('orphan-tempo-automation', async () => { + // GPIF tempo automations can reference bar indices that are not + // present in the score's masterBars list (e.g. off-by-one or after + // bar deletion). Should be skipped instead of null-dereferencing. + const reader = await prepareImporterWithFile('guitarpro8/orphan-tempo-automation.gp'); + const score = reader.readScore(); + expect(score.masterBars.length).to.equal(100); + expect(score.tracks.length).to.equal(3); + }); });