Skip to content

Commit

Permalink
⚡✅ Update all net-imap regexps to run in O(n)
Browse files Browse the repository at this point in the history
The BIDI_FAILURE regexps all used `\g<name>` to define char classes and
then re-use them.  Unfortunately, ruby 3.2 can't compile that to run in
linear time.  The regexps could also be written using lookahead, but
that also wouldn't run in linear time.

The debug output gsub is simple to accomplish without negative lookahead
by using a block with gsub and checking `$'.empty?`.

`bin/check-regexps` was added for quick double-check, just in case the
tests aren't catching everything.
  • Loading branch information
nevans committed Apr 28, 2023
1 parent 92db350 commit 8008407
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 79 deletions.
27 changes: 27 additions & 0 deletions bin/check-regexps
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

# See also: test/net/imap/regexp_collector.rb
# See also: test/net/imap/test_regexps.rb

def traverse(m=Object, s=Set.new, &b)
m.constants(false).map{m.const_get _1 rescue nil}.select{_1 in Module}.each do
next if s.include?(_1); s << _1
b and b[_1]
traverse(_1, s, &b)
end
end

def collect_regexps = ObjectSpace
.each_object(Regexp)
.reject{Regexp.linear_time? _1}

2.times{traverse}
before = collect_regexps

$LOAD_PATH.unshift "./lib"
require 'net/imap'
2.times{traverse}
traverse(Net::IMAP) { puts _1.name }
after = collect_regexps - before
p before: before.count, count: after.count, after:;
4 changes: 2 additions & 2 deletions lib/net/imap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2443,8 +2443,8 @@ def put_string(str)
if @debug_output_bol
$stderr.print("C: ")
end
$stderr.print(str.gsub(/\n(?!\z)/n, "\nC: "))
if /\r\n\z/n.match(str)
$stderr.print(str.gsub(/\n/n) { $'.empty? ? $& : "\nC: " })
if /\n\z/n.match(str)
@debug_output_bol = true
else
@debug_output_bol = false
Expand Down
14 changes: 1 addition & 13 deletions lib/net/imap/stringprep/saslprep_tables.rb

Large diffs are not rendered by default.

Loading

0 comments on commit 8008407

Please sign in to comment.