Skip to content

Optimize Gem::Text#format_text performance#9418

Open
apocalypse9949 wants to merge 3 commits intoruby:masterfrom
apocalypse9949:master
Open

Optimize Gem::Text#format_text performance#9418
apocalypse9949 wants to merge 3 commits intoruby:masterfrom
apocalypse9949:master

Conversation

@apocalypse9949
Copy link

The Gem::Text#format_text method contained a performance bottleneck that caused it to run with an $O(N^2)$ time complexity. This was due to the use of String#slice!(0, length) inside a while loop to iteratively strip chunks from the beginning of the work string.

Because String#slice! modifies the string in-place, it requires shifting the remaining characters in memory to the left during every iteration. When processing very long strings (such as maliciously crafted gem descriptions), the repeated memory shifting leads to excessive CPU usage and a potential Denial of Service (DoS) vulnerability.

This PR resolves the performance bottleneck by refactoring format_text to use non-destructive string slicing (String#slice) combined with reassignment (work = work.slice(...)).

Ruby optimizes String#slice using a shared string buffer (copy-on-write), meaning it simply creates a new string object that points to an offset within the original buffer rather than duplicating the entire buffer. This prevents the memory-shifting overhead and effectively reduces the time complexity to $O(N)$.

String#slice! modifies the string in place, it shifts
all remaining characters to the left, resulting in O(N^2) time complexity
when formatting very long strings. This could lead to excessive CPU usage and potential DoS vulnerability if passed maliciously long strings.
testing Modifed Gem : : in tib/rubygems/version. rb by using a script to inject a fast path
optimization at the beginning of def <=>(other). The fast path should target versions that have
no pre-release segments and 4 or fewer segments. Since canonicat_segments might be slower,
we will avoid computing it if possible and use _ segments for simple numerical checks. We can
write an explicit comparison:
@apocalypse9949
Copy link
Author

testing Modified Gem : :Version#<=> in tib/rubygems/version .rb by using a script to inject a fast path
optimization at the beginning of def <=>(other). The fast path should target versions that have
no pre-release segments and 4 or fewer segments. Since canonical_segments might be slower,
we will avoid computing it if possible and use _ segments for simple numerical checks. We can
write an explicit comparison
just testing if it works or not

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant