diff --git a/internal/kconfig/kconfig.go b/internal/kconfig/kconfig.go index fa5308578..1921e4f15 100644 --- a/internal/kconfig/kconfig.go +++ b/internal/kconfig/kconfig.go @@ -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)) diff --git a/internal/kconfig/kconfig_test.go b/internal/kconfig/kconfig_test.go index 362123737..19f42f745 100644 --- a/internal/kconfig/kconfig_test.go +++ b/internal/kconfig/kconfig_test.go @@ -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")) +}