diff --git a/src/vs/workbench/api/common/shared/semanticTokensDto.ts b/src/vs/workbench/api/common/shared/semanticTokensDto.ts index a5f3738272d05..8c6795c97a9e4 100644 --- a/src/vs/workbench/api/common/shared/semanticTokensDto.ts +++ b/src/vs/workbench/api/common/shared/semanticTokensDto.ts @@ -55,12 +55,12 @@ function fromLittleEndianBuffer(buff: VSBuffer): Uint32Array { reverseEndianness(uint8Arr); } if (uint8Arr.byteOffset % 4 === 0) { - return new Uint32Array(uint8Arr.buffer, uint8Arr.byteOffset); + return new Uint32Array(uint8Arr.buffer, uint8Arr.byteOffset, uint8Arr.length / 4); } else { // unaligned memory access doesn't work on all platforms const data = new Uint8Array(uint8Arr.byteLength); data.set(uint8Arr); - return new Uint32Array(data.buffer, data.byteOffset); + return new Uint32Array(data.buffer, data.byteOffset, data.length / 4); } } diff --git a/src/vs/workbench/test/common/api/semanticTokensDto.test.ts b/src/vs/workbench/test/common/api/semanticTokensDto.test.ts index 3f59943a43b3b..091bc24e2f3ed 100644 --- a/src/vs/workbench/test/common/api/semanticTokensDto.test.ts +++ b/src/vs/workbench/test/common/api/semanticTokensDto.test.ts @@ -5,6 +5,7 @@ import * as assert from 'assert'; import { IFullSemanticTokensDto, IDeltaSemanticTokensDto, encodeSemanticTokensDto, ISemanticTokensDto, decodeSemanticTokensDto } from 'vs/workbench/api/common/shared/semanticTokensDto'; +import { VSBuffer } from 'vs/base/common/buffer'; suite('SemanticTokensDto', () => { @@ -107,4 +108,29 @@ suite('SemanticTokensDto', () => { }); }); + test('issue #94521: unusual backing array buffer', () => { + function wrapAndSliceUint8Arry(buff: Uint8Array, prefixLength: number, suffixLength: number): Uint8Array { + const wrapped = new Uint8Array(prefixLength + buff.byteLength + suffixLength); + wrapped.set(buff, prefixLength); + return wrapped.subarray(prefixLength, prefixLength + buff.byteLength); + } + function wrapAndSlice(buff: VSBuffer, prefixLength: number, suffixLength: number): VSBuffer { + return VSBuffer.wrap(wrapAndSliceUint8Arry(buff.buffer, prefixLength, suffixLength)); + } + const dto: ISemanticTokensDto = { + id: 5, + type: 'full', + data: new Uint32Array([1, 2, 3, 4, 5]) + }; + const encoded = encodeSemanticTokensDto(dto); + + // with misaligned prefix and misaligned suffix + assertEqualFull(decodeSemanticTokensDto(wrapAndSlice(encoded, 1, 1)), dto); + // with misaligned prefix and aligned suffix + assertEqualFull(decodeSemanticTokensDto(wrapAndSlice(encoded, 1, 4)), dto); + // with aligned prefix and misaligned suffix + assertEqualFull(decodeSemanticTokensDto(wrapAndSlice(encoded, 4, 1)), dto); + // with aligned prefix and aligned suffix + assertEqualFull(decodeSemanticTokensDto(wrapAndSlice(encoded, 4, 4)), dto); + }); });