diff --git a/src/gguf/fileReaders/GgufNetworkFetchFileReader.ts b/src/gguf/fileReaders/GgufNetworkFetchFileReader.ts index 0a6d0c12..5b5d9acf 100644 --- a/src/gguf/fileReaders/GgufNetworkFetchFileReader.ts +++ b/src/gguf/fileReaders/GgufNetworkFetchFileReader.ts @@ -59,7 +59,7 @@ export class GgufNetworkFetchFileReader extends GgufFileReader { if (endOffset > this._buffer.length) return this._fetchToExpandBufferUpToOffset(endOffset) .then(() => { - if (endOffset >= this._buffer.length) + if (endOffset > this._buffer.length) throw new Error("Expected buffer to be long enough for the requested byte range"); }); diff --git a/test/standalone/gguf/ggufNetworkFileBoundary.test.ts b/test/standalone/gguf/ggufNetworkFileBoundary.test.ts new file mode 100644 index 00000000..638e7ddc --- /dev/null +++ b/test/standalone/gguf/ggufNetworkFileBoundary.test.ts @@ -0,0 +1,28 @@ +import {describe, expect, test} from "vitest"; +import {GgufNetworkFetchFileReader} from "../../../src/gguf/fileReaders/GgufNetworkFetchFileReader.js"; + +const remoteGGUFModel = "https://huggingface.co/ggml-org/models-moved/resolve/499bc8821c6b12b4e53c5bffcb21ec206f212d81/tinyllamas/stories260K.gguf"; +const remoteGGUFModelSize = 1185376; + +describe("gguf network file boundaries", () => { + test("reads the final byte after expanding the buffer to EOF", {timeout: 1000 * 60 * 10}, async () => { + const fileReader = new GgufNetworkFetchFileReader({url: remoteGGUFModel, retryOptions: {retries: 0}}); + + expect(await fileReader.readUint8(remoteGGUFModelSize - 1)) + .toBe(63); + }); + + test("reads bytes before EOF", {timeout: 1000 * 60 * 10}, async () => { + const fileReader = new GgufNetworkFetchFileReader({url: remoteGGUFModel, retryOptions: {retries: 0}}); + + expect(await fileReader.readStringWithLength(0, 4)) + .toBe("GGUF"); + }); + + test("rejects a byte beyond EOF", {timeout: 1000 * 60 * 10}, async () => { + const fileReader = new GgufNetworkFetchFileReader({url: remoteGGUFModel, retryOptions: {retries: 0}}); + + await expect(fileReader.readUint8(remoteGGUFModelSize)) + .rejects.toThrow("Expected buffer to be long enough for the requested byte range"); + }); +});