aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2024-02-27 14:11:19 +0100
committerRon Evans <[email protected]>2024-02-27 15:16:38 +0100
commit9951eb9990071aaf5e29665cc3185c1abe7368dc (patch)
tree131641e5ea07026bc2628e54a16829faa700ce06
parentc8f77d26a872cf9686b06a7a7ce3b7c4f2292363 (diff)
downloadtinygo-9951eb9990071aaf5e29665cc3185c1abe7368dc.tar.gz
tinygo-9951eb9990071aaf5e29665cc3185c1abe7368dc.zip
interp: return a proper error message when indexing out of range
This helps debug issues inside interp.
-rw-r--r--interp/interpreter.go22
-rw-r--r--interp/memory.go6
2 files changed, 21 insertions, 7 deletions
diff --git a/interp/interpreter.go b/interp/interpreter.go
index 24735eb26..864d6f652 100644
--- a/interp/interpreter.go
+++ b/interp/interpreter.go
@@ -427,7 +427,11 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
if err != nil {
return nil, mem, r.errorAt(inst, err)
}
- methodSetPtr, err := mem.load(typecodePtr.addOffset(-int64(r.pointerSize)), r.pointerSize).asPointer(r)
+ typecodePtrOffset, err := typecodePtr.addOffset(-int64(r.pointerSize))
+ if err != nil {
+ return nil, mem, r.errorAt(inst, err) // unlikely
+ }
+ methodSetPtr, err := mem.load(typecodePtrOffset, r.pointerSize).asPointer(r)
if err != nil {
return nil, mem, r.errorAt(inst, err)
}
@@ -473,7 +477,11 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
if err != nil {
return nil, mem, r.errorAt(inst, err)
}
- methodSetPtr, err := mem.load(typecodePtr.addOffset(-int64(r.pointerSize)), r.pointerSize).asPointer(r)
+ typecodePtrOffset, err := typecodePtr.addOffset(-int64(r.pointerSize))
+ if err != nil {
+ return nil, mem, r.errorAt(inst, err)
+ }
+ methodSetPtr, err := mem.load(typecodePtrOffset, r.pointerSize).asPointer(r)
if err != nil {
return nil, mem, r.errorAt(inst, err)
}
@@ -658,7 +666,10 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
locals[inst.localIndex] = makeLiteralInt(ptrValue, int(operands[0].len(r)*8))
continue
}
- ptr = ptr.addOffset(int64(offset))
+ ptr, err = ptr.addOffset(int64(offset))
+ if err != nil {
+ return nil, mem, r.errorAt(inst, err)
+ }
locals[inst.localIndex] = ptr
if r.debug {
fmt.Fprintln(os.Stderr, indent+"gep:", operands, "->", ptr)
@@ -756,7 +767,10 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
if inst.opcode == llvm.Add {
// This likely means this is part of a
// unsafe.Pointer(uintptr(ptr) + offset) pattern.
- lhsPtr = lhsPtr.addOffset(int64(rhs.Uint()))
+ lhsPtr, err = lhsPtr.addOffset(int64(rhs.Uint()))
+ if err != nil {
+ return nil, mem, r.errorAt(inst, err)
+ }
locals[inst.localIndex] = lhsPtr
} else if inst.opcode == llvm.Xor && rhs.Uint() == 0 {
// Special workaround for strings.noescape, see
diff --git a/interp/memory.go b/interp/memory.go
index 356ffa512..759a1ffe4 100644
--- a/interp/memory.go
+++ b/interp/memory.go
@@ -517,12 +517,12 @@ func (v pointerValue) offset() uint32 {
// addOffset essentially does a GEP operation (pointer arithmetic): it adds the
// offset to the pointer. It also checks that the offset doesn't overflow the
// maximum offset size (which is 4GB).
-func (v pointerValue) addOffset(offset int64) pointerValue {
+func (v pointerValue) addOffset(offset int64) (pointerValue, error) {
result := pointerValue{v.pointer + uint64(offset)}
if checks && v.index() != result.index() {
- panic("interp: offset out of range")
+ return result, fmt.Errorf("interp: offset %d out of range for object %v", offset, v)
}
- return result
+ return result, nil
}
func (v pointerValue) len(r *runner) uint32 {