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
Этот коммит содержится в:
родитель
dd1a836903
коммит
b8e433821a
1 изменённых файлов: 17 добавлений и 1 удалений
|
@ -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
|
||||
}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче