Skip to content

Commit b8e4338

Browse files
aykevldeadprogram
authored andcommitted
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 #2842. It didn't occur more often probably because it only seems to happen in practice with inline assembly. Fixes #2842
1 parent dd1a836 commit b8e4338

File tree

1 file changed

+17
-1
lines changed

1 file changed

+17
-1
lines changed

interp/interpreter.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,28 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
8181
if inst.opcode != llvm.PHI {
8282
for _, v := range inst.operands {
8383
if v, ok := v.(localValue); ok {
84-
if localVal := locals[fn.locals[v.value]]; localVal == nil {
84+
index, ok := fn.locals[v.value]
85+
if !ok {
86+
// This is a localValue that is not local to the
87+
// function. An example would be an inline assembly call
88+
// operand.
89+
isRuntimeInst = true
90+
break
91+
}
92+
localVal := locals[index]
93+
if localVal == nil {
94+
// Trying to read a function-local value before it is
95+
// set.
8596
return nil, mem, r.errorAt(inst, errors.New("interp: local not defined"))
8697
} else {
8798
operands = append(operands, localVal)
8899
if _, ok := localVal.(localValue); ok {
100+
// The function-local value is still just a
101+
// localValue (which can't be interpreted at compile
102+
// time). Not sure whether this ever happens in
103+
// practice.
89104
isRuntimeInst = true
105+
break
90106
}
91107
continue
92108
}

0 commit comments

Comments
 (0)