1
0
Fork 0
mirror of https://github.com/Luzifer/rconfig.git synced 2024-12-21 03:31:19 +00:00

Fix: Ensure int/uint do not overflow

by utilizing correct parsing for the requested type in strconv

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2024-08-27 15:47:47 +02:00
parent 6f0f872a04
commit 80dd107159
Signed by: luzifer
SSH key fingerprint: SHA256:/xtE5lCgiRDQr8SLxHMS92ZBlACmATUmF1crK16Ks4E
2 changed files with 65 additions and 14 deletions

View file

@ -259,7 +259,7 @@ func execTags(in interface{}, fs *pflag.FlagSet) ([]afterFunc, error) {
} }
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
vt, err := strconv.ParseInt(value, 10, 64) vt, err := parseIntForType(value, 10, typeField.Type.Kind()) //nolint:mnd
if err != nil { if err != nil {
if value != "" { if value != "" {
return nil, fmt.Errorf("parsing int: %w", err) return nil, fmt.Errorf("parsing int: %w", err)
@ -273,7 +273,7 @@ func execTags(in interface{}, fs *pflag.FlagSet) ([]afterFunc, error) {
} }
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
vt, err := strconv.ParseUint(value, 10, 64) vt, err := parseUintForType(value, 10, typeField.Type.Kind()) //nolint:mnd
if err != nil { if err != nil {
if value != "" { if value != "" {
return nil, fmt.Errorf("parsing uint: %w", err) return nil, fmt.Errorf("parsing uint: %w", err)
@ -371,21 +371,21 @@ func registerFlagInt(t reflect.Kind, fs *pflag.FlagSet, field interface{}, parts
} }
case reflect.Int8: case reflect.Int8:
if len(parts) == 1 { if len(parts) == 1 {
fs.Int8Var(field.(*int8), parts[0], int8(vt), desc) fs.Int8Var(field.(*int8), parts[0], int8(vt), desc) //#nosec:G115 - Variable is guaranteed to match by strconv
} else { } else {
fs.Int8VarP(field.(*int8), parts[0], parts[1], int8(vt), desc) fs.Int8VarP(field.(*int8), parts[0], parts[1], int8(vt), desc) //#nosec:G115 - Variable is guaranteed to match by strconv
} }
case reflect.Int16: case reflect.Int16:
if len(parts) == 1 { if len(parts) == 1 {
fs.Int16Var(field.(*int16), parts[0], int16(vt), desc) fs.Int16Var(field.(*int16), parts[0], int16(vt), desc) //#nosec:G115 - Variable is guaranteed to match by strconv
} else { } else {
fs.Int16VarP(field.(*int16), parts[0], parts[1], int16(vt), desc) fs.Int16VarP(field.(*int16), parts[0], parts[1], int16(vt), desc) //#nosec:G115 - Variable is guaranteed to match by strconv
} }
case reflect.Int32: case reflect.Int32:
if len(parts) == 1 { if len(parts) == 1 {
fs.Int32Var(field.(*int32), parts[0], int32(vt), desc) fs.Int32Var(field.(*int32), parts[0], int32(vt), desc) //#nosec:G115 - Variable is guaranteed to match by strconv
} else { } else {
fs.Int32VarP(field.(*int32), parts[0], parts[1], int32(vt), desc) fs.Int32VarP(field.(*int32), parts[0], parts[1], int32(vt), desc) //#nosec:G115 - Variable is guaranteed to match by strconv
} }
case reflect.Int64: case reflect.Int64:
if len(parts) == 1 { if len(parts) == 1 {
@ -406,21 +406,21 @@ func registerFlagUint(t reflect.Kind, fs *pflag.FlagSet, field interface{}, part
} }
case reflect.Uint8: case reflect.Uint8:
if len(parts) == 1 { if len(parts) == 1 {
fs.Uint8Var(field.(*uint8), parts[0], uint8(vt), desc) fs.Uint8Var(field.(*uint8), parts[0], uint8(vt), desc) //#nosec:G115 - Variable is guaranteed to match by strconv
} else { } else {
fs.Uint8VarP(field.(*uint8), parts[0], parts[1], uint8(vt), desc) fs.Uint8VarP(field.(*uint8), parts[0], parts[1], uint8(vt), desc) //#nosec:G115 - Variable is guaranteed to match by strconv
} }
case reflect.Uint16: case reflect.Uint16:
if len(parts) == 1 { if len(parts) == 1 {
fs.Uint16Var(field.(*uint16), parts[0], uint16(vt), desc) fs.Uint16Var(field.(*uint16), parts[0], uint16(vt), desc) //#nosec:G115 - Variable is guaranteed to match by strconv
} else { } else {
fs.Uint16VarP(field.(*uint16), parts[0], parts[1], uint16(vt), desc) fs.Uint16VarP(field.(*uint16), parts[0], parts[1], uint16(vt), desc) //#nosec:G115 - Variable is guaranteed to match by strconv
} }
case reflect.Uint32: case reflect.Uint32:
if len(parts) == 1 { if len(parts) == 1 {
fs.Uint32Var(field.(*uint32), parts[0], uint32(vt), desc) fs.Uint32Var(field.(*uint32), parts[0], uint32(vt), desc) //#nosec:G115 - Variable is guaranteed to match by strconv
} else { } else {
fs.Uint32VarP(field.(*uint32), parts[0], parts[1], uint32(vt), desc) fs.Uint32VarP(field.(*uint32), parts[0], parts[1], uint32(vt), desc) //#nosec:G115 - Variable is guaranteed to match by strconv
} }
case reflect.Uint64: case reflect.Uint64:
if len(parts) == 1 { if len(parts) == 1 {

51
strconv.go Normal file
View file

@ -0,0 +1,51 @@
package rconfig
import (
"fmt"
"reflect"
"strconv"
)
func parseIntForType(s string, base int, fieldType reflect.Kind) (i int64, err error) {
switch fieldType {
case reflect.Int:
return strconv.ParseInt(s, base, strconv.IntSize) //nolint:wrapcheck
case reflect.Int8:
return strconv.ParseInt(s, base, 8) //nolint:wrapcheck
case reflect.Int16:
return strconv.ParseInt(s, base, 16) //nolint:wrapcheck
case reflect.Int32:
return strconv.ParseInt(s, base, 32) //nolint:wrapcheck
case reflect.Int64:
return strconv.ParseInt(s, base, 64) //nolint:wrapcheck
default:
return 0, fmt.Errorf("unsupported type: %v", fieldType)
}
}
func parseUintForType(s string, base int, fieldType reflect.Kind) (uint64, error) {
switch fieldType {
case reflect.Uint:
return strconv.ParseUint(s, base, strconv.IntSize) //nolint:wrapcheck
case reflect.Uint8:
return strconv.ParseUint(s, base, 8) //nolint:wrapcheck
case reflect.Uint16:
return strconv.ParseUint(s, base, 16) //nolint:wrapcheck
case reflect.Uint32:
return strconv.ParseUint(s, base, 32) //nolint:wrapcheck
case reflect.Uint64:
return strconv.ParseUint(s, base, 64) //nolint:wrapcheck
default:
return 0, fmt.Errorf("unsupported type: %v", fieldType)
}
}