Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions packages/gguf/src/gguf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const MAX_STRING_LENGTH = 10_000_000; // 10MB per string (CWE-770)
const MAX_TENSOR_NDIMS = 8; // GGML supports up to 4, be generous (CWE-770)
const MAX_ARRAY_RECURSION_DEPTH = 4; // nested ARRAY-of-ARRAY depth limit (CWE-674)
const MAX_CHUNK_FETCHES_PER_VALUE = 30; // prevent infinite fetch loop (CWE-835)
const MAX_ALIGNMENT = 1 << 30; // 2^30 — largest power-of-2 safe for JS bitwise ops (CWE-190)
const GGML_PAD = (x: number, n: number) => (x + n - 1) & ~(n - 1); // defined in ggml.h
const PARALLEL_DOWNLOADS = 20;

Expand Down Expand Up @@ -505,6 +506,12 @@ export async function gguf(
if (alignment <= 0 || !Number.isInteger(alignment)) {
throw new Error(`general.alignment must be a positive integer, got ${rawAlignment}`);
}
if ((alignment & (alignment - 1)) !== 0) {
throw new Error(`general.alignment must be a power of 2, got ${rawAlignment}`);
}
if (alignment > MAX_ALIGNMENT) {
throw new Error(`general.alignment ${rawAlignment} exceeds maximum safe value (${MAX_ALIGNMENT}) for JS bitwise operations`);
}
const tensorInfoEndBeforePadOffset = offset;
const tensorDataOffset = BigInt(GGML_PAD(offset, alignment));

Expand Down Expand Up @@ -654,6 +661,9 @@ export function serializeGgufMetadata(
): Uint8Array {
const littleEndian = options.littleEndian ?? true;
const alignment = options.alignment ?? GGUF_DEFAULT_ALIGNMENT;
if (alignment <= 0 || !Number.isInteger(alignment) || (alignment & (alignment - 1)) !== 0 || alignment > MAX_ALIGNMENT) {
throw new Error(`alignment must be a power of 2 in [1, ${MAX_ALIGNMENT}], got ${alignment}`);
}
const version = typedMetadata.version.value;

// Start with GGUF magic number: "GGUF"
Expand Down Expand Up @@ -762,6 +772,9 @@ export async function buildGgufHeader(
},
): Promise<Blob> {
const alignment = options.alignment ?? GGUF_DEFAULT_ALIGNMENT;
if (alignment <= 0 || !Number.isInteger(alignment) || (alignment & (alignment - 1)) !== 0 || alignment > MAX_ALIGNMENT) {
throw new Error(`alignment must be a power of 2 in [1, ${MAX_ALIGNMENT}], got ${alignment}`);
}
const version = updatedMetadata.version.value;

// Serialize the new metadata
Expand Down