chore(internal): Handle ranges in type-conversion and add missing types (#14618)

This commit is contained in:
Sven Rebhan 2024-01-24 14:47:51 +01:00 committed by GitHub
parent 29f7d04172
commit a3bea89509
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 659 additions and 134 deletions

View File

@ -2,9 +2,655 @@ package internal
import (
"fmt"
"math"
"strconv"
)
var ErrOutOfRange = strconv.ErrRange
func ToFloat64(value interface{}) (float64, error) {
switch v := value.(type) {
case string:
return strconv.ParseFloat(v, 64)
case []byte:
return strconv.ParseFloat(string(v), 64)
case fmt.Stringer:
return strconv.ParseFloat(v.String(), 64)
case bool:
if v {
return 1, nil
}
return 0, nil
case int:
return float64(v), nil
case int8:
return float64(v), nil
case int16:
return float64(v), nil
case int32:
return float64(v), nil
case int64:
return float64(v), nil
case uint:
return float64(v), nil
case uint8:
return float64(v), nil
case uint16:
return float64(v), nil
case uint32:
return float64(v), nil
case uint64:
return float64(v), nil
case float32:
return float64(v), nil
case float64:
return v, nil
case nil:
return 0, nil
}
return 0, fmt.Errorf("type \"%T\" unsupported", value)
}
func ToFloat32(value interface{}) (float32, error) {
switch v := value.(type) {
case string:
x, err := strconv.ParseFloat(v, 32)
return float32(x), err
case []byte:
x, err := strconv.ParseFloat(string(v), 32)
return float32(x), err
case fmt.Stringer:
x, err := strconv.ParseFloat(v.String(), 32)
return float32(x), err
case bool:
if v {
return 1, nil
}
return 0, nil
case int:
return float32(v), nil
case int8:
return float32(v), nil
case int16:
return float32(v), nil
case int32:
return float32(v), nil
case int64:
return float32(v), nil
case uint:
return float32(v), nil
case uint8:
return float32(v), nil
case uint16:
return float32(v), nil
case uint32:
return float32(v), nil
case uint64:
return float32(v), nil
case float32:
return v, nil
case float64:
if v < -math.MaxFloat32 || v > math.MaxFloat32 {
return float32(v), ErrOutOfRange
}
return float32(v), nil
case nil:
return 0, nil
}
return 0, fmt.Errorf("type \"%T\" unsupported", value)
}
func ToUint64(value interface{}) (uint64, error) {
switch v := value.(type) {
case string:
return strconv.ParseUint(v, 10, 64)
case []byte:
return strconv.ParseUint(string(v), 10, 64)
case fmt.Stringer:
return strconv.ParseUint(v.String(), 10, 64)
case bool:
if v {
return 1, nil
}
return 0, nil
case int:
if v < 0 {
return uint64(v), ErrOutOfRange
}
return uint64(v), nil
case int8:
if v < 0 {
return uint64(v), ErrOutOfRange
}
return uint64(v), nil
case int16:
if v < 0 {
return uint64(v), ErrOutOfRange
}
return uint64(v), nil
case int32:
if v < 0 {
return uint64(v), ErrOutOfRange
}
return uint64(v), nil
case int64:
if v < 0 {
return uint64(v), ErrOutOfRange
}
return uint64(v), nil
case uint:
return uint64(v), nil
case uint8:
return uint64(v), nil
case uint16:
return uint64(v), nil
case uint32:
return uint64(v), nil
case uint64:
return v, nil
case float32:
if v < 0 || v > math.MaxUint64 {
return uint64(v), ErrOutOfRange
}
return uint64(v), nil
case float64:
if v < 0 || v > math.MaxUint64 {
return uint64(v), ErrOutOfRange
}
return uint64(v), nil
case nil:
return 0, nil
}
return 0, fmt.Errorf("type \"%T\" unsupported", value)
}
func ToUint32(value interface{}) (uint32, error) {
switch v := value.(type) {
case string:
x, err := strconv.ParseUint(v, 10, 32)
return uint32(x), err
case []byte:
x, err := strconv.ParseUint(string(v), 10, 32)
return uint32(x), err
case fmt.Stringer:
x, err := strconv.ParseUint(v.String(), 10, 32)
return uint32(x), err
case bool:
if v {
return 1, nil
}
return 0, nil
case int:
if v < 0 || uint64(v) > math.MaxUint32 {
return uint32(v), ErrOutOfRange
}
return uint32(v), nil
case int8:
if v < 0 {
return uint32(v), ErrOutOfRange
}
return uint32(v), nil
case int16:
if v < 0 {
return uint32(v), ErrOutOfRange
}
return uint32(v), nil
case int32:
if v < 0 {
return uint32(v), ErrOutOfRange
}
return uint32(v), nil
case int64:
if v < 0 || v > math.MaxUint32 {
return uint32(v), ErrOutOfRange
}
return uint32(v), nil
case uint:
return uint32(v), nil
case uint8:
return uint32(v), nil
case uint16:
return uint32(v), nil
case uint32:
return v, nil
case uint64:
if v > math.MaxUint32 {
return uint32(v), ErrOutOfRange
}
return uint32(v), nil
case float32:
if v < 0 || v > math.MaxUint32 {
return uint32(v), ErrOutOfRange
}
return uint32(v), nil
case float64:
if v < 0 || v > math.MaxUint32 {
return uint32(v), ErrOutOfRange
}
return uint32(v), nil
case nil:
return 0, nil
}
return 0, fmt.Errorf("type \"%T\" unsupported", value)
}
func ToUint16(value interface{}) (uint16, error) {
switch v := value.(type) {
case string:
x, err := strconv.ParseUint(v, 10, 32)
return uint16(x), err
case []byte:
x, err := strconv.ParseUint(string(v), 10, 32)
return uint16(x), err
case fmt.Stringer:
x, err := strconv.ParseUint(v.String(), 10, 32)
return uint16(x), err
case bool:
if v {
return 1, nil
}
return 0, nil
case int:
if v < 0 || v > math.MaxUint16 {
return uint16(v), ErrOutOfRange
}
return uint16(v), nil
case int8:
if v < 0 {
return uint16(v), ErrOutOfRange
}
return uint16(v), nil
case int16:
if v < 0 {
return uint16(v), ErrOutOfRange
}
return uint16(v), nil
case int32:
if v < 0 || v > math.MaxUint16 {
return uint16(v), ErrOutOfRange
}
return uint16(v), nil
case int64:
if v < 0 || v > math.MaxUint16 {
return uint16(v), ErrOutOfRange
}
return uint16(v), nil
case uint:
return uint16(v), nil
case uint8:
return uint16(v), nil
case uint16:
return v, nil
case uint32:
if v > math.MaxUint16 {
return uint16(v), ErrOutOfRange
}
return uint16(v), nil
case uint64:
if v > math.MaxUint16 {
return uint16(v), ErrOutOfRange
}
return uint16(v), nil
case float32:
if v < 0 || v > math.MaxUint16 {
return uint16(v), ErrOutOfRange
}
return uint16(v), nil
case float64:
if v < 0 || v > math.MaxUint16 {
return uint16(v), ErrOutOfRange
}
return uint16(v), nil
case nil:
return 0, nil
}
return 0, fmt.Errorf("type \"%T\" unsupported", value)
}
func ToUint8(value interface{}) (uint8, error) {
switch v := value.(type) {
case string:
x, err := strconv.ParseUint(v, 10, 32)
return uint8(x), err
case []byte:
x, err := strconv.ParseUint(string(v), 10, 32)
return uint8(x), err
case fmt.Stringer:
x, err := strconv.ParseUint(v.String(), 10, 32)
return uint8(x), err
case bool:
if v {
return 1, nil
}
return 0, nil
case int:
if v < 0 || v > math.MaxUint8 {
return uint8(v), ErrOutOfRange
}
return uint8(v), nil
case int8:
if v < 0 {
return uint8(v), ErrOutOfRange
}
return uint8(v), nil
case int16:
if v < 0 || v > math.MaxUint8 {
return uint8(v), ErrOutOfRange
}
return uint8(v), nil
case int32:
if v < 0 || v > math.MaxUint8 {
return uint8(v), ErrOutOfRange
}
return uint8(v), nil
case int64:
if v < 0 || v > math.MaxUint8 {
return uint8(v), ErrOutOfRange
}
return uint8(v), nil
case uint:
return uint8(v), nil
case uint8:
return v, nil
case uint16:
if v > math.MaxUint8 {
return uint8(v), ErrOutOfRange
}
return uint8(v), nil
case uint32:
if v > math.MaxUint8 {
return uint8(v), ErrOutOfRange
}
return uint8(v), nil
case uint64:
if v > math.MaxUint8 {
return uint8(v), ErrOutOfRange
}
return uint8(v), nil
case float32:
if v < 0 || v > math.MaxUint8 {
return uint8(v), ErrOutOfRange
}
return uint8(v), nil
case float64:
if v < 0 || v > math.MaxUint8 {
return uint8(v), ErrOutOfRange
}
return uint8(v), nil
case nil:
return 0, nil
}
return 0, fmt.Errorf("type \"%T\" unsupported", value)
}
func ToInt64(value interface{}) (int64, error) {
switch v := value.(type) {
case string:
return strconv.ParseInt(v, 10, 64)
case []byte:
return strconv.ParseInt(string(v), 10, 64)
case fmt.Stringer:
return strconv.ParseInt(v.String(), 10, 64)
case bool:
if v {
return 1, nil
}
return 0, nil
case int:
return int64(v), nil
case int8:
return int64(v), nil
case int16:
return int64(v), nil
case int32:
return int64(v), nil
case int64:
return v, nil
case uint:
if uint64(v) > math.MaxInt64 {
return int64(v), ErrOutOfRange
}
return int64(v), nil
case uint8:
return int64(v), nil
case uint16:
return int64(v), nil
case uint32:
return int64(v), nil
case uint64:
if v > math.MaxInt64 {
return int64(v), ErrOutOfRange
}
return int64(v), nil
case float32:
if v < math.MinInt64 || v > math.MaxInt64 {
return int64(v), ErrOutOfRange
}
return int64(v), nil
case float64:
if v < math.MinInt64 || v > math.MaxInt64 {
return int64(v), ErrOutOfRange
}
return int64(v), nil
case nil:
return 0, nil
}
return 0, fmt.Errorf("type \"%T\" unsupported", value)
}
func ToInt32(value interface{}) (int32, error) {
switch v := value.(type) {
case string:
x, err := strconv.ParseInt(v, 10, 32)
return int32(x), err
case []byte:
x, err := strconv.ParseInt(string(v), 10, 32)
return int32(x), err
case fmt.Stringer:
x, err := strconv.ParseInt(v.String(), 10, 32)
return int32(x), err
case bool:
if v {
return 1, nil
}
return 0, nil
case int:
if int64(v) < math.MinInt32 || int64(v) > math.MaxInt32 {
return int32(v), ErrOutOfRange
}
return int32(v), nil
case int8:
return int32(v), nil
case int16:
return int32(v), nil
case int32:
return v, nil
case int64:
if v < math.MinInt32 || v > math.MaxInt32 {
return int32(v), ErrOutOfRange
}
return int32(v), nil
case uint:
if v > math.MaxInt32 {
return int32(v), ErrOutOfRange
}
return int32(v), nil
case uint8:
return int32(v), nil
case uint16:
return int32(v), nil
case uint32:
if v > math.MaxInt32 {
return int32(v), ErrOutOfRange
}
return int32(v), nil
case uint64:
if v > math.MaxInt32 {
return int32(v), ErrOutOfRange
}
return int32(v), nil
case float32:
if v < math.MinInt32 || v > math.MaxInt32 {
return int32(v), ErrOutOfRange
}
return int32(v), nil
case float64:
if v < math.MinInt32 || v > math.MaxInt32 {
return int32(v), ErrOutOfRange
}
return int32(v), nil
case nil:
return 0, nil
}
return 0, fmt.Errorf("type \"%T\" unsupported", value)
}
func ToInt16(value interface{}) (int16, error) {
switch v := value.(type) {
case string:
x, err := strconv.ParseInt(v, 10, 32)
return int16(x), err
case []byte:
x, err := strconv.ParseInt(string(v), 10, 32)
return int16(x), err
case fmt.Stringer:
x, err := strconv.ParseInt(v.String(), 10, 32)
return int16(x), err
case bool:
if v {
return 1, nil
}
return 0, nil
case int:
return int16(v), nil
case int8:
return int16(v), nil
case int16:
return v, nil
case int32:
if v < math.MinInt16 || v > math.MaxInt16 {
return int16(v), ErrOutOfRange
}
return int16(v), nil
case int64:
if v < math.MinInt16 || v > math.MaxInt16 {
return int16(v), ErrOutOfRange
}
return int16(v), nil
case uint:
if v > math.MaxInt16 {
return int16(v), ErrOutOfRange
}
return int16(v), nil
case uint8:
return int16(v), nil
case uint16:
if v > math.MaxInt16 {
return int16(v), ErrOutOfRange
}
return int16(v), nil
case uint32:
if v > math.MaxInt16 {
return int16(v), ErrOutOfRange
}
return int16(v), nil
case uint64:
if v > math.MaxInt16 {
return int16(v), ErrOutOfRange
}
return int16(v), nil
case float32:
if v < math.MinInt16 || v > math.MaxInt16 {
return int16(v), ErrOutOfRange
}
return int16(v), nil
case float64:
if v < math.MinInt16 || v > math.MaxInt16 {
return int16(v), ErrOutOfRange
}
return int16(v), nil
case nil:
return 0, nil
}
return 0, fmt.Errorf("type \"%T\" unsupported", value)
}
func ToInt8(value interface{}) (int8, error) {
switch v := value.(type) {
case string:
x, err := strconv.ParseInt(v, 10, 32)
return int8(x), err
case []byte:
x, err := strconv.ParseInt(string(v), 10, 32)
return int8(x), err
case fmt.Stringer:
x, err := strconv.ParseInt(v.String(), 10, 32)
return int8(x), err
case bool:
if v {
return 1, nil
}
return 0, nil
case int:
return int8(v), nil
case int8:
return v, nil
case int16:
if v < math.MinInt8 || v > math.MaxInt8 {
return int8(v), ErrOutOfRange
}
return int8(v), nil
case int32:
if v < math.MinInt8 || v > math.MaxInt8 {
return int8(v), ErrOutOfRange
}
return int8(v), nil
case int64:
if v < math.MinInt8 || v > math.MaxInt8 {
return int8(v), ErrOutOfRange
}
return int8(v), nil
case uint:
if v > math.MaxInt8 {
return int8(v), ErrOutOfRange
}
return int8(v), nil
case uint8:
if v > math.MaxInt8 {
return int8(v), ErrOutOfRange
}
return int8(v), nil
case uint16:
if v > math.MaxInt8 {
return int8(v), ErrOutOfRange
}
return int8(v), nil
case uint32:
if v > math.MaxInt8 {
return int8(v), ErrOutOfRange
}
return int8(v), nil
case uint64:
if v > math.MaxInt8 {
return int8(v), ErrOutOfRange
}
return int8(v), nil
case float32:
if v < math.MinInt8 || v > math.MaxInt8 {
return int8(v), ErrOutOfRange
}
return int8(v), nil
case float64:
if v < math.MinInt8 || v > math.MaxInt8 {
return int8(v), ErrOutOfRange
}
return int8(v), nil
case nil:
return 0, nil
}
return 0, fmt.Errorf("type \"%T\" unsupported", value)
}
func ToString(value interface{}) (string, error) {
switch v := value.(type) {
case string:
@ -45,135 +691,6 @@ func ToString(value interface{}) (string, error) {
return "", fmt.Errorf("type \"%T\" unsupported", value)
}
func ToFloat64(value interface{}) (float64, error) {
switch v := value.(type) {
case string:
return strconv.ParseFloat(v, 64)
case []byte:
return strconv.ParseFloat(string(v), 64)
case fmt.Stringer:
return strconv.ParseFloat(v.String(), 64)
case bool:
if v {
return float64(1), nil
}
return float64(0), nil
case int:
return float64(v), nil
case int8:
return float64(v), nil
case int16:
return float64(v), nil
case int32:
return float64(v), nil
case int64:
return float64(v), nil
case uint:
return float64(v), nil
case uint8:
return float64(v), nil
case uint16:
return float64(v), nil
case uint32:
return float64(v), nil
case uint64:
return float64(v), nil
case float32:
return float64(v), nil
case float64:
return v, nil
case nil:
return 0, nil
}
return 0, fmt.Errorf("type \"%T\" unsupported", value)
}
func ToInt64(value interface{}) (int64, error) {
switch v := value.(type) {
case string:
return strconv.ParseInt(v, 10, 64)
case []byte:
return strconv.ParseInt(string(v), 10, 64)
case fmt.Stringer:
return strconv.ParseInt(v.String(), 10, 64)
case bool:
if v {
return int64(1), nil
}
return int64(0), nil
case int:
return int64(v), nil
case int8:
return int64(v), nil
case int16:
return int64(v), nil
case int32:
return int64(v), nil
case int64:
return v, nil
case uint:
return int64(v), nil
case uint8:
return int64(v), nil
case uint16:
return int64(v), nil
case uint32:
return int64(v), nil
case uint64:
return int64(v), nil
case float32:
return int64(v), nil
case float64:
return int64(v), nil
case nil:
return 0, nil
}
return 0, fmt.Errorf("type \"%T\" unsupported", value)
}
func ToUint64(value interface{}) (uint64, error) {
switch v := value.(type) {
case string:
return strconv.ParseUint(v, 10, 64)
case []byte:
return strconv.ParseUint(string(v), 10, 64)
case fmt.Stringer:
return strconv.ParseUint(v.String(), 10, 64)
case bool:
if v {
return uint64(1), nil
}
return uint64(0), nil
case int:
return uint64(v), nil
case int8:
return uint64(v), nil
case int16:
return uint64(v), nil
case int32:
return uint64(v), nil
case int64:
return uint64(v), nil
case uint:
return uint64(v), nil
case uint8:
return uint64(v), nil
case uint16:
return uint64(v), nil
case uint32:
return uint64(v), nil
case uint64:
return v, nil
case float32:
return uint64(v), nil
case float64:
return uint64(v), nil
case nil:
return 0, nil
}
return 0, fmt.Errorf("type \"%T\" unsupported", value)
}
func ToBool(value interface{}) (bool, error) {
switch v := value.(type) {
case string:

View File

@ -55,7 +55,7 @@ type Query struct {
fieldFilterString filter.Filter
}
func (q *Query) parse(acc telegraf.Accumulator, rows *dbsql.Rows, t time.Time) (int, error) {
func (q *Query) parse(acc telegraf.Accumulator, rows *dbsql.Rows, t time.Time, logger telegraf.Logger) (int, error) {
columnNames, err := rows.Columns()
if err != nil {
return 0, err
@ -140,8 +140,13 @@ func (q *Query) parse(acc telegraf.Accumulator, rows *dbsql.Rows, t time.Time) (
if q.fieldFilterInt.Match(name) {
v, err := internal.ToInt64(columnData[i])
if err != nil {
if err != nil {
if !errors.Is(err, internal.ErrOutOfRange) {
return 0, fmt.Errorf("converting field column %q to int failed: %w", name, err)
}
logger.Warnf("field column %q: %v", name, err)
}
}
fields[name] = v
continue
}
@ -149,8 +154,11 @@ func (q *Query) parse(acc telegraf.Accumulator, rows *dbsql.Rows, t time.Time) (
if q.fieldFilterUint.Match(name) {
v, err := internal.ToUint64(columnData[i])
if err != nil {
if !errors.Is(err, internal.ErrOutOfRange) {
return 0, fmt.Errorf("converting field column %q to uint failed: %w", name, err)
}
logger.Warnf("field column %q: %v", name, err)
}
fields[name] = v
continue
}
@ -526,7 +534,7 @@ func (s *SQL) executeQuery(ctx context.Context, acc telegraf.Accumulator, q Quer
if err != nil {
return err
}
rowCount, err := q.parse(acc, rows, tquery)
rowCount, err := q.parse(acc, rows, tquery, s.Log)
s.Log.Debugf("Received %d rows and %d columns for query %q", rowCount, len(columnNames), q.Query)
return err

View File

@ -305,7 +305,7 @@ func (s *Suricata) parseGeneric(acc telegraf.Accumulator, result map[string]inte
}
for _, key := range []string{"src_port", "dest_port"} {
if val, ok := result[key]; ok {
if convertedVal, err := internal.ToInt64(val); err == nil {
if convertedVal, err := internal.ToInt64(val); err == nil || errors.Is(err, internal.ErrOutOfRange) {
fields[key] = convertedVal
}
}