From 5460068d52154726fda3179fbbe53fa615662ce4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Mon, 17 Dec 2018 23:59:48 +0100 Subject: [PATCH 1/2] fix invalid string and buffer index --- src/Buffer.test.ts | 33 +++++++++++++++++++++++++++++++-- src/Buffer.ts | 2 +- src/Linkifier.ts | 8 ++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/Buffer.test.ts b/src/Buffer.test.ts index 6b6adc11da..5c1e56c93c 100644 --- a/src/Buffer.test.ts +++ b/src/Buffer.test.ts @@ -355,7 +355,7 @@ describe('Buffer', () => { let terminal: TestTerminal; beforeEach(() => { - terminal = new TestTerminal({rows: 5, cols: 10}); + terminal = new TestTerminal({rows: 5, cols: 10, scrollback: 5}); }); it('multiline ascii', () => { @@ -516,9 +516,38 @@ describe('Buffer', () => { assert.deepEqual([(j / terminal.cols) | 0, j % terminal.cols], bufferIndex); } }); + + it('test fully wrapped buffer up to last char', () => { + const input = Array(6).join('1234567890'); + terminal.writeSync(input); + const s = terminal.buffer.iterator(true).next().content; + assert.equal(input, s); + for (let i = 0; i < input.length; ++i) { + const bufferIndex = terminal.buffer.stringIndexToBufferIndex(0, i); + assert.equal(input[i], terminal.buffer.lines.get(bufferIndex[0]).get(bufferIndex[1])[CHAR_DATA_CHAR_INDEX]); + } + }); + + it('test fully wrapped buffer up to last char with full width odd', () => { + const input = 'a¥\u0301a¥\u0301a¥\u0301a¥\u0301a¥\u0301a¥\u0301a¥\u0301a¥\u0301' + + 'a¥\u0301a¥\u0301a¥\u0301a¥\u0301a¥\u0301a¥\u0301a¥\u0301'; + terminal.writeSync(input); + const s = terminal.buffer.iterator(true).next().content; + assert.equal(input, s); + for (let i = 0; i < input.length; ++i) { + const bufferIndex = terminal.buffer.stringIndexToBufferIndex(0, i); + assert.equal( + (!(i % 3)) + ? input[i] + : (i % 3 === 1) + ? input.substr(i, 2) + : input.substr(i-1, 2), + terminal.buffer.lines.get(bufferIndex[0]).get(bufferIndex[1])[CHAR_DATA_CHAR_INDEX]); + } + }); }); describe('BufferStringIterator', function(): void { - it('iterator does not ovrflow buffer limits', function(): void { + it('iterator does not overflow buffer limits', function(): void { const terminal = new TestTerminal({rows: 5, cols: 10, scrollback: 5}); const data = [ 'aaaaaaaaaa', diff --git a/src/Buffer.ts b/src/Buffer.ts index 10f1d1b2cb..df4134ee14 100644 --- a/src/Buffer.ts +++ b/src/Buffer.ts @@ -252,7 +252,7 @@ export class Buffer implements IBuffer { while (stringIndex) { const line = this.lines.get(lineIndex); if (!line) { - [-1, -1]; + return [-1, -1]; } for (let i = 0; i < line.length; ++i) { stringIndex -= line.get(i)[CHAR_DATA_CHAR_INDEX].length; diff --git a/src/Linkifier.ts b/src/Linkifier.ts index 2ec3ed400d..53247c95f8 100644 --- a/src/Linkifier.ts +++ b/src/Linkifier.ts @@ -219,9 +219,17 @@ export class Linkifier extends EventEmitter implements ILinkifier { // also correct regex and string search offsets for the next loop run stringIndex = text.indexOf(uri, stringIndex + 1); rex.lastIndex = stringIndex + uri.length; + if (stringIndex < 0) { + // invalid stringIndex (should not have happened) + break; + } // get the buffer index as [absolute row, col] for the match const bufferIndex = this._terminal.buffer.stringIndexToBufferIndex(rowIndex, stringIndex); + if (bufferIndex[0] < 0) { + // invalid bufferIndex (should not have happened) + break; + } const line = this._terminal.buffer.lines.get(bufferIndex[0]); const char = line.get(bufferIndex[1]); From 0da630010279cbebd4363adb44991ba7c2652373 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Tue, 18 Dec 2018 10:50:30 +0100 Subject: [PATCH 2/2] make linter happy --- src/Buffer.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Buffer.test.ts b/src/Buffer.test.ts index 5c1e56c93c..0546dfe809 100644 --- a/src/Buffer.test.ts +++ b/src/Buffer.test.ts @@ -541,7 +541,7 @@ describe('Buffer', () => { ? input[i] : (i % 3 === 1) ? input.substr(i, 2) - : input.substr(i-1, 2), + : input.substr(i - 1, 2), terminal.buffer.lines.get(bufferIndex[0]).get(bufferIndex[1])[CHAR_DATA_CHAR_INDEX]); } });