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 {
|
if inst.opcode != llvm.PHI {
|
||||||
for _, v := range inst.operands {
|
for _, v := range inst.operands {
|
||||||
if v, ok := v.(localValue); ok {
|
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"))
|
return nil, mem, r.errorAt(inst, errors.New("interp: local not defined"))
|
||||||
} else {
|
} else {
|
||||||
operands = append(operands, localVal)
|
operands = append(operands, localVal)
|
||||||
if _, ok := localVal.(localValue); ok {
|
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
|
isRuntimeInst = true
|
||||||
|
break
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче