trailofbits.go.string-to-int-signedness-cast.string-to-int-signedness-cast

Author
232
Download Count*
License
Downcasting or changing sign of an integer with $CAST_METHOD
method
Run Locally
Run in CI
Defintion
rules:
- id: string-to-int-signedness-cast
message: Downcasting or changing sign of an integer with `$CAST_METHOD` method
languages:
- go
severity: WARNING
metadata:
category: security
cwe: "CWE-681: Incorrect Conversion between Numeric Types"
subcategory:
- audit
confidence: HIGH
likelihood: LOW
impact: MEDIUM
technology:
- --no-technology--
description: Integer underflows
references:
- https://github.com/golang/go/issues/30209
license: CC-BY-NC-SA-4.0
pattern-either:
- patterns:
- metavariable-pattern:
metavariable: $CAST_METHOD
pattern-either:
- pattern: uint8
- pattern: uint16
- pattern: uint32
- pattern: int8
- pattern: int16
- pattern: int32
- pattern-either:
- pattern: |
$X, ... = strconv.Atoi(...)
...
$CAST_METHOD($X)
- pattern: |
$X, ... = strconv.ParseInt(..., ..., 64)
...
$CAST_METHOD($X)
- pattern: |
$X, ... = strconv.ParseUint(..., ..., 64)
...
$CAST_METHOD($X)
- pattern: |
$X, ... = strconv.Atoi(...)
...
uint64($X)
- pattern: |
$X, ... = strconv.ParseInt(..., ..., 64)
...
uint64($X)
- pattern: |
$X, ... = strconv.ParseUint(..., ..., 64)
...
int64($X)
- patterns:
- metavariable-pattern:
metavariable: $CAST_METHOD
pattern-either:
- pattern: uint8
- pattern: uint16
- pattern: int8
- pattern: int16
- pattern-either:
- pattern: |
$X, ... = strconv.ParseInt(..., ..., 32)
...
$CAST_METHOD($X)
- pattern: |
$X, ... = strconv.ParseUint(..., ..., 32)
...
$CAST_METHOD($X)
- pattern: |
$X, ... = strconv.ParseInt(..., ..., 32)
...
uint32($X)
- pattern: |
$X, ... = strconv.ParseUint(..., ..., 32)
...
int32($X)
- patterns:
- metavariable-pattern:
metavariable: $CAST_METHOD
pattern-either:
- pattern: uint8
- pattern: int8
- pattern-either:
- pattern: |
$X, ... = strconv.ParseInt(..., ..., 16)
...
$CAST_METHOD($X)
- pattern: |
$X, ... = strconv.ParseUint(..., ..., 16)
...
$CAST_METHOD($X)
- pattern: |
$X, ... = strconv.ParseInt(..., ..., 16)
...
uint16($X)
- pattern: |
$X, ... = strconv.ParseUint(..., ..., 16)
...
int16($X)
- pattern: |
$X, ... = strconv.ParseInt(..., ..., 8)
...
uint8($X)
- pattern: |
$X, ... = strconv.ParseUint(..., ..., 8)
...
int8($X)
Examples
string-to-int-signedness-cast.go
package main
import (
"fmt"
"strconv"
)
const BigNum1 = "-4394967295"
const BigNum2 = "4294967294"
const BigNum3 = "-32766"
const BigNum4 = "18446744073709551615"
const BigNum5 = "253"
func main(){
conv_atoi1(BigNum1)
conv_atoi2(BigNum1)
conv_atoi3(BigNum1)
conv_atoi4(BigNum1)
conv_atoi5(BigNum1)
conv_atoi6(BigNum1)
conv_atoi7(BigNum1)
conv_atoi8(BigNum1)
conv_parse_int1(BigNum1)
conv_parse_int2(BigNum1)
conv_parse_int3(BigNum1)
conv_parse_int4(BigNum1)
conv_parse_int5(BigNum1)
conv_parse_int6(BigNum1)
conv_parse_int7(BigNum1)
conv_parse_int8(BigNum1)
conv_parse_uint1(BigNum4)
conv_parse_uint2(BigNum4)
conv_parse_uint3(BigNum4)
conv_parse_uint4(BigNum4)
conv_parse_uint5(BigNum4)
conv_parse_uint6(BigNum4)
conv_parse_uint7(BigNum4)
conv_parse_uint8(BigNum4)
conv32_parse_uint(BigNum2)
conv16_parse_int(BigNum3)
conv8_parse_uint8(BigNum5)
}
/* ATOI */
func conv_atoi1(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.Atoi(numStr)
if err != nil {
return
}
num := uint8(res)
fmt.Println("conv_atoi1 result: ", numStr, "->", num)
}
func conv_atoi2(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.Atoi(numStr)
if err != nil {
return
}
num := uint16(res)
fmt.Println("conv_atoi2 result: ", numStr, "->", num)
}
func conv_atoi3(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.Atoi(numStr)
if err != nil {
return
}
num := uint32(res)
fmt.Println("conv_atoi3 result: ", numStr, "->", num)
}
func conv_atoi4(numStr string){
// it is ok on 32-bit systems
// todook: string-to-int-signedness-cast
// ruleid: string-to-int-signedness-cast
res, err := strconv.Atoi(numStr)
if err != nil {
return
}
num := uint64(res)
fmt.Println("conv_atoi4 result: ", numStr, "->", num)
}
func conv_atoi5(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.Atoi(numStr)
if err != nil {
return
}
num := int8(res)
fmt.Println("conv_atoi5 result: ", numStr, "->", num)
}
func conv_atoi6(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.Atoi(numStr)
if err != nil {
return
}
num := int16(res)
fmt.Println("conv_atoi6 result: ", numStr, "->", num)
}
func conv_atoi7(numStr string){
// it is ok on 32-bit systems
// todook: string-to-int-signedness-cast
// ruleid: string-to-int-signedness-cast
res, err := strconv.Atoi(numStr)
if err != nil {
return
}
num := int32(res)
fmt.Println("conv_atoi7 result: ", numStr, "->", num)
}
func conv_atoi8(numStr string){
// it is not ok on 32-bit systems
// todoruleid: string-to-int-signedness-cast
// ok: string-to-int-signedness-cast
res, err := strconv.Atoi(numStr)
if err != nil {
return
}
num := int64(res)
fmt.Println("conv_atoi8 result: ", numStr, "->", num)
}
/* PARSE_INT */
func conv_parse_int1(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.ParseInt(numStr, 0, 64)
if err != nil {
return
}
num := uint8(res)
fmt.Println("conv_parse_int1 result: ", numStr, "->", num)
}
func conv_parse_int2(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.ParseInt(numStr, 0, 64)
if err != nil {
return
}
num := uint16(res)
fmt.Println("conv_parse_int2 result: ", numStr, "->", num)
}
func conv_parse_int3(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.ParseInt(numStr, 0, 64)
if err != nil {
return
}
num := uint32(res)
fmt.Println("conv_parse_int3 result: ", numStr, "->", num)
}
func conv_parse_int4(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.ParseInt(numStr, 0, 64)
if err != nil {
return
}
num := uint64(res)
fmt.Println("conv_parse_int4 result: ", numStr, "->", num)
}
func conv_parse_int5(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.ParseInt(numStr, 0, 64)
if err != nil {
return
}
num := int8(res)
fmt.Println("conv_parse_int5 result: ", numStr, "->", num)
}
func conv_parse_int6(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.ParseInt(numStr, 0, 64)
if err != nil {
return
}
num := int16(res)
fmt.Println("conv_parse_int6 result: ", numStr, "->", num)
}
func conv_parse_int7(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.ParseInt(numStr, 0, 64)
if err != nil {
return
}
num := int32(res)
fmt.Println("conv_parse_int7 result: ", numStr, "->", num)
}
func conv_parse_int8(numStr string){
// ok: string-to-int-signedness-cast
res, err := strconv.ParseInt(numStr, 0, 64)
if err != nil {
return
}
num := int64(res)
fmt.Println("conv_parse_int8 result: ", numStr, "->", num)
}
/* PARSE_UINT */
func conv_parse_uint1(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.ParseUint(numStr, 0, 64)
if err != nil {
return
}
num := uint8(res)
fmt.Println("conv_parse_uint1 result: ", numStr, "->", num)
}
func conv_parse_uint2(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.ParseUint(numStr, 0, 64)
if err != nil {
return
}
num := uint16(res)
fmt.Println("conv_parse_uint2 result: ", numStr, "->", num)
}
func conv_parse_uint3(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.ParseUint(numStr, 0, 64)
if err != nil {
return
}
num := uint32(res)
fmt.Println("conv_parse_uint3 result: ", numStr, "->", num)
}
func conv_parse_uint4(numStr string){
// ok: string-to-int-signedness-cast
res, err := strconv.ParseUint(numStr, 0, 64)
if err != nil {
return
}
num := uint64(res)
fmt.Println("conv_parse_uint4 result: ", numStr, "->", num)
}
func conv_parse_uint5(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.ParseUint(numStr, 0, 64)
if err != nil {
return
}
num := int8(res)
fmt.Println("conv_parse_uint5 result: ", numStr, "->", num)
}
func conv_parse_uint6(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.ParseUint(numStr, 0, 64)
if err != nil {
return
}
num := int16(res)
fmt.Println("conv_parse_uint6 result: ", numStr, "->", num)
}
func conv_parse_uint7(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.ParseUint(numStr, 0, 64)
if err != nil {
return
}
num := int32(res)
fmt.Println("conv_parse_uint7 result: ", numStr, "->", num)
}
func conv_parse_uint8(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.ParseUint(numStr, 0, 64)
if err != nil {
return
}
num := int64(res)
fmt.Println("conv_parse_uint8 result: ", numStr, "->", num)
}
/* 32 bits*/
func conv32_parse_uint(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.ParseUint(numStr, 0, 32)
if err != nil {
return
}
num := int32(res)
fmt.Println("conv32_parse_uint result: ", numStr, "->", num)
}
/* 16 bits*/
func conv16_parse_int(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.ParseInt(numStr, 0, 16)
if err != nil {
return
}
num := uint16(res)
fmt.Println("conv16_parse_int result: ", numStr, "->", num)
}
/* 8 bits*/
func conv8_parse_uint8(numStr string){
// ruleid: string-to-int-signedness-cast
res, err := strconv.ParseUint(numStr, 0, 8)
if err != nil {
return
}
num := int8(res)
fmt.Println("conv8_parse_uint8 result: ", numStr, "->", num)
}
Short Link: https://sg.run/65WB