Skip to content

Commit 5f2fbf7

Browse files
committed
Fix varinfo parsing for luajit local var name lookup
We were decrementing the slot when PC was out of bounds which is wrong because LuaJIT reuses stack slots for locals in different scopes. This caused us to hit on local var lookup instead of failing and falling through to looking at bytecode names. Add a test case lifted from luajit that shows slots being reused for different variables and remove old unhelpful test case.
1 parent 21da566 commit 5f2fbf7

File tree

2 files changed

+43
-53
lines changed

2 files changed

+43
-53
lines changed

interpreter/luajit/proto.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -356,13 +356,15 @@ func parseVarinfo(b []byte, pc, slot uint32) string {
356356
}
357357
b, pcdelta = parseULEB128(b)
358358
endpc := startpc + pcdelta
359-
if pc < endpc && slot == 0 {
360-
if vn <= len(varnames) {
361-
return varnames[vn-1]
359+
if pc < endpc {
360+
if slot == 0 {
361+
if vn <= len(varnames) {
362+
return varnames[vn-1]
363+
}
364+
return name
362365
}
363-
return name
366+
slot--
364367
}
365-
slot--
366368
}
367369
return ""
368370
}

interpreter/luajit/proto_test.go

Lines changed: 36 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -12,59 +12,47 @@
1212
package luajit
1313

1414
import (
15-
"strconv"
16-
"strings"
1715
"testing"
1816

1917
"github.com/stretchr/testify/require"
2018
)
2119

22-
// literal go
23-
// add commas between each element
24-
//
25-
//nolint:lll
26-
const bytes = "105 110 112 117 116 0 0 99 108 101 110 0 14 85 100 105 99 116 0 8 77 97 0 2 75 98 0 0 75 114 101 115 117 108 116 0 1 74 114 101 115 117 108 116 108 101 110 0 1 73 110 0 1 72 119 111 114 100 0 1 71 1 3 49 2 0 49 3 0 49 105 0 1 47 99 0 5 42 119 99 0 3 39 119 114 105 116 101 0 12 25 0"
27-
2820
func TestParseVarinfo(t *testing.T) {
29-
strs := strings.Split(bytes, " ")
30-
b := make([]byte, len(strs))
31-
for i, s := range strs {
32-
num, err := strconv.ParseInt(s, 10, 8)
33-
require.NoError(t, err)
34-
b[i] = byte(num)
21+
b := []byte{0x66, 0x75, 0x6e, 0x63, 0x0, 0x0, 0xdc, 0x1, 0x70, 0x63, 0x0, 0x0, 0xdc, 0x1, 0x70,
22+
0x72, 0x65, 0x66, 0x69, 0x78, 0x0, 0x0, 0xdc, 0x1, 0x6c, 0x69, 0x6e, 0x65, 0x69, 0x6e,
23+
0x66, 0x6f, 0x0, 0x0, 0xdc, 0x1, 0x69, 0x6e, 0x73, 0x0, 0xa, 0xd2, 0x1, 0x6d, 0x0, 0x0,
24+
0xd2, 0x1, 0x6c, 0x0, 0x0, 0xd2, 0x1, 0x6d, 0x61, 0x0, 0xf, 0xc3, 0x1, 0x6d, 0x62, 0x0,
25+
0x0, 0xc3, 0x1, 0x6d, 0x63, 0x0, 0x0, 0xc3, 0x1, 0x61, 0x0, 0x7, 0xbc, 0x1, 0x6f, 0x69,
26+
0x64, 0x78, 0x0, 0x5, 0xb7, 0x1, 0x6f, 0x70, 0x0, 0x5, 0xb2, 0x1, 0x73, 0x0, 0x1, 0xb1,
27+
0x1, 0x64, 0x0, 0x27, 0x8a, 0x1, 0x6b, 0x63, 0x0, 0x17, 0x73, 0x66, 0x69, 0x0, 0x2c, 0x9,
28+
0x6b, 0x61, 0x0, 0x17, 0x8, 0x62, 0x0, 0xe, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x79,
29+
0xf5, 0x0}
30+
for _, tc := range []struct {
31+
name string
32+
startpc, endp uint32
33+
slot uint32
34+
}{
35+
{"func", 0, 220, 0},
36+
{"pc", 0, 220, 1},
37+
{"prefix", 0, 220, 2},
38+
{"lineinfo", 0, 220, 3},
39+
{"ins", 10, 220, 4},
40+
{"m", 10, 220, 5},
41+
{"l", 10, 220, 6},
42+
{"ma", 25, 220, 7},
43+
{"mb", 25, 220, 8},
44+
{"mc", 25, 220, 9},
45+
{"a", 32, 220, 10},
46+
{"oidx", 37, 220, 11},
47+
{"op", 42, 220, 12},
48+
{"s", 43, 220, 13},
49+
{"d", 82, 220, 14},
50+
{"kc", 105, 220, 15},
51+
{"fi", 149, 158, 16},
52+
{"ka", 172, 180, 16},
53+
{"b", 186, 201, 16},
54+
} {
55+
s := parseVarinfo(b, tc.startpc, tc.slot)
56+
require.Equal(t, s, tc.name)
3557
}
36-
str := parseVarinfo(b, 2, 0)
37-
t.Log(str)
38-
str = parseVarinfo(b, 14, 1)
39-
t.Log(str)
40-
str = parseVarinfo(b, 23, 2)
41-
t.Log(str)
42-
str = parseVarinfo(b, 40, 3)
43-
t.Log(str)
44-
str = parseVarinfo(b, 40, 4)
45-
t.Log(str)
46-
str = parseVarinfo(b, 40, 5)
47-
t.Log(str)
48-
str = parseVarinfo(b, 40, 6)
49-
t.Log(str)
50-
str = parseVarinfo(b, 40, 7)
51-
t.Log(str)
52-
str = parseVarinfo(b, 40, 8)
53-
t.Log(str)
54-
str = parseVarinfo(b, 40, 9)
55-
t.Log(str)
56-
str = parseVarinfo(b, 40, 10)
57-
t.Log(str)
58-
str = parseVarinfo(b, 40, 11)
59-
t.Log(str)
60-
str = parseVarinfo(b, 40, 12)
61-
t.Log(str)
62-
str = parseVarinfo(b, 40, 13)
63-
t.Log(str)
64-
str = parseVarinfo(b, 40, 14)
65-
t.Log(str)
66-
str = parseVarinfo(b, 60, 15)
67-
t.Log(str)
68-
str = parseVarinfo(b, 60, 16)
69-
t.Log(str)
7058
}

0 commit comments

Comments
 (0)