-
Notifications
You must be signed in to change notification settings - Fork 136
OCPBUGS-6958: Fix clipHAProxyTimeoutValue #483
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
Changes from all commits
bfa3b28
cf596f8
d434ca6
01038ad
e52afb2
d56f627
267fb6c
6f75c35
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -12,6 +12,7 @@ import ( | |||||||||||||
| "testing" | ||||||||||||||
|
|
||||||||||||||
| routev1 "github.com/openshift/api/route/v1" | ||||||||||||||
| templateutil "github.com/openshift/router/pkg/router/template/util" | ||||||||||||||
| ) | ||||||||||||||
|
|
||||||||||||||
| func buildServiceAliasConfig(name, namespace, host, path string, termination routev1.TLSTerminationType, policy routev1.InsecureEdgeTerminationPolicyType, wildcard bool) ServiceAliasConfig { | ||||||||||||||
|
|
@@ -790,6 +791,56 @@ func TestClipHAProxyTimeoutValue(t *testing.T) { | |||||||||||||
| value: "", | ||||||||||||||
| expected: "", | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "s", | ||||||||||||||
| expected: "", | ||||||||||||||
| // Invalid input produces blank output. | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "0", | ||||||||||||||
| expected: "", | ||||||||||||||
| // Invalid input produces blank output. | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "01s", | ||||||||||||||
| expected: "", | ||||||||||||||
| // Invalid input produces blank output. | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "1.5.8.9", | ||||||||||||||
| expected: "", | ||||||||||||||
| // Invalid input produces blank output. | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "1.5s", | ||||||||||||||
| expected: "", | ||||||||||||||
| // Invalid input produces blank output. | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "+-+", | ||||||||||||||
| expected: "", | ||||||||||||||
| // Invalid input produces blank output. | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "24d1", | ||||||||||||||
| expected: "", | ||||||||||||||
| // Invalid input produces blank output. | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "1d12h", | ||||||||||||||
| expected: "", | ||||||||||||||
| // Invalid input produces blank output. | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "foo", | ||||||||||||||
| expected: "", | ||||||||||||||
| // Invalid input produces blank output. | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "2562047.99h", | ||||||||||||||
| expected: "", | ||||||||||||||
| // Invalid input produces blank output. | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "10", | ||||||||||||||
| expected: "10", | ||||||||||||||
|
|
@@ -802,13 +853,58 @@ func TestClipHAProxyTimeoutValue(t *testing.T) { | |||||||||||||
| value: "10d", | ||||||||||||||
| expected: "10d", | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "24d", | ||||||||||||||
| expected: "24d", | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "2147483647ms", | ||||||||||||||
| expected: "2147483647ms", | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "100d", | ||||||||||||||
| expected: haproxyMaxTimeout, | ||||||||||||||
| expected: templateutil.HaproxyMaxTimeout, | ||||||||||||||
| // Exceeds the HAProxy maximum. | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "1000h", | ||||||||||||||
| expected: haproxyMaxTimeout, | ||||||||||||||
| expected: templateutil.HaproxyMaxTimeout, | ||||||||||||||
| // Exceeds the HAProxy maximum. | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "2147483648", | ||||||||||||||
| expected: templateutil.HaproxyMaxTimeout, | ||||||||||||||
| // Exceeds the HAProxy maximum and has no unit. | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "9223372036855ms", | ||||||||||||||
| expected: templateutil.HaproxyMaxTimeout, | ||||||||||||||
| // Exceeds the haproxytime.ParseDuration maximum. | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "9223372036854776us", | ||||||||||||||
| expected: templateutil.HaproxyMaxTimeout, | ||||||||||||||
| // Exceeds the haproxytime.ParseDuration maximum. | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "100000000000s", | ||||||||||||||
| expected: templateutil.HaproxyMaxTimeout, | ||||||||||||||
| // Exceeds the haproxytime.ParseDuration maximum. | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "922337203685477581ms", | ||||||||||||||
| expected: templateutil.HaproxyMaxTimeout, | ||||||||||||||
| // Exceeds the haproxytime.ParseDuration maximum. | ||||||||||||||
| }, | ||||||||||||||
| { | ||||||||||||||
| value: "9223372036854775807", | ||||||||||||||
| expected: templateutil.HaproxyMaxTimeout, | ||||||||||||||
| // Exceeds the int64 maximum and has no unit. | ||||||||||||||
| }, | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These additional test will test the boundary for {
value: "9223372036854775807", // max int64
expected: "2147483647ms",
},
{
value: "9223372036854775808", // overflow int64
expected: "2147483647ms",
},
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even this smaller value overflows. I'm not finding any number that triggers the overflow errors in
Suggested change
|
||||||||||||||
| { | ||||||||||||||
| value: "9999999999999999", | ||||||||||||||
| expected: templateutil.HaproxyMaxTimeout, | ||||||||||||||
| // Exceeds the haproxytime.ParseDuration maximum and has no unit. | ||||||||||||||
| }, | ||||||||||||||
| } | ||||||||||||||
| for _, tc := range testCases { | ||||||||||||||
|
|
||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,107 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package haproxytime | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "errors" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "math" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "regexp" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "strconv" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "time" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // OverflowError represents an overflow error from ParseDuration. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // OverflowError is returned if the input value is greater than what ParseDuration | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // allows (value must be representable as int64, e.g. 9223372036854775807 nanoseconds). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| OverflowError = errors.New("overflow") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // SyntaxError represents an error based on invalid input to ParseDuration. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SyntaxError = errors.New("invalid duration") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // durationRE regexp should match the one in $timeSpecPattern in the haproxy-config.template, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // except that we use ^$ anchors and a capture group around the numeric part to simplify the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // duration parsing. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| durationRE = regexp.MustCompile(`^([1-9][0-9]*)(us|ms|s|m|h|d)?$`) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // ParseDuration takes a string representing a duration in HAProxy's | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // specific format and converts it into a time.Duration value. The | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // string can include an optional unit suffix, such as "us", "ms", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // "s", "m", "h", or "d". If no suffix is provided, milliseconds are | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // assumed. The function returns OverflowError if the value exceeds | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // the maximum allowable input, or SyntaxError if the input string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // doesn't match the expected format. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func ParseDuration(input string) (time.Duration, error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| matches := durationRE.FindStringSubmatch(input) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if matches == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 0, SyntaxError | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Unit is milliseconds when left unspecified. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| unit := time.Millisecond | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| numericPart := matches[1] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| unitPart := "" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if len(matches) > 2 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| unitPart = matches[2] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| switch unitPart { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "us": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| unit = time.Microsecond | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "ms": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| unit = time.Millisecond | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "s": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| unit = time.Second | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "m": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| unit = time.Minute | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "h": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| unit = time.Hour | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "d": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| unit = 24 * time.Hour | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value, err := strconv.ParseInt(numericPart, 10, 64) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // ParseInt is documented to return only ErrSyntax or | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // ErrRange when an error occurs. As we've already | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // covered the ErrSyntax case with the regex, we can | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // assume this is ErrRange. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 0, OverflowError | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Check for overflow conditions before multiplying 'value' by 'unit'. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 'value' is guaranteed to be >= 0, as ensured by the preceding regular expression. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // The maximum allowable 'value' is determined by dividing math.MaxInt64 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // by the nanosecond representation of 'unit'. This prevents overflow when | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 'value' is later multiplied by 'unit'. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Examples: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 1. If the 'unit' is time.Second (1e9 ns), then the maximum | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 'value' allowed is math.MaxInt64 / 1e9. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 2. If the 'unit' is 24 * time.Hour (86400e9 ns), then the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // maximum 'value' allowed is math.MaxInt64 / 86400e9. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 3. If the 'unit' is time.Microsecond (1e3 ns), then the maximum | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 'value' allowed is math.MaxInt64 / 1e3. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Concrete examples with actual values: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // - No Overflow (days): "106751d" as input makes 'unit' 24 * time.Hour (86400e9 ns). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // The check ensures 106751 <= math.MaxInt64 / 86400e9. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Specifically, 106751 <= 9223372036854775807 / 86400000000 (106751 <= 106751). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // This is the maximum 'value' for days that won't cause an overflow. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // - Overflow (days): Specifying "106752d" makes 'unit' 24 * time.Hour (86400e9 ns). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // The check finds 106752 > math.MaxInt64 / 86400e9. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Specifically, 106752 > 9223372036854775807 / 86400000000 (106752 > 106751), causing an overflow. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // - No Overflow (us): "9223372036854775us" makes 'unit' time.Microsecond (1e3 ns). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // The check ensures 9223372036854775 <= math.MaxInt64 / 1e3. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Specifically, 9223372036854775 <= 9223372036854775807 / 1000 (9223372036854775 <= 9223372036854775). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // This is the maximum 'value' for microseconds that won't cause an overflow. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if value > math.MaxInt64/int64(unit) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 0, OverflowError | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+101
to
+103
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| duration := time.Duration(value) * unit | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return duration, nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specifically test for the HAProxy maximum.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok