@@ -291,6 +291,12 @@ def self.[](config)
291291 # CopyUIDData for +COPYUID+ response codes, and UIDPlusData or
292292 # AppendUIDData for +APPENDUID+ response codes.
293293 #
294+ # UIDPlusData stores its data in arrays of numbers, which is vulnerable to
295+ # a memory exhaustion denial of service attack from an untrusted or
296+ # compromised server. Set this option to +false+ to completely block this
297+ # vulnerability. Otherwise, parser_max_deprecated_uidplus_data_size
298+ # mitigates this vulnerability.
299+ #
294300 # AppendUIDData and CopyUIDData are _mostly_ backward-compatible with
295301 # UIDPlusData. Most applications should be able to upgrade with little
296302 # or no changes.
@@ -313,6 +319,30 @@ def self.[](config)
313319 true , false
314320 ]
315321
322+ # The maximum +uid-set+ size that ResponseParser will parse into
323+ # deprecated UIDPlusData. This limit only applies when
324+ # parser_use_deprecated_uidplus_data is not +false+.
325+ #
326+ # <em>(Parser support for +UIDPLUS+ added in +v0.3.2+.)</em>
327+ #
328+ # <em>Support for limiting UIDPlusData to a maximum size was added in
329+ # +v0.3.8+, +v0.4.19+, and +v0.5.6+.</em>
330+ #
331+ # <em>UIDPlusData will be removed in +v0.6+.</em>
332+ #
333+ # ==== Versioned Defaults
334+ #
335+ # Because this limit guards against a remote server causing catastrophic
336+ # memory exhaustion, the versioned default (used by #load_defaults) also
337+ # applies to versions without the feature.
338+ #
339+ # * +0.3+ and prior: <tt>10,000</tt>
340+ # * +0.4+: <tt>1,000</tt>
341+ # * +0.5+: <tt>100</tt>
342+ # * +0.6+: <tt>0</tt>
343+ #
344+ attr_accessor :parser_max_deprecated_uidplus_data_size , type : Integer
345+
316346 # Creates a new config object and initialize its attribute with +attrs+.
317347 #
318348 # If +parent+ is not given, the global config is used by default.
@@ -394,6 +424,7 @@ def defaults_hash
394424 enforce_logindisabled : true ,
395425 responses_without_block : :warn ,
396426 parser_use_deprecated_uidplus_data : true ,
427+ parser_max_deprecated_uidplus_data_size : 100 ,
397428 ) . freeze
398429
399430 @global = default . new
@@ -406,6 +437,7 @@ def defaults_hash
406437 responses_without_block : :silence_deprecation_warning ,
407438 enforce_logindisabled : false ,
408439 parser_use_deprecated_uidplus_data : true ,
440+ parser_max_deprecated_uidplus_data_size : 10_000 ,
409441 ) . freeze
410442 version_defaults [ 0.0 ] = Config [ 0 ]
411443 version_defaults [ 0.1 ] = Config [ 0 ]
@@ -414,13 +446,15 @@ def defaults_hash
414446
415447 version_defaults [ 0.4 ] = Config [ 0.3 ] . dup . update (
416448 sasl_ir : true ,
449+ parser_max_deprecated_uidplus_data_size : 1000 ,
417450 ) . freeze
418451
419452 version_defaults [ 0.5 ] = Config [ :current ]
420453
421454 version_defaults [ 0.6 ] = Config [ 0.5 ] . dup . update (
422455 responses_without_block : :frozen_dup ,
423456 parser_use_deprecated_uidplus_data : false ,
457+ parser_max_deprecated_uidplus_data_size : 0 ,
424458 ) . freeze
425459 version_defaults [ :next ] = Config [ 0.6 ]
426460 version_defaults [ :future ] = Config [ :next ]
0 commit comments