Skip to content

Commit 1f6d34d

Browse files
aykevldeadprogram
authored andcommitted
interp: make getelementptr offsets signed
getelementptr offsets are signed, not unsigned. Yet they were used as unsigned integers in interp. Somehow this worked most of the time, until finally there was some code that did a getelementptr with a negative index.
1 parent 9951eb9 commit 1f6d34d

File tree

3 files changed

+14
-5
lines changed

3 files changed

+14
-5
lines changed

interp/interpreter.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -644,11 +644,11 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
644644
case llvm.GetElementPtr:
645645
// GetElementPtr does pointer arithmetic, changing the offset of the
646646
// pointer into the underlying object.
647-
var offset uint64
647+
var offset int64
648648
for i := 1; i < len(operands); i += 2 {
649-
index := operands[i].Uint()
650-
elementSize := operands[i+1].Uint()
651-
if int64(elementSize) < 0 {
649+
index := operands[i].Int()
650+
elementSize := operands[i+1].Int()
651+
if elementSize < 0 {
652652
// This is a struct field.
653653
offset += index
654654
} else {
@@ -662,7 +662,7 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
662662
return nil, mem, r.errorAt(inst, err)
663663
}
664664
// GEP on fixed pointer value (for example, memory-mapped I/O).
665-
ptrValue := operands[0].Uint() + offset
665+
ptrValue := operands[0].Uint() + uint64(offset)
666666
locals[inst.localIndex] = makeLiteralInt(ptrValue, int(operands[0].len(r)*8))
667667
continue
668668
}

interp/testdata/basic.ll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ target triple = "x86_64--linux"
1010
@main.exposedValue1 = global i16 0
1111
@main.exposedValue2 = global i16 0
1212
@main.insertedValue = global {i8, i32, {float, {i64, i16}}} zeroinitializer
13+
@main.gepArray = global [8 x i8] zeroinitializer
14+
@main.negativeGEP = global ptr null
1315

1416
declare void @runtime.printint64(i64) unnamed_addr
1517

@@ -88,6 +90,11 @@ entry:
8890
%agg2 = insertvalue {i8, i32, {float, {i64, i16}}} %agg, i64 5, 2, 1, 0
8991
store {i8, i32, {float, {i64, i16}}} %agg2, ptr @main.insertedValue
9092

93+
; negative GEP instruction
94+
%ngep1 = getelementptr [8 x i8], ptr @main.negativeGEP, i32 0, i32 5
95+
%ngep2 = getelementptr [8 x i8], ptr %ngep1, i32 0, i32 -3
96+
store ptr %ngep2, ptr @main.negativeGEP
97+
9198
ret void
9299
}
93100

interp/testdata/basic.out.ll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ target triple = "x86_64--linux"
99
@main.exposedValue1 = global i16 0
1010
@main.exposedValue2 = local_unnamed_addr global i16 0
1111
@main.insertedValue = local_unnamed_addr global { i8, i32, { float, { i64, i16 } } } zeroinitializer
12+
@main.gepArray = local_unnamed_addr global [8 x i8] zeroinitializer
13+
@main.negativeGEP = global ptr getelementptr inbounds (i8, ptr @main.negativeGEP, i64 2)
1214

1315
declare void @runtime.printint64(i64) unnamed_addr
1416

0 commit comments

Comments
 (0)