https://github.com/ccoveille/go-safecast
Safe number conversion in Go: address gosec G115 and cwe-190 Integer Overflow or Wraparound
https://github.com/ccoveille/go-safecast
Last synced: about 2 months ago
JSON representation
Safe number conversion in Go: address gosec G115 and cwe-190 Integer Overflow or Wraparound
- Host: GitHub
- URL: https://github.com/ccoveille/go-safecast
- Owner: ccoVeille
- License: mit
- Created: 2024-09-05T18:04:05.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2025-03-31T16:09:28.000Z (3 months ago)
- Last Synced: 2025-03-31T17:26:04.420Z (3 months ago)
- Language: Go
- Homepage:
- Size: 59.6 KB
- Stars: 52
- Watchers: 2
- Forks: 4
- Open Issues: 11
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# 🪄 go-safecast: safe numbers conversion
[](https://goreportcard.com/report/github.com/ccoveille/go-safecast)
[](https://godoc.org/github.com/ccoVeille/go-safecast)
[](https://codecov.io/gh/ccoVeille/go-safecast)
[](https://codeclimate.com/github/ccoVeille/go-safecast)
[](https://github.com/search?q=%22%5C%22github.com%2Fccoveille%2Fgo-safecast%5C%22%22+language%3Ago++-is%3Afork+-is%3Aarchived+&type=code)
go-safecast solves the type conversion issues in Go
In Go, integer type conversion can lead to a silent and unexpected behavior and errors if not handled carefully.
This package helps to convert any number to another, and report an error when if there would be a [loss or overflow in the conversion](#conversion-issues)
## Usage
```go
package mainimport (
"fmt"
"math""github.com/ccoveille/go-safecast"
)func main() {
var a inta = 42
b, err := safecast.ToUint8(a) // everything is fine
if err != nil {
fmt.Println(err)
}
fmt.Println(b)
// Output: 42a = 255 + 1
_, err = safecast.ToUint8(a) // 256 is greater than uint8 maximum value
if err != nil {
fmt.Println(err)
// Output: conversion issue: 256 (int) is greater than 255 (uint8): maximum value for this type exceeded
}a = -1
_, err = safecast.ToUint8(a) // -1 cannot fit in uint8
if err != nil {
fmt.Println(err)
// Output: conversion issue: -1 (int) is less than 0 (uint8): minimum value for this type exceeded
}str := "\x99" // ASCII code 153 for Trademark symbol
e := str[0]
_, err = safecast.ToInt8(e)
if err != nil {
fmt.Println(err)
// Output: conversion issue: 153 (uint8) is greater than 127 (int8): maximum value for this type exceeded
}
}
```[Go Playground](https://go.dev/play/p/nelJshulOnj)
## Conversion issues
Issues can happen when converting between signed and unsigned integers, or when converting to a smaller integer type.
```go
package mainimport "fmt"
func main() {
var a int64
a = 42
b := uint8(a)
fmt.Println(b) // 42a = 255 // this is the math.MaxUint8
b = uint8(a)
fmt.Println(b) // 255a = 255 + 1
b = uint8(a)
fmt.Println(b) // 0 conversion overflowa = -1
b = uint8(a)
fmt.Println(b) // 255 conversion overflow
}
```[Go Playground](https://go.dev/play/p/DHfNUcZBvVn)
So you need to adapt your code to write something like this.
```go
package mainimport "fmt"
func main() {
var a int64
a = 42
if a < 0 || a > math.MaxUint8 {
log.Println("overflow") // Output: overflow
}
fmt.Println(b) // 42a = 255 // this is the math.MaxUint8
b = uint8(a)
fmt.Println(b) // 255a = 255 + 1
b = uint8(a)
if a < 0 || a > math.MaxUint8 {
log.Println("overflow") // Output: overflow
}
fmt.Println(b) // Output: 0a = -1
b = uint8(a)
if a < 0 || a > math.MaxUint8 {
log.Println("overflow") // Output: overflow
}
fmt.Println(b) // Output:255
}
```[Go Playground](https://go.dev/play/p/qAHGyy4NCLP)
`go-safecast` is there to avoid boilerplate copy pasta.
## Motivation
The gosec project raised this to my attention when the gosec [G115 rule was added](https://github.com/securego/gosec/pull/1149)
> G115: Potential overflow when converting between integer types.
This issue was way more complex than expected, and required multiple fixes.
[CWE-190](https://cwe.mitre.org/data/definitions/190.html) explains in detail.
But to sum it up, you can face:
- infinite loop
- access to wrong resource by id
- grant access to someone who exhausted their quotaThe gosec G115 will now report issues in a lot of project.
## Alternatives
Some libraries existed, but they were not able to cover all the use cases.
- [github.com/rung/go-safecast](https://github.com/rung/go-safecast):
Unmaintained, not architecture agnostic, do not support `uint` -> `int` conversion- [github.com/cybergarage/go-safecast](https://github.com/cybergarage/go-safecast)
Work with pointer like `json.Marshall`## Stargazers over time
[](https://starchart.cc/ccoVeille/go-safecast)