{"record":{"id":"b1ec5a20b3a2377c","repo":"go-delve/delve","slug":"write-out-of-bounds","errorCode":null,"errorMessage":"write out of bounds","messagePattern":"write out of bounds","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/mem.go","lineNumber":190,"sourceCode":"\t\tpadding := make([]byte, paddingBytes)\n\t\tcmem.data = append(cmem.data, padding...)\n\t}\n\treturn cmem, nil\n}\n\nfunc (mem *compositeMemory) ReadMemory(data []byte, addr uint64) (int, error) {\n\taddr -= mem.base\n\tif addr >= uint64(len(mem.data)) || addr+uint64(len(data)) > uint64(len(mem.data)) {\n\t\treturn 0, errors.New(\"read out of bounds\")\n\t}\n\tcopy(data, mem.data[addr:addr+uint64(len(data))])\n\treturn len(data), nil\n}\n\nfunc (mem *compositeMemory) WriteMemory(addr uint64, data []byte) (int, error) {\n\taddr -= mem.base\n\tif addr >= uint64(len(mem.data)) || addr+uint64(len(data)) > uint64(len(mem.data)) {\n\t\treturn 0, errors.New(\"write out of bounds\")\n\t}\n\tif mem.regs.ChangeFunc == nil {\n\t\tfor _, piece := range mem.pieces {\n\t\t\tif piece.Kind == op.RegPiece {\n\t\t\t\treturn 0, errors.New(\"can not write registers\")\n\t\t\t}\n\t\t}\n\t}\n\n\tcopy(mem.data[addr:], data)\n\n\tcurAddr := uint64(0)\n\tdonesz := 0\n\tfor _, piece := range mem.pieces {\n\t\tif curAddr < (addr+uint64(len(data))) && addr < (curAddr+uint64(piece.Size)) {\n\t\t\t// changed memory interval overlaps current piece\n\t\t\tpieceMem := mem.data[curAddr : curAddr+uint64(piece.Size)]\n","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/mem.go#L172-L208","documentation":"compositeMemory.WriteMemory validates that the target range, after subtracting the memory base, lies entirely within the assembled data buffer. 'write out of bounds' means the write address or address+len(data) extends past the buffer backing this composite view, so Delve refuses to write rather than corrupt adjacent data.","triggerScenarios":"Calling variable-setting APIs (e.g. 'set' command, SetVariable) on a variable backed by compositeMemory when the resolved address is outside the assembled pieces' range — typically variables located in registers, optimized-away slots, or stale frames.","commonSituations":"Attempting to set a variable that lives partly or wholly in registers in optimized code; setting a variable in a dead/returned frame; address computation from a mismatched DWARF version.","solutions":["Set variables in the live topmost frame (frame 0)","Rebuild without optimizations (-gcflags=\"all=-N -l\") so variables have stable memory locations","Verify the binary/core dump pairing matches; re-evaluate to refresh the memory view before writing"],"exampleFix":"// before\n(dlv) frame 3\n(dlv) set i = 10   // write out of bounds\n// after\n(dlv) frame 0\n(dlv) set i = 10","handlingStrategy":"validation","validationCode":"// Before 'set', confirm the variable has a memory (non-register) location:\n//   (dlv) print &i   // a valid address in the live frame\n// If &i fails or the frame is not 0, expect write failures.","typeGuard":null,"tryCatchPattern":"err := setVariable(\"i\", \"10\")\nif err != nil && strings.Contains(err.Error(), \"write out of bounds\") {\n    log.Printf(\"cannot set %s: not writable here (dead frame or register-backed)\", \"i\")\n}","preventionTips":["Set variables only in frame 0 of a live process","Disable optimizations in debug builds so variables live on the stack","Refresh evaluation state after stepping before writing"],"tags":["go","memory","registers","debugger"],"backgroundTag":"memory-write-out-of-bounds","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}