aboutsummaryrefslogtreecommitdiffstats
path: root/prog
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2019-12-20 13:57:42 +0100
committerDmitry Vyukov <dvyukov@google.com>2019-12-20 16:45:34 +0100
commitae5ed0b14052adc4be0d98e5e8a46a0b0ab2c565 (patch)
tree162cebcc1f8d487399415f1b11ac9738fabd7ec7 /prog
parent4bba9fd1629d5351877b21fc662a125342a18a9e (diff)
pkg/compiler: fix bitfield layout bug
Fixes #1542 Found thanks to syz-check. Update #590
Diffstat (limited to 'prog')
-rw-r--r--prog/any_test.go2
-rw-r--r--prog/encodingexec.go1
-rw-r--r--prog/encodingexec_test.go24
-rw-r--r--prog/types.go18
4 files changed, 28 insertions, 17 deletions
diff --git a/prog/any_test.go b/prog/any_test.go
index 4e162258c..eaa5bddf6 100644
--- a/prog/any_test.go
+++ b/prog/any_test.go
@@ -45,7 +45,7 @@ func TestSquash(t *testing.T) {
}{
{
`foo$any0(&(0x7f0000000000)={0x11, 0x11223344, 0x2233, 0x1122334455667788, {0x1, 0x7, 0x1, 0x1, 0x1bc, 0x4}, [{0x0, @res32=0x0, 0x0, @i8=0x44, "aabb"}, {0x0, @res64=0x1, 0x0, @i32=0x11223344, "1122334455667788"}]})`,
- `foo$any0(&(0x7f0000000000)=ANY=[@ANYBLOB="1100000044332211223300000000000088776655443322113d0079230000000000000000", @ANYRES32=0x0, @ANYBLOB="00000000000000000000000044aabb000000000000000000", @ANYRES64=0x1, @ANYBLOB="000000000000000044332211112233445566778800000000"])`,
+ `foo$any0(&(0x7f0000000000)=ANY=[@ANYBLOB="1100000044332211223300000000000088776655443322117d00bc110000000000000000", @ANYRES32=0x0, @ANYBLOB="00000000000000000000000044aabb000000000000000000", @ANYRES64=0x1, @ANYBLOB="000000000000000044332211112233445566778800000000"])`,
},
}
for i, test := range tests {
diff --git a/prog/encodingexec.go b/prog/encodingexec.go
index 2e69f2116..45fb2d75e 100644
--- a/prog/encodingexec.go
+++ b/prog/encodingexec.go
@@ -125,6 +125,7 @@ func (w *execContext) writeCopyin(c *Call) {
return
}
addr := w.target.PhysicalAddr(ctx.Base) + ctx.Offset
+ addr -= arg.Type().UnitOffset()
if w.willBeUsed(arg) {
w.args[arg] = argInfo{Addr: addr}
}
diff --git a/prog/encodingexec_test.go b/prog/encodingexec_test.go
index 7a5c066b8..6e2e5f61f 100644
--- a/prog/encodingexec_test.go
+++ b/prog/encodingexec_test.go
@@ -249,10 +249,10 @@ func TestSerializeForExec(t *testing.T) {
execInstrCopyin, dataOffset + 8, execArgConst, 8, 0x42,
execInstrCopyin, dataOffset + 16, execArgConst, 2 | 0<<16 | 5<<24, 0x42,
execInstrCopyin, dataOffset + 16, execArgConst, 2 | 5<<16 | 6<<24, 0x42,
- execInstrCopyin, dataOffset + 20, execArgConst, 4 | 0<<16 | 15<<24, 0x42,
- execInstrCopyin, dataOffset + 24, execArgConst, 2 | 0<<16 | 11<<24, 0x42,
- execInstrCopyin, dataOffset + 26, execArgConst, 2 | 1<<8 | 0<<16 | 11<<24, 0x42,
- execInstrCopyin, dataOffset + 28, execArgConst, 1, 0x42,
+ execInstrCopyin, dataOffset + 16, execArgConst, 4 | 11<<16 | 15<<24, 0x42,
+ execInstrCopyin, dataOffset + 20, execArgConst, 2 | 0<<16 | 11<<24, 0x42,
+ execInstrCopyin, dataOffset + 22, execArgConst, 2 | 1<<8 | 0<<16 | 11<<24, 0x42,
+ execInstrCopyin, dataOffset + 24, execArgConst, 1, 0x42,
callID("test$bf0"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
},
@@ -303,16 +303,16 @@ func TestSerializeForExec(t *testing.T) {
},
},
{
- Addr: dataOffset + 20,
+ Addr: dataOffset + 16,
Arg: ExecArgConst{
Size: 4,
Value: 0x42,
- BitfieldOffset: 0,
+ BitfieldOffset: 11,
BitfieldLength: 15,
},
},
{
- Addr: dataOffset + 24,
+ Addr: dataOffset + 20,
Arg: ExecArgConst{
Size: 2,
Value: 0x42,
@@ -321,7 +321,7 @@ func TestSerializeForExec(t *testing.T) {
},
},
{
- Addr: dataOffset + 26,
+ Addr: dataOffset + 22,
Arg: ExecArgConst{
Size: 2,
Format: FormatBigEndian,
@@ -331,7 +331,7 @@ func TestSerializeForExec(t *testing.T) {
},
},
{
- Addr: dataOffset + 28,
+ Addr: dataOffset + 24,
Arg: ExecArgConst{
Size: 1,
Value: 0x42,
@@ -394,9 +394,9 @@ func TestSerializeForExec(t *testing.T) {
execInstrCopyin, dataOffset + 0, execArgConst, 1 | 0<<16 | 1<<24, 0x1,
execInstrCopyin, dataOffset + 0, execArgConst, 1 | 1<<16 | 1<<24, 0x2,
execInstrCopyin, dataOffset + 0, execArgConst, 1 | 2<<16 | 1<<24, 0x3,
- execInstrCopyin, dataOffset + 1, execArgConst, 2 | 0<<16 | 1<<24, 0x4,
- execInstrCopyin, dataOffset + 1, execArgConst, 2 | 1<<16 | 1<<24, 0x5,
- execInstrCopyin, dataOffset + 1, execArgConst, 2 | 2<<16 | 1<<24, 0x6,
+ execInstrCopyin, dataOffset + 0, execArgConst, 2 | 3<<16 | 1<<24, 0x4,
+ execInstrCopyin, dataOffset + 0, execArgConst, 2 | 4<<16 | 1<<24, 0x5,
+ execInstrCopyin, dataOffset + 0, execArgConst, 2 | 5<<16 | 1<<24, 0x6,
execInstrCopyin, dataOffset + 8, execArgConst, 1, 0x42,
callID("test$align7"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
diff --git a/prog/types.go b/prog/types.go
index 6b2d37e07..0d9bb1604 100644
--- a/prog/types.go
+++ b/prog/types.go
@@ -65,6 +65,7 @@ type Type interface {
// These are different only for all but last bitfield in the group,
// where Size == 0 and UnitSize equals to the underlying bitfield type size.
UnitSize() uint64
+ UnitOffset() uint64
DefaultArg() Arg
isDefaultArg(arg Arg) bool
@@ -134,6 +135,10 @@ func (t *TypeCommon) UnitSize() uint64 {
return t.Size()
}
+func (t *TypeCommon) UnitOffset() uint64 {
+ return 0
+}
+
func (t *TypeCommon) IsBitfield() bool {
return false
}
@@ -189,10 +194,11 @@ func (t *ResourceType) Format() BinaryFormat {
type IntTypeCommon struct {
TypeCommon
- ArgFormat BinaryFormat
- BitfieldOff uint64
- BitfieldLen uint64
- BitfieldUnit uint64
+ ArgFormat BinaryFormat
+ BitfieldOff uint64
+ BitfieldLen uint64
+ BitfieldUnit uint64
+ BitfieldUnitOff uint64
}
func (t *IntTypeCommon) String() string {
@@ -231,6 +237,10 @@ func (t *IntTypeCommon) UnitSize() uint64 {
return t.Size()
}
+func (t *IntTypeCommon) UnitOffset() uint64 {
+ return t.BitfieldUnitOff
+}
+
func (t *IntTypeCommon) IsBitfield() bool {
return t.BitfieldLen != 0
}