Skip to content

Commit

Permalink
doc: improve the README
Browse files Browse the repository at this point in the history
Fixes #22
  • Loading branch information
ccoVeille committed Sep 9, 2024
1 parent ddf82b9 commit f5380f5
Showing 1 changed file with 45 additions and 40 deletions.
85 changes: 45 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,69 +1,76 @@
# Go SafeCast
# 🪄 go-safecast: safe numbers conversion

[![Go Report Card](https://goreportcard.com/badge/github.com/ccoveille/go-safecast)](https://goreportcard.com/report/github.com/ccoveille/go-safecast)
[![GoDoc](https://godoc.org/github.com/ccoVeille/go-safecast?status.svg)](https://godoc.org/github.com/ccoVeille/go-safecast)
[![codecov](https://codecov.io/gh/ccoVeille/go-safecast/graph/badge.svg?token=VW0VO503U6)](https://codecov.io/gh/ccoVeille/go-safecast)
[![Code Climate](https://codeclimate.com/github/ccoVeille/go-safecast.png)](https://codeclimate.com/github/ccoVeille/go-safecast)

## Origin of this project
## Project purpose

In Go, integer type conversion can lead to unexpected behavior and errors if not handled carefully.
In Go, integer type conversion can lead to a silent and unexpected behavior and errors if not handled carefully.

Issues can happen when converting between signed and unsigned integers, or when converting to a smaller integer type.

The gosec project raised this to my attention when the gosec [G115 rule was added](https://github.com/securego/gosec/pull/1149)

> G115: Potential integer overflow when converting between integer types
This package is made to help to convert any number to another, and report an error when if there would be a [loss or overflow in the conversion](#conversion-overflows)

This issue was way more complex than expected, and required multiple fixes.

## Example

This code seems OK
## Usage

```go
package main

import (
"fmt"
"fmt"

"github.com/ccoveille/go-safecast"
)

func main() {
var a uint64
a = 42
b := int32(a)
fmt.Println(b) // 42
_, err := safecast.ToInt8(uint16(1000))
fmt.Println(err) // integer overflow: 1000 (uint16) is greater than 127 (int8): exceed upper boundary for this type

_, err = safecast.ToUint16(int64(-1))
fmt.Println(err) // integer overflow: -1 (int64) is smaller than 0 (uint16): exceed lower boundary for this type
}
```

But the conversion to int32 will behave differently depending on the value
[Go Playground](https://go.dev/play/p/ciic-m0cdfb)

## Conversion overflows

Issues can happen when converting between signed and unsigned integers, or when converting to a smaller integer type.

```go
package main

import (
"fmt"
)
import "fmt"

func main() {
var a uint64
a = 2147483647
b := int32(a)
fmt.Println(b) // 2147483647

a = 2147483647 + 1
b = int32(a)
fmt.Println(b) // -2147483648 integer overflow

c := -1
d := uint32(c)
fmt.Println(d) // 4294967295
var a int64
a = 42
b := uint8(a)
fmt.Println(b) // 42

a = 255 // this is the math.MaxUint8
b = uint8(a)
fmt.Println(b) // 255

a = 255 + 1
b = uint8(a)
fmt.Println(b) // 0 integer overflow

a = -1
b = uint8(a)
fmt.Println(b) // 255 integer overflow
}
```

GoPlay: [https://go.dev/play/p/9PRWI7e0x1T](https://go.dev/play/p/9PRWI7e0x1T)
[Go Playground](https://go.dev/play/p/DHfNUcZBvVn)

## Motivation

The gosec project raised this to my attention when the gosec [G115 rule was added](https://github.com/securego/gosec/pull/1149)

### What is the problem ?
> G115: Potential integer 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.

Expand All @@ -73,16 +80,14 @@ But to sum it up, you can face:
- access to wrong resource by id
- grant access to someone who exhausted their quota

## Motivation

The 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
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
Work with pointer like `json.Marshall`

0 comments on commit f5380f5

Please sign in to comment.