feat(cgo): validate Int conversion against C.int width
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
c95429fbbd
commit
42d6b0441e
2 changed files with 44 additions and 2 deletions
32
call_test.go
32
call_test.go
|
|
@ -21,6 +21,38 @@ func TestSizeTAndIntConversions(t *testing.T) {
|
|||
if got := Int(4096); got != 4096 {
|
||||
t.Fatalf("expected Int(4096) to be 4096, got %v", got)
|
||||
}
|
||||
|
||||
cIntBits := cIntBitSize()
|
||||
maxInt := int64(int(^uint(0) >> 1))
|
||||
minInt := -maxInt - 1
|
||||
cIntMax := int64(1)<<(cIntBits-1) - 1
|
||||
cIntMin := -cIntMax - 1
|
||||
|
||||
// Verify exact C.int boundaries for this platform.
|
||||
if cIntMax <= maxInt {
|
||||
got := Int(int(cIntMax))
|
||||
if int(got) != int(cIntMax) {
|
||||
t.Fatalf("expected Int(%d) to be %d, got %v", cIntMax, cIntMax, got)
|
||||
}
|
||||
}
|
||||
if cIntMin >= minInt {
|
||||
got := Int(int(cIntMin))
|
||||
if int(got) != int(cIntMin) {
|
||||
t.Fatalf("expected Int(%d) to be %d, got %v", cIntMin, cIntMin, got)
|
||||
}
|
||||
}
|
||||
|
||||
// Int should panic when value is outside C.int range.
|
||||
if cIntMax < maxInt {
|
||||
assertPanics(t, "value exceeds C.int range", func() {
|
||||
_ = Int(int(cIntMax + 1))
|
||||
})
|
||||
}
|
||||
if cIntMin > minInt {
|
||||
assertPanics(t, "value exceeds C.int range", func() {
|
||||
_ = Int(int(cIntMin - 1))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCallWrapsZeroAndNonZeroReturns(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -73,12 +73,22 @@ func SizeT(value int) C.size_t {
|
|||
//
|
||||
// rc := cgo.Int(returnCode)
|
||||
func Int(value int) C.int {
|
||||
if value < -2147483648 || value > 2147483647 {
|
||||
panic("cgo.Int: value exceeds C.int range")
|
||||
cIntBits := cIntBitSize()
|
||||
if cIntBits < strconv.IntSize {
|
||||
maxValue := (int64(1) << (cIntBits - 1)) - 1
|
||||
minValue := -maxValue - 1
|
||||
casted := int64(value)
|
||||
if casted < minValue || casted > maxValue {
|
||||
panic("cgo.Int: value exceeds C.int range")
|
||||
}
|
||||
}
|
||||
return C.int(value)
|
||||
}
|
||||
|
||||
func cIntBitSize() int {
|
||||
return int(unsafe.Sizeof(C.int(0)) * 8)
|
||||
}
|
||||
|
||||
// Call invokes a C function pointer and maps a non-zero return into a Go error.
|
||||
//
|
||||
// err := cgo.Call(unsafe.Pointer(C.some_function), cgo.SizeT(len(data)))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue