{"record":{"id":"d771cd2fd298abf8","repo":"oven-sh/bun","slug":"third-buffer-was-modified","errorCode":null,"errorMessage":"Third buffer was modified","messagePattern":"Third buffer was modified","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"bench/snippets/buffer-concat.mjs","lineNumber":41,"sourceCode":"    `Buffer.concat(${fmt.format(\n      Number((size > 1024 * 1024 ? size / 1024 / 1024 : size > 1024 ? size / 1024 : size).toFixed(2)),\n    )} x 3)`,\n    () => {\n      const result = Buffer.concat(buffers);\n      if (check) {\n        if (result.byteLength != size * 3) throw new Error(\"Wrong length\");\n        if (result[0] != 1) throw new Error(\"Wrong first byte\");\n        if (result[size] != 2) throw new Error(\"Wrong second byte\");\n        if (result[size * 2] != 3) throw new Error(\"Wrong third byte\");\n\n        result[0] = 10;\n        if (first[0] != 1) throw new Error(\"First buffer was modified\");\n\n        result[size] = 20;\n        if (second[0] != 2) throw new Error(\"Second buffer was modified\");\n\n        result[size * 2] = 30;\n        if (third[0] != 3) throw new Error(\"Third buffer was modified\");\n      }\n    },\n  );\n}\n\nconst chunk = Buffer.alloc(16);\nchunk.fill(\"3\");\nconst array = Array.from({ length: 100 }, () => chunk);\nbench(\"Buffer.concat 100 tiny chunks\", () => {\n  return Buffer.concat(array);\n});\n\nawait run();\n","sourceCodeStart":23,"sourceCodeEnd":55,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/bench/snippets/buffer-concat.mjs#L23-L55","documentation":"Same copy-semantics assertion as its siblings in bench/snippets/buffer-concat.mjs, but for the last input: after Buffer.concat([first, second, third]) it writes 30 into result[size * 2] and requires third[0] to remain 3. It throws when the concat result's tail region aliases the `third` buffer's memory, i.e. concat did not produce an independent copy.","triggerScenarios":"Buffer.concat reusing the last argument's backing memory (a common zero-copy temptation since the tail of the result aligns with it), or an off-by-one/region bug in the copy loop that makes result[size * 2] and third[0] the same byte. The check runs on every iteration because `check` is hard-coded true.","commonSituations":"Regressions in Bun's Buffer.concat tail-copy path; dev builds while optimizing large (16 MB) concatenations; comparing aliasing behavior against Node, which always copies.","solutions":["Isolate with a 3-buffer concat of distinct fill values and write result[result.length - 1] to see if third changes","Run `bun bd test test/js/node/buffer` to catch the conformance failure","Review Buffer.concat changes for accidental view-return or in-place writes into an argument","Report to oven-sh/bun with the minimal aliasing repro if it reproduces in a release build"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// tail-region aliasing check: write the last byte, verify the last input\nconst result = Buffer.concat([first, second, third]);\nresult[result.length - 1] ^= 0xff;\nif (third[0] !== 3) throw new Error('concat aliased the tail input');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check both the head (result[0] vs first[0]) and tail (result[len-1] vs last input) regions when validating concat copy semantics","Include the buffer-concat snippet in regression runs after touching buffer copy paths","Report confirmed aliasing to oven-sh/bun — silent data corruption for any user of Buffer.concat"],"tags":["buffer","buffer-concat","benchmark","assertion","memory-aliasing","data-corruption"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}