-
Notifications
You must be signed in to change notification settings - Fork 2.4k
mysql/replication: bound the intervals preallocation in ParseMysql56GTIDSet #20932
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
base: main
Are you sure you want to change the base?
Changes from 1 commit
0307181
bcec182
9c3935d
def9237
afb24d4
e7f8f5e
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 |
|---|---|---|
|
|
@@ -91,7 +91,20 @@ func ParseMysql56GTIDSet(s string) (Mysql56GTIDSet, error) { | |
| return nil, vterrors.Wrapf(err, "invalid MySQL 5.6 GTID set (%q)", s) | ||
| } | ||
|
|
||
| intervals := make([]interval, 0, strings.Count(tail, ":")+1) | ||
| // The capacity is only a hint to append, so bounding it cannot change the | ||
| // parsed result. It is bounded because the hint is derived from untrusted | ||
| // input: a valid SID followed by a long run of colons would otherwise | ||
| // reserve one interval per colon before any interval is parsed, and | ||
| // parseInterval below rejects the very first one. | ||
| // | ||
| // The bound is a fraction of the remaining input rather than a constant, so | ||
| // a genuinely long interval list still gets a useful hint: the shortest | ||
| // possible interval is "N-M:" so the count cannot exceed len(tail)/4. | ||
| nIntervals := strings.Count(tail, ":") + 1 | ||
| if max := len(tail)/4 + 1; nIntervals > max { | ||
| nIntervals = max | ||
|
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.
For accepted sets containing many bare intervals, such as Useful? React with 👍 / 👎. |
||
| } | ||
|
Comment on lines
+100
to
+114
|
||
| intervals := make([]interval, 0, nIntervals) | ||
| for len(tail) > 0 { | ||
| if idx := strings.IndexByte(tail, ':'); idx >= 0 { | ||
| head = tail[:idx] | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,6 +17,7 @@ limitations under the License. | |
| package replication | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "maps" | ||
| "reflect" | ||
| "strings" | ||
|
|
@@ -902,3 +903,32 @@ func TestSIDs(t *testing.T) { | |
| require.Len(t, sids, 1) | ||
| assert.Equal(t, "8bc65cca-3fe4-11ed-bbfb-091034d48b3e", sids[0].String()) | ||
| } | ||
|
|
||
| // TestParseMysql56GTIDSetIntervalsCapHint checks that bounding the preallocation | ||
| // hint for the intervals slice does not change what is parsed. The capacity is only | ||
| // a hint to append, so results must be identical either side of the bound. | ||
| func TestParseMysql56GTIDSetIntervalsCapHint(t *testing.T) { | ||
| const sid = "00010203-0405-0607-0809-0a0b0c0d0e0f" | ||
| for _, n := range []int{1, 10, 100, 1023, 1024, 1025, 2051, 5000} { | ||
| var sb strings.Builder | ||
| sb.WriteString(sid) | ||
| for i := 0; i < n; i++ { | ||
| // non-overlapping ascending intervals, so none are merged or discarded | ||
| fmt.Fprintf(&sb, ":%d-%d", 2*i+1, 2*i+1) | ||
| } | ||
| got, err := ParseMysql56GTIDSet(sb.String()) | ||
| require.NoError(t, err, "n=%d", n) | ||
| sidVal, err := ParseSID(sid) | ||
| require.NoError(t, err) | ||
| assert.Len(t, got[sidVal], n, "n=%d", n) | ||
|
Comment on lines
+924
to
+928
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.
This test passes unchanged against the parent implementation and therefore cannot guard the allocation fix: every generated AGENTS.md reference: AGENTS.md:L79-L80 Useful? React with 👍 / 👎. |
||
| } | ||
| } | ||
|
|
||
| // TestParseMysql56GTIDSetColonRun checks that an interval list made only of | ||
| // separators is still rejected: the bound must not turn invalid input into a | ||
| // silent success. | ||
| func TestParseMysql56GTIDSetColonRun(t *testing.T) { | ||
| s := "00010203-0405-0607-0809-0a0b0c0d0e0f:" + strings.Repeat(":", 64) | ||
| _, err := ParseMysql56GTIDSet(s) | ||
| assert.Error(t, err) | ||
| } | ||
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.
Unless the originating task explicitly requested source-level commentary, this newly added multi-paragraph rationale violates the repository’s strict instruction not to add explanatory comments; the machine- and implementation-specific allocation measurements also risk becoming stale while duplicating PR/commit context. Keep the implementation focused and move this narrative out of the source.
AGENTS.md reference: AGENTS.md:L20-L27
Useful? React with 👍 / 👎.