{"record":{"id":"85194a5650b41e23","repo":"ruvnet/ruflo","slug":"section-id-exceeds-buffer-bounds","errorCode":null,"errorMessage":"Section \"${id}\" exceeds buffer bounds","messagePattern":"Section \"(.+?)\" exceeds buffer bounds","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/appliance/rvfa-format.ts","lineNumber":416,"sourceCode":"  /** List all sections declared in the header. */\n  getSections(): RvfaSection[] {\n    return this.header.sections;\n  }\n\n  /**\n   * Extract and decompress a section by its id.\n   *\n   * @param id  The section identifier (e.g. 'kernel', 'runtime').\n   * @returns   The decompressed section payload.\n   */\n  extractSection(id: string): Buffer {\n    const sec = this.header.sections.find((s) => s.id === id);\n    if (!sec) {\n      throw new Error(`Section \"${id}\" not found`);\n    }\n\n    if (sec.offset + sec.size > this.buf.length - SHA256_SIZE) {\n      throw new Error(`Section \"${id}\" exceeds buffer bounds`);\n    }\n\n    const raw = this.buf.subarray(sec.offset, sec.offset + sec.size);\n\n    if (sec.compression === 'gzip') {\n      return gunzipSync(raw);\n    }\n    if (sec.compression === 'zstd') {\n      // zstd not natively supported — attempt gzip fallback (mirrors writer)\n      try {\n        return gunzipSync(raw);\n      } catch {\n        throw new Error(\n          'zstd decompression is not supported in this environment',\n        );\n      }\n    }\n","sourceCodeStart":398,"sourceCodeEnd":434,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/cli/src/appliance/rvfa-format.ts#L398-L434","documentation":"extractSection(id) re-checks at read time that sec.offset + sec.size <= buf.length - 32, even though fromBuffer already validated this. It fires when the buffer shrank between construction and extraction — e.g. the caller passed a subarray/truncated copy — or when a RvfaReader was somehow constructed without full validation. It is defense-in-depth against reading past the data region into the SHA256 footer.","triggerScenarios":"Calling extractSection after the reader's underlying buffer was replaced or the reader was built via a path that skipped validation; or holding a reader over a Buffer that a debugging step reallocated. In normal use (fromBuffer/fromFile) this is unreachable — seeing it means the reader instance was constructed unusually or the buffer was mutated.","commonSituations":"Test code constructing RvfaReader-like objects directly; buffer pooling/copying bugs where a smaller buffer is handed to an existing reader; memory-pressure 'optimizations' that slice buffers in place.","solutions":["Always obtain readers via RvfaReader.fromBuffer(buf) or await RvfaReader.fromFile(path) — both run the full validation pass","Don't share or mutate the buffer you passed to fromBuffer; the reader retains a reference (subarray shares memory)","If you must revalidate, rebuild the reader from the original full buffer rather than patching offsets","Add an assertion on buf.length before extractSection in hot paths to catch early buffer swaps"],"exampleFix":"// before — reusing a reader after truncating the source buffer\nconst reader = RvfaReader.fromBuffer(buf);\nbuf = buf.subarray(0, 1000); // reader still points at original, sizes now wrong\nreader.extractSection('kernel');\n\n// after — rebuild the reader from the bytes you actually have\nconst reader = RvfaReader.fromBuffer(buf);\n// ... later, if buf changed:\nconst fresh = RvfaReader.fromBuffer(currentBuf);","handlingStrategy":"validation","validationCode":"const sec = reader.getSections().find((s) => s.id === id);\nif (!sec || sec.offset + sec.size > buf.length - 32) {\n  throw new Error('section would read past data region — buffer changed');\n}","typeGuard":null,"tryCatchPattern":"try { const data = reader.extractSection(id); }\ncatch (e) {\n  if (/exceeds buffer bounds/.test(String((e as Error).message))) {\n    // rebuild the reader from the full original buffer\n  }\n  throw e;\n}","preventionTips":["Only obtain readers via fromBuffer/fromFile — never construct them directly","Do not mutate or shrink the buffer passed to fromBuffer (subarray shares memory)","Rebuild the reader instead of patching buffers when underlying data changes"],"tags":["rvfa","buffer-bounds","defense-in-depth","binary-format"],"backgroundTag":"buffer-out-of-bounds","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}