{"record":{"id":"a02ad44747203341","repo":"BabylonJS/Babylon.js","slug":"wrong-huf-encsize","errorCode":null,"errorMessage":"Wrong HUF_ENCSIZE","messagePattern":"Wrong HUF_ENCSIZE","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/Materials/Textures/Loaders/EXR/exrLoader.compression.huf.ts","lineNumber":440,"sourceCode":"    return true;\r\n}\r\n\r\n/** @internal */\r\nexport function HufUncompress(array: Uint8Array, dataView: DataView, offset: DataCursor, nCompressed: number, outBuffer: Uint16Array, nRaw: number) {\r\n    const outOffset: DataCursor = { value: 0 };\r\n    const initialInOffset = offset.value;\r\n\r\n    const im = ParseUint32(dataView, offset);\r\n    const iM = ParseUint32(dataView, offset);\r\n\r\n    offset.value += 4;\r\n\r\n    const nBits = ParseUint32(dataView, offset);\r\n\r\n    offset.value += 4;\r\n\r\n    if (im < 0 || im >= HUF_ENCSIZE || iM < 0 || iM >= HUF_ENCSIZE) {\r\n        throw new Error(\"Wrong HUF_ENCSIZE\");\r\n    }\r\n\r\n    const freq = new Array(HUF_ENCSIZE);\r\n    const hdec = new Array(HUF_DECSIZE);\r\n\r\n    HufClearDecTable(hdec);\r\n\r\n    const ni = nCompressed - (offset.value - initialInOffset);\r\n\r\n    HufUnpackEncTable(array, offset, ni, im, iM, freq);\r\n\r\n    if (nBits > 8 * (nCompressed - (offset.value - initialInOffset))) {\r\n        throw new Error(\"Wrong hufUncompress\");\r\n    }\r\n\r\n    HufBuildDecTable(freq, im, iM, hdec);\r\n\r\n    HufDecode(freq, hdec, array, offset, nBits, iM, nRaw, outBuffer, outOffset);\r","sourceCodeStart":422,"sourceCodeEnd":458,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Materials/Textures/Loaders/EXR/exrLoader.compression.huf.ts#L422-L458","documentation":"HufUncompress validated the minimum/maximum symbol indices (im/iM) read from the Huffman table header of a PIZ-compressed block against HUF_ENCSIZE (65537). A value outside [0, HUF_ENCSIZE) proves the compressed stream is not a valid OpenEXR huf block, so the loader aborts instead of indexing arrays out of bounds.","triggerScenarios":"Raised in HufUncompress (called by UncompressPIZ) immediately after parsing the four leading uint32 fields when im or iM is negative or >= HUF_ENCSIZE — i.e. the bytes at the huf block start are not a real huf table.","commonSituations":"Corrupt or truncated downloads, wrong chunk offsets after a malformed EXR header, or a file saved by a non-conformant writer.","solutions":["Verify the .exr integrity (size, checksum) and re-download/re-export it","Load the file with exrheader or another EXR reader to confirm it is valid PIZ data","Check the EXR offset table is being parsed correctly (earlier header errors shift block offsets)","Re-export the texture using ZIP/ZIPS compression instead of PIZ"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// confirm the file is a well-formed EXR before attempting PIZ decode\nif (new DataView(buf).getUint32(0, true) !== 0x01312f76 || buf.byteLength < 64) throw new Error(\"invalid or truncated EXR\");","typeGuard":null,"tryCatchPattern":"try {\n  await loader.loadAsync(exrFile);\n} catch (e) {\n  if (/Wrong HUF_ENCSIZE/.test(String(e))) {\n    console.error(\"PIZ block corrupt — re-export the EXR with ZIP compression\");\n    return loadFallbackTexture();\n  }\n  throw e;\n}","preventionTips":["Re-download corrupted assets and compare checksums","Avoid manual byte-offset manipulation of EXR chunk data","Prefer ZIP/ZIPS compression over PIZ in exports","Validate source EXRs with a reference tool before shipping them"],"tags":["exr","piz-compression","corrupted-data"],"backgroundTag":"corrupt-compressed-exr-data","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}