Concepts
Integer is a basic data types. Golang supports integer data types extensively. Integer are divided into two types which are signed and unsigned integer. Now we will see it’s types
Signed integer in go
Types | Range |
---|---|
Types | Range |
int8 | -128 to 127 |
int16 | -32768 to 32767 |
int32 | -2147483648 to 2147483647 |
int64 | -9223372036854775808 to 9223372036854775807 |
Types of signed integer
Unsigned integer in Golang
Types | Range |
---|---|
Types | Range |
uint8 | 0 to 255 |
uint16 | 0 to 65535 |
uint32 | 0 to 4294967295 |
uint64 | 0 to 18446744073709551615 |
The other two integer types are the most commonly used: int and uint. These two types have a size that depends on the system architecture: 32 bits on 32 bits systems or 64 bits on 64-bbit systems.
Integer Overflow
Now, Let’s talk about integer overflow. If a program performs a calculation and the true answer is larger than the available space,it may result in an integer overflow. It can cause the program to use incorrect numbers and respond in unintended ways, which can be exploited by attackers. Unexpected integer overflow can lead to serious bugs. An integer overflow occurs when an arithmetic operation creates a value outside the range.
Let’s now discuss integer overflow. Suppose we want to initialize an int8 to its maximum value and then increment it. What should be the behavior of this code?
var counter int8 = math.MaxInt8
counter++
fmt.Printf("counter=%d\n", counter)
This code compiles and doesn’t panic at runtime. However, the counter++ statement generates an integer overflow:
counter=-128
An int8 is represented using 8 bits. Here is the binary representation of the maximum int8 value (math.MaxInt8):
0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
7 bits set to 1
Because an int8 is signed integer, the bit on the left represents the integer’s sign: 0 for positive, 1 for negative. If we increment this integer, there is no space left to represent the new value. Hence, this leads to an integer overflow. Binary wise here’s the new value:
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
In Go, an integer overflow that can be detected at compile time generates a compilation error. For example:
var counter int8 = math.MaxInt8 + 1
However, at run time, an integer overflow is silent, this does not lead to an application panic. It is essential to keep this behavior in mind, because it can lead to sneaky bugs (for example, an integer increment or addition of positive integers that leads to negative result.)
Detecting integer overflow
To detect an overflow with common operations. In most contexts, like handling a counter of requests or basic additions/multiplications, we shouldn’t worry too much if we use the right integer type. But in some cases, like memory constrained projects using smaller integer types, dealing with large numbers, or doing conversions. Following are the possible integer overflow scenarios:
- Detecting integer overflow when incrementing
- Detecting integer overflows during addition
- Detecting an integer overflow during multiplication
Detecting integer overflow when increment
If we want to detect an integer overflow during an increment operation with a type based on a defined size (int8,int16,int32,int64,uint8,uint16,uint32,uint64). We can check the value against the math constants. For example, with an int8:
func incrementNumber(counter int8) int8 {
if counter == math.MaxInt8 {
panic("integer overflow")
}
return counter + 1
}
This function checks whether the input is already equal to math.MaxInt8. If it matches the case it panic the code with overflow message.
In summary, integer overflows are silent operation in Go. If we want to check for overflows to avoid unexpected errors, we can use the utility functions. If int is not enough, You may use package math/big which is provided by Go.
References:
- 100 Go Mistakes and how to avoid them, Teiva Harsanyi, Manning Publications Co