Skip to content
  • Peter Zhu's avatar
    7b7dde37
    [ruby/psych] Guard from memory leak in Psych::Emitter#start_document · 7b7dde37
    Peter Zhu authored
    When an exception is raised, it can leak memory in `head`. There are two
    places that can leak memory:
    
    1. `Check_Type(tuple, T_ARRAY)` can leak memory if `tuple` is not an
       array.
    2. `StringValue(name)` and `StringValue(value)` if they are not strings
       and the call to `to_str` does not return a string.
    
    This commit fixes these memory leaks by wrapping the code around a
    rb_ensure so that the memory is freed in all cases.
    
    The following code demonstrates the memory leak:
    
        emitter = Psych::Emitter.new(StringIO.new)
        nil_to_string_tags = [[nil, "tag:TALOS"]] + ([1] * 1000)
        expected_array_tags = [1] * 1000
    
        10.times do
          1_000.times do
            # Raises `no implicit conversion of nil into String`
            emitter.start_document([], nil_to_string_tags, 0)
          rescue TypeError
          end
    
          1_000.times do
            # Raises `wrong argument type Integer (expected Array)`
            emitter.start_document([], expected_array_tags, 0)
          rescue TypeError
          end
    
          puts `ps -o rss= -p #{$$}`
        end
    
    Before:
    
        47248
        79728
        111968
        144224
        176480
        208896
        241104
        273280
        305472
        337664
    
    After:
    
        14832
        15088
        15344
        15344
        15360
        15632
        15632
        15632
        15648
        15648
    
    https://github.com/ruby/psych/commit/053af73818
    7b7dde37
    [ruby/psych] Guard from memory leak in Psych::Emitter#start_document
    Peter Zhu authored
    When an exception is raised, it can leak memory in `head`. There are two
    places that can leak memory:
    
    1. `Check_Type(tuple, T_ARRAY)` can leak memory if `tuple` is not an
       array.
    2. `StringValue(name)` and `StringValue(value)` if they are not strings
       and the call to `to_str` does not return a string.
    
    This commit fixes these memory leaks by wrapping the code around a
    rb_ensure so that the memory is freed in all cases.
    
    The following code demonstrates the memory leak:
    
        emitter = Psych::Emitter.new(StringIO.new)
        nil_to_string_tags = [[nil, "tag:TALOS"]] + ([1] * 1000)
        expected_array_tags = [1] * 1000
    
        10.times do
          1_000.times do
            # Raises `no implicit conversion of nil into String`
            emitter.start_document([], nil_to_string_tags, 0)
          rescue TypeError
          end
    
          1_000.times do
            # Raises `wrong argument type Integer (expected Array)`
            emitter.start_document([], expected_array_tags, 0)
          rescue TypeError
          end
    
          puts `ps -o rss= -p #{$$}`
        end
    
    Before:
    
        47248
        79728
        111968
        144224
        176480
        208896
        241104
        273280
        305472
        337664
    
    After:
    
        14832
        15088
        15344
        15344
        15360
        15632
        15632
        15632
        15648
        15648
    
    https://github.com/ruby/psych/commit/053af73818
Loading