gitlab-labkit 4.1.1 → 4.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 809ee7b1894b9ff60755556cb95f69d9dca501297077e5eb1ddadac9d5d2b492
4
- data.tar.gz: 48d5598c40eefcd144ed435f0e0fafa7a2e1dffa305830e6f7bf1a4ce5e71d1e
3
+ metadata.gz: 65cd128c823d6b57133cffb5e0b4314af6ca3e18f0cf23c38c874e58a77bcdad
4
+ data.tar.gz: cbdd5aa4acc9250e07fb2332257e15c6712cf6a6c82389031d159f565a857dff
5
5
  SHA512:
6
- metadata.gz: 7081e60adc3b7d3929b83949710758c6af3ed04dca87337006637d7c4a1f90e6261c817bf0eae1a2ca5644763b25ee9896f06ff440670fadd1e675a64effec29
7
- data.tar.gz: eb903367e7296978188ca66f9affb82a543ee9342938934f8ea817f49bb7a843920e570279d03d727ae68d2cb8f73d3627b3c62715d806bac2c2f337a668e965
6
+ metadata.gz: 7c93fda74c06cd0d76c4aa37315a98433b24e94e3b8f6a4a67ff5e2f579dfb01b25b3f716b90806e175fada5bb5d7669adc3daf3483872f142a026a141f09675
7
+ data.tar.gz: 4e2ca4d166e927065772c3b87892c4bc0b5152e4c77eba4ec407bce5d7901e5cc136a7748e7063a777401c116c2f57414b8fb1d8ecdeea17b671107d9a73a2d7
@@ -24,10 +24,21 @@ module Labkit
24
24
  MAX_REGEX_SOURCE_LENGTH = 200
25
25
  ERROR_INSPECT_LIMIT = 80
26
26
 
27
+ # Wall-clock budget for a single #match? call. Without it a match is
28
+ # bounded only by whatever global the host sets (40s in GitLab Rails,
29
+ # unbounded elsewhere), and a timeout reaches Evaluator's fail-open
30
+ # rescue, so the request goes unlimited.
31
+ #
32
+ # 5ms is ~119x the slowest real match measured against GitLab's
33
+ # RackAttack path patterns on inputs up to 16KB (worst: 0.0419ms, none
34
+ # timed out). Re-measure if a rule ever needs nested quantifiers or
35
+ # backreferences, which are what make backtracking exponential.
36
+ MATCH_TIMEOUT_SECONDS = 0.005
37
+
27
38
  def self.build(input)
28
39
  case input
29
40
  when Regexp
30
- new(type: :re, value: input)
41
+ new(type: :re, value: with_match_timeout(input))
31
42
  when Hash
32
43
  from_hash(input)
33
44
  when Array
@@ -67,7 +78,7 @@ module Labkit
67
78
  end
68
79
 
69
80
  begin
70
- new(type: :re, value: Regexp.new(source))
81
+ new(type: :re, value: with_match_timeout(source))
71
82
  rescue RegexpError, TypeError => e
72
83
  raise ArgumentError,
73
84
  "rate-limit match value {re: #{truncate_for_error(source)}} failed to compile: #{e.message}"
@@ -76,6 +87,32 @@ module Labkit
76
87
  end
77
88
  private_class_method :compile
78
89
 
90
+ # Compiles +source+ (a String pattern or an existing Regexp) into a
91
+ # Regexp bounded by MATCH_TIMEOUT_SECONDS.
92
+ #
93
+ # The timeout is set per-Regexp rather than via the global
94
+ # +Regexp.timeout=+: labkit is a library, and a global would silently
95
+ # change regex behaviour throughout the host application, including
96
+ # code unrelated to rate limiting.
97
+ #
98
+ # A Regexp that already carries its own timeout is returned untouched -
99
+ # an explicit choice by the rule author wins over our default.
100
+ #
101
+ # Recompiling an existing Regexp preserves its source and options
102
+ # (including the fixed-encoding flags) and therefore +#==+; only object
103
+ # identity changes.
104
+ def self.with_match_timeout(source)
105
+ return source if source.is_a?(Regexp) && source.timeout
106
+
107
+ if source.is_a?(Regexp)
108
+ Regexp.new(source.source, source.options, timeout: MATCH_TIMEOUT_SECONDS)
109
+ else
110
+ Regexp.new(source, timeout: MATCH_TIMEOUT_SECONDS)
111
+ end
112
+ end
113
+
114
+ private_class_method :with_match_timeout
115
+
79
116
  def self.truncate_for_error(value)
80
117
  s = value.inspect
81
118
  s.length > ERROR_INSPECT_LIMIT ? "#{s[0, ERROR_INSPECT_LIMIT]}...(truncated)" : s
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-labkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.1
4
+ version: 4.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Newdigate