Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix convert processor conversion of string with leading zeros to integer #15557

Merged
merged 4 commits into from
Jan 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- Fix bug with potential concurrent reads and writes from event.Meta map by Kafka output. {issue}14542[14542] {pull}14568[14568]
- Fix spooling to disk blocking infinitely if the lock file can not be acquired. {pull}15338[15338]
- Fix `metricbeat test output` with an ipv6 ES host in the output.hosts. {pull}15368[15368]
- Fix `convert` processor conversion of string to integer with leading zeros. {issue}15513[15513] {pull}15557[15557]

*Auditbeat*

Expand Down
25 changes: 23 additions & 2 deletions libbeat/processors/convert/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ func toString(value interface{}) (string, error) {
func toLong(value interface{}) (int64, error) {
switch v := value.(type) {
case string:
return strconv.ParseInt(v, 0, 64)
return strToInt(v, 64)
case int:
return int64(v), nil
case int8:
Expand Down Expand Up @@ -238,7 +238,7 @@ func toLong(value interface{}) (int64, error) {
func toInteger(value interface{}) (int32, error) {
switch v := value.(type) {
case string:
i, err := strconv.ParseInt(v, 0, 32)
i, err := strToInt(v, 32)
return int32(i), err
case int:
return int32(v), nil
Expand Down Expand Up @@ -403,3 +403,24 @@ func cloneValue(value interface{}) interface{} {
return value
}
}

// strToInt is a helper to interpret a string as either base 10 or base 16.
func strToInt(s string, bitSize int) (int64, error) {
base := 10
if hasHexPrefix(s) {
// strconv.ParseInt will accept the '0x' or '0X` prefix only when base is 0.
base = 0
}
return strconv.ParseInt(s, base, bitSize)
}

func hasHexPrefix(s string) bool {
if len(s) < 3 {
return false
}
a, b := s[0], s[1]
if a == '+' || a == '-' {
a, b = b, s[2]
}
return a == '0' && (b == 'x' || b == 'X')
}
19 changes: 19 additions & 0 deletions libbeat/processors/convert/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,16 @@ var testCases = []testCase{

{Long, nil, nil, true},
{Long, "x", nil, true},
{Long, "0x", nil, true},
{Long, "0b1", nil, true},
{Long, "1x2", nil, true},
{Long, true, nil, true},
{Long, "1", int64(1), false},
{Long, "-1", int64(-1), false},
{Long, "017", int64(17), false},
{Long, "08", int64(8), false},
{Long, "0X0A", int64(10), false},
{Long, "-0x12", int64(-18), false},
{Long, int(1), int64(1), false},
{Long, int8(1), int64(1), false},
{Long, int16(1), int64(1), false},
Expand All @@ -294,6 +302,17 @@ var testCases = []testCase{
{Integer, nil, nil, true},
{Integer, "x", nil, true},
{Integer, true, nil, true},
{Integer, "x", nil, true},
{Integer, "0x", nil, true},
{Integer, "0b1", nil, true},
{Integer, "1x2", nil, true},
{Integer, true, nil, true},
{Integer, "1", int32(1), false},
{Integer, "-1", int32(-1), false},
{Integer, "017", int32(17), false},
{Integer, "08", int32(8), false},
{Integer, "0X0A", int32(10), false},
{Integer, "-0x12", int32(-18), false},
{Integer, "1", int32(1), false},
{Integer, int(1), int32(1), false},
{Integer, int8(1), int32(1), false},
Expand Down