-
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 2 commits
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 |
|---|---|---|
|
|
@@ -17,8 +17,10 @@ limitations under the License. | |
| package replication | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "maps" | ||
| "reflect" | ||
| "runtime" | ||
| "strings" | ||
| "testing" | ||
|
|
||
|
|
@@ -902,3 +904,40 @@ func TestSIDs(t *testing.T) { | |
| require.Len(t, sids, 1) | ||
| assert.Equal(t, "8bc65cca-3fe4-11ed-bbfb-091034d48b3e", sids[0].String()) | ||
| } | ||
|
|
||
| // TestParseMysql56GTIDSetIntervalsCapHint checks that the preallocation hint for | ||
| // the intervals slice does not follow a count taken from the input beyond what that | ||
| // input could hold, while a genuinely long interval list still parses unchanged. | ||
| // The hostile case asserts on allocation volume, because a colon run parses without | ||
| // error either way once the intervals are all discarded. | ||
| func TestParseMysql56GTIDSetIntervalsCapHint(t *testing.T) { | ||
| const sid = "00010203-0405-0607-0809-0a0b0c0d0e0f" | ||
|
|
||
| // Results must be identical either side of the bound. | ||
| 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) | ||
| } | ||
|
|
||
| // A long run of colons carries no intervals at all, so reserving one per colon | ||
| // is pure waste. 1MiB of colons is 16MiB of interval structs unbounded. | ||
| hostile := sid + ":" + strings.Repeat(":", 1<<20) | ||
| var before, after runtime.MemStats | ||
| runtime.GC() | ||
| runtime.ReadMemStats(&before) | ||
| _, _ = ParseMysql56GTIDSet(hostile) | ||
| runtime.ReadMemStats(&after) | ||
| allocated := after.TotalAlloc - before.TotalAlloc | ||
| assert.Less(t, allocated, uint64(8<<20), | ||
|
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 revision adds the allocation assertion but does not include the production fix: AGENTS.md reference: AGENTS.md:L79-L80 Useful? React with 👍 / 👎. |
||
| "parsing %d colons allocated %d bytes for intervals that are all discarded", | ||
| 1<<20, allocated) | ||
|
devin-ai-integration[bot] marked this conversation as resolved.
Outdated
|
||
| } | ||
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.
This test passes unchanged against the parent implementation and therefore cannot guard the allocation fix: every generated
:%d-%dinterval occupies at least four bytes, solen(tail)/4+1is never smaller than the colon-derived capacity and the new clamping branch is not taken. The colon-run test also passes before the fix because it checks only the existing parse error. Test the extracted capacity calculation or otherwise verify that malformed input receives bounded preallocation so reverting the fix makes a test fail.AGENTS.md reference: AGENTS.md:L79-L80
Useful? React with 👍 / 👎.