Skip to content

Commit

Permalink
kconfig: add over/underflow checks and tests for PutInteger
Browse files Browse the repository at this point in the history
Fixes: #1323

Signed-off-by: atgane <[email protected]>
Co-authored-by: Timo Beckers <[email protected]>
  • Loading branch information
atgane and ti-mo committed Feb 20, 2024
1 parent ff37506 commit 8b285e7
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 0 deletions.
13 changes: 13 additions & 0 deletions internal/kconfig/kconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,12 +263,25 @@ func PutInteger(data []byte, integer *btf.Int, n uint64) error {
return fmt.Errorf("invalid boolean value: %d", n)
}

if len(data) < int(integer.Size) {
return fmt.Errorf("can't fit an integer of size %d into a byte slice of length %d", integer.Size, len(data))
}

switch integer.Size {
case 1:
if integer.Encoding == btf.Signed && (int64(n) > math.MaxInt8 || int64(n) < math.MinInt8) {
return fmt.Errorf("can't represent %d as a signed integer of size %d", int64(n), integer.Size)
}
data[0] = byte(n)
case 2:
if integer.Encoding == btf.Signed && (int64(n) > math.MaxInt16 || int64(n) < math.MinInt16) {
return fmt.Errorf("can't represent %d as a signed integer of size %d", int64(n), integer.Size)
}
internal.NativeEndian.PutUint16(data, uint16(n))
case 4:
if integer.Encoding == btf.Signed && (int64(n) > math.MaxInt32 || int64(n) < math.MinInt32) {
return fmt.Errorf("can't represent %d as a signed integer of size %d", int64(n), integer.Size)
}
internal.NativeEndian.PutUint32(data, uint32(n))
case 8:
internal.NativeEndian.PutUint64(data, uint64(n))
Expand Down
111 changes: 111 additions & 0 deletions internal/kconfig/kconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -416,3 +416,114 @@ func TestPutValue(t *testing.T) {
qt.Assert(t, qt.DeepEquals(data, expected))
}
}

func TestPutInteger(t *testing.T) {
t.Parallel()

type testCase struct {
expected []byte
integer *btf.Int
n uint64
err bool
comment string
}

cases := []testCase{
{
integer: &btf.Int{Size: 1, Encoding: btf.Unsigned},
n: 0x01,
expected: []byte{0x01},
},
{
integer: &btf.Int{Size: 2, Encoding: btf.Unsigned},
n: 0x902a,
expected: []byte{0x2a, 0x90},
},
{
integer: &btf.Int{Size: 4, Encoding: btf.Unsigned},
n: 0x01234567,
expected: []byte{0x67, 0x45, 0x23, 0x01},
},
{
integer: &btf.Int{Size: 1, Encoding: btf.Signed},
n: 0x80,
err: true,
comment: "outside of range int8 -128 ~ 127",
},
{
integer: &btf.Int{Size: 2, Encoding: btf.Signed},
n: 0xabcdabcd,
err: true,
comment: "outside of range int16 -32768 ~ 32767",
},
{
integer: &btf.Int{Size: 4, Encoding: btf.Signed},
n: 0x1234567890,
err: true,
comment: "outside of range int32 -2147483648 ~ 2147483647",
},
{
integer: &btf.Int{Size: 2, Encoding: btf.Signed},
n: 0xffffffffffffffff,
expected: []byte{0xff, 0xff, 0x00, 0x00},
comment: "n means -1",
},
{
integer: &btf.Int{Size: 2, Encoding: btf.Signed},
n: 0xffffffffffffffff - 0x8000,
err: true,
comment: "n means -32768(-MinInt16) - 1 in signed value",
},
{
integer: &btf.Int{Size: 2, Encoding: btf.Signed},
n: 0x7fff,
expected: []byte{0xff, 0x7f},
comment: "maximum value of int16",
},
{
integer: &btf.Int{Size: 2, Encoding: btf.Unsigned},
n: 0xffff,
expected: []byte{0xff, 0xff},
},
{
integer: &btf.Int{Size: 4, Encoding: btf.Unsigned},
n: 0xffffffff,
expected: []byte{0xff, 0xff, 0xff, 0xff},
},
{
integer: &btf.Int{Size: 4, Encoding: btf.Signed},
n: 0x80000000,
err: true,
comment: "outside of range int32 ~2147483648 ~ 2147483647",
},
{
integer: &btf.Int{Size: 4, Encoding: btf.Signed},
n: 0xffffffffffffffff - 0x80000000,
err: true,
comment: "outside of range int32 ~2147483648 ~ 2147483647",
},
{
integer: &btf.Int{Size: 8, Encoding: btf.Unsigned},
n: 0xffffffffffffffff,
expected: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
},
}

for _, c := range cases {
data := make([]byte, len(c.expected))
err := PutInteger(data, c.integer, c.n)

if c.err {
qt.Assert(t, qt.IsNotNil(err))
continue
}

qt.Assert(t, qt.IsNil(err))
qt.Assert(t, qt.DeepEquals(data, c.expected), qt.Commentf(c.comment))
}
}

func TestPutIntegerError(t *testing.T) {
qt.Assert(t, qt.IsNotNil(PutInteger(nil, &btf.Int{Size: 2}, 0)), qt.Commentf("slice too small for int"))
qt.Assert(t, qt.IsNotNil(PutInteger(nil, &btf.Int{Encoding: btf.Bool}, 2)), qt.Commentf("n too big for bool"))
}

0 comments on commit 8b285e7

Please sign in to comment.