aboutsummaryrefslogtreecommitdiffhomepage
path: root/interp
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2022-05-21 15:46:00 +0200
committerRon Evans <[email protected]>2022-05-22 15:08:17 +0200
commitb8e433821adca1d1b68abb584e606a1217434894 (patch)
treee0ac2e84c71bbb01942bf428acda3528fa21bcb1 /interp
parentdd1a836903ea52c7f6a52a01ac4ccc27a63006f2 (diff)
downloadtinygo-b8e433821adca1d1b68abb584e606a1217434894.tar.gz
tinygo-b8e433821adca1d1b68abb584e606a1217434894.zip
interp: fix some buggy localValue handling
Bug: 1. fn.locals[v.value] returns 0 (the default value) if v.value is not part of the fn.locals map. 2. locals[fn.locals[v.value]] then returns the first local value, which is usually non-nil 3. This incorrect value is then used as the operand value. The manifestation of this convoluted bug was https://github.com/tinygo-org/tinygo/issues/2842. It didn't occur more often probably because it only seems to happen in practice with inline assembly. Fixes https://github.com/tinygo-org/tinygo/issues/2842
Diffstat (limited to 'interp')
-rw-r--r--interp/interpreter.go18
1 files changed, 17 insertions, 1 deletions
diff --git a/interp/interpreter.go b/interp/interpreter.go
index 0f2355a68..cccbe7b3b 100644
--- a/interp/interpreter.go
+++ b/interp/interpreter.go
@@ -81,12 +81,28 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
if inst.opcode != llvm.PHI {
for _, v := range inst.operands {
if v, ok := v.(localValue); ok {
- if localVal := locals[fn.locals[v.value]]; localVal == nil {
+ index, ok := fn.locals[v.value]
+ if !ok {
+ // This is a localValue that is not local to the
+ // function. An example would be an inline assembly call
+ // operand.
+ isRuntimeInst = true
+ break
+ }
+ localVal := locals[index]
+ if localVal == nil {
+ // Trying to read a function-local value before it is
+ // set.
return nil, mem, r.errorAt(inst, errors.New("interp: local not defined"))
} else {
operands = append(operands, localVal)
if _, ok := localVal.(localValue); ok {
+ // The function-local value is still just a
+ // localValue (which can't be interpreted at compile
+ // time). Not sure whether this ever happens in
+ // practice.
isRuntimeInst = true
+ break
}
continue
}