{"record":{"id":"b4e55bca3c409693","repo":"go-delve/delve","slug":"start-address-x-should-be-less-than-end-address","errorCode":null,"errorMessage":"start address(%x) should be less than end address(%x)","messagePattern":"start address\\(%x\\) should be less than end address\\(%x\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proc/disasm.go","lineNumber":125,"sourceCode":"\nfunc checkPrologue(s []AsmInstruction, prologuePattern opcodeSeq) bool {\n\tline := s[0].Loc.Line\n\tfor i, op := range prologuePattern {\n\t\tif !s[i].Inst.OpcodeEquals(op) || s[i].Loc.Line != line {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// Disassemble disassembles target memory between startAddr and endAddr, marking\n// the current instruction being executed in goroutine g.\n// If currentGoroutine is set and thread is stopped at a CALL instruction Disassemble\n// will evaluate the argument of the CALL instruction using the thread's registers.\n// Be aware that the Bytes field of each returned instruction is a slice of a larger array of size startAddr - endAddr.\nfunc Disassemble(mem MemoryReadWriter, regs Registers, breakpoints *BreakpointMap, bi *BinaryInfo, startAddr, endAddr uint64) ([]AsmInstruction, error) {\n\tif startAddr > endAddr {\n\t\treturn nil, fmt.Errorf(\"start address(%x) should be less than end address(%x)\", startAddr, endAddr)\n\t}\n\treturn disassemble(mem, regs, breakpoints, bi, startAddr, endAddr, false)\n}\n\nfunc disassemble(memrw MemoryReadWriter, regs Registers, breakpoints *BreakpointMap, bi *BinaryInfo, startAddr, endAddr uint64, singleInstr bool) ([]AsmInstruction, error) {\n\tvar dregs *op.DwarfRegisters\n\tif regs != nil {\n\t\tdregs = bi.Arch.RegistersToDwarfRegisters(0, regs)\n\t}\n\n\tmem := make([]byte, int(endAddr-startAddr))\n\t_, err := memrw.ReadMemory(mem, startAddr)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tr := make([]AsmInstruction, 0, len(mem)/bi.Arch.MaxInstructionLength())\n\tpc := startAddr","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/go-delve/delve/blob/a23773e6c31361e43246bc43a424ee009679b174/pkg/proc/disasm.go#L107-L143","documentation":"proc.Disassemble disassembles machine code in the address range [startAddr, endAddr) of the target's memory. It rejects calls where startAddr > endAddr with this error, because a reversed range is meaningless and downstream code allocates a buffer of size startAddr-endAddr. Equal addresses are allowed and yield an empty instruction list.","triggerScenarios":"Calling proc.Disassemble (or its public callers findRetPC, setStepIntoNewProcBreakpoint, skipAutogeneratedWrappersIn, and service-level StepInto/Disassemble RPC/DAP requests) with swapped or computed bounds such that startAddr > endAddr.","commonSituations":"A client computing a function's range from a symbol table with reversed hi/lo bounds; endAddr computed as funcEnd - n with unsigned underflow; an RPC client sending incorrectly ordered Start/End arguments.","solutions":["Swap the arguments so startAddr is the lower address (e.g. min/max the two values).","Check where the bounds are computed (e.g. fn.Entry/fn.End from the symbol table) and fix the reversal or underflow.","For RPC/DAP clients, verify the Start and End fields sent in the request are ordered ascending.","Add a guard before calling: only invoke when endAddr > startAddr, else return an empty result."],"exampleFix":"// before\ninsns, err := proc.Disassemble(mem, regs, bp, bi, fn.End, fn.Entry) // swapped\n\n// after\ninsns, err := proc.Disassemble(mem, regs, bp, bi, fn.Entry, fn.End)","handlingStrategy":"validation","validationCode":"func safeDisassemble(mem proc.MemoryReadWriter, regs proc.Registers, bp *proc.BreakpointMap, bi *proc.BinaryInfo, start, end uint64) ([]proc.AsmInstruction, error) {\n    if start > end {\n        start, end = end, start\n    }\n    return proc.Disassemble(mem, regs, bp, bi, start, end)\n}","typeGuard":"func validRange(start, end uint64) bool {\n    return start <= end\n}","tryCatchPattern":"insns, err := proc.Disassemble(mem, regs, bp, bi, startAddr, endAddr)\nif err != nil {\n    if strings.Contains(err.Error(), \"should be less than end address\") {\n        startAddr, endAddr = endAddr, startAddr\n        insns, err = proc.Disassemble(mem, regs, bp, bi, startAddr, endAddr)\n    }\n    if err != nil { return nil, err }\n}","preventionTips":["Always derive ranges as (fn.Entry, fn.End) from the symbol table, not ad-hoc math.","Watch for unsigned arithmetic underflow when computing endAddr = x - n.","In RPC/DAP clients, assert Start < End before sending the request.","Unit-test range computation helpers with reversed and zero-length cases."],"tags":["disassembly","argument-validation","address-range"],"backgroundTag":"invalid-address-range","analyzedSha":"a23773e6c31361e43246bc43a424ee009679b174","analyzedAt":"2026-08-31T15:12:45.221Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}