Repository navigation
Commit 226654a
committed
fix(commit): accumulate gpgsig continuation lines in linear time
`Commit._deserialize` collected a `gpgsig` header by appending each
continuation line to a `bytes` object with `+=`. `bytes` are immutable, so
every line copied the whole signature read so far, and a signature with *n*
continuation lines cost O(n^2) to parse.
Commit headers are fully controlled by whoever wrote the commit, and
`_deserialize` runs on the first access to any commit attribute (`author`,
`message`, `parents`, ...). Reading the commits of an untrusted repository is
therefore enough to hit it. Measured on Python 3.11 with a `gpgsig` header of
`" x\n"` lines:
| object size | before | after |
| ----------- | ------- | ------ |
| 2.4 MB | 9.5 s | 0.08 s |
| 4.8 MB | 116.8 s | |
| 9.6 MB | 547.9 s | 0.32 s |
Collect the lines in a list and join them once. This is linear and produces
byte-identical `gpgsig` values, so the existing `test_gpgsig` round trip is
unchanged.
`test_gpgsig_deserialization_is_linear` deserializes a 1.8 MB signature under
a 1 s CPU-time bound. It fails on the previous code and passes here. The full
suite has no new failures; the 8 tests that fail locally (non-UTF-8 trailer
encoding and NUL submodule names) fail identically without this change.
`ruff`, `mypy` and `basedpyright --warnings` are clean.1 parent 6306c5c commit 226654a
2 files changed
Lines changed: 25 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
885 | 885 | | |
886 | 886 | | |
887 | 887 | | |
888 | | - | |
| 888 | + | |
889 | 889 | | |
890 | 890 | | |
891 | 891 | | |
| |||
895 | 895 | | |
896 | 896 | | |
897 | 897 | | |
898 | | - | |
| 898 | + | |
899 | 899 | | |
900 | | - | |
| 900 | + | |
901 | 901 | | |
902 | 902 | | |
903 | 903 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
607 | 607 | | |
608 | 608 | | |
609 | 609 | | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
610 | 632 | | |
611 | 633 | | |
612 | 634 | | |
| |||
0 commit comments