VYPR
Critical severity9.8NVD Advisory· Published May 14, 2024· Updated Apr 15, 2026

CVE-2024-27280

CVE-2024-27280

Description

A buffer-overread issue was discovered in StringIO 3.0.1, as distributed in Ruby 3.0.x through 3.0.6 and 3.1.x through 3.1.4. The ungetbyte and ungetc methods on a StringIO can read past the end of a string, and a subsequent call to StringIO.gets may return the memory value. 3.0.3 is the main fixed version; however, for Ruby 3.0 users, a fixed version is stringio 3.0.1.1, and for Ruby 3.1 users, a fixed version is stringio 3.0.1.2.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
stringioRubyGems
< 3.0.1.13.0.1.1

Patches

2
0e5965240977

merge revision(s) 21dced8b01823a991829b66ffdc8ffc635965c76: [Backport #19389]

https://github.com/ruby/stringionagachikaMar 21, 2023via ghsa
2 files changed · +5 2
  • ext/stringio/stringio.c+3 2 modified
    @@ -1233,8 +1233,9 @@ strio_getline(struct getline_arg *arg, struct StringIO *ptr)
     	str = strio_substr(ptr, ptr->pos, e - s - w, enc);
         }
         else {
    -	if (n < e - s) {
    -	    if (e - s < 1024) {
    +	if (n < e - s + arg->chomp) {
    +	    /* unless chomping, RS at the end does not matter */
    +	    if (e - s < 1024 || n == e - s) {
     		for (p = s; p + n <= e; ++p) {
     		    if (MEMCMP(p, RSTRING_PTR(str), char, n) == 0) {
     			e = p + (arg->chomp ? 0 : n);
    
  • test/stringio/test_stringio.rb+2 0 modified
    @@ -99,6 +99,8 @@ def test_gets_chomp
         assert_equal("def", stringio.gets("", chomp: true))
     
         assert_string("", Encoding::UTF_8, StringIO.new("\n").gets(chomp: true))
    +
    +    assert_equal("", StringIO.new("ab").gets("ab", chomp: true))
       end
     
       def test_gets_chomp_eol
    
c58c5f54f1ea

[ruby/stringio] Fix expanding size at ungetc/ungetbyte

https://github.com/ruby/stringioNobuyoshi NakadaNov 16, 2021via ghsa
2 files changed · +22 5
  • ext/stringio/stringio.c+1 1 modified
    @@ -984,7 +984,7 @@ strio_unget_bytes(struct StringIO *ptr, const char *cp, long cl)
         len = RSTRING_LEN(str);
         rest = pos - len;
         if (cl > pos) {
    -	long ex = (rest < 0 ? cl-pos : cl+rest);
    +	long ex = cl - (rest < 0 ? pos : len);
     	rb_str_modify_expand(str, ex);
     	rb_str_set_len(str, len + ex);
     	s = RSTRING_PTR(str);
    
  • test/stringio/test_stringio.rb+21 4 modified
    @@ -757,6 +757,15 @@ def test_ungetc_padding
         assert_equal("b""\0""a", s.string)
       end
     
    +  def test_ungetc_fill
    +    count = 100
    +    s = StringIO.new
    +    s.print 'a' * count
    +    s.ungetc('b' * (count * 5))
    +    assert_equal((count * 5), s.string.size)
    +    assert_match(/\Ab+\z/, s.string)
    +  end
    +
       def test_ungetbyte_pos
         b = '\\b00010001 \\B00010001 \\b1 \\B1 \\b000100011'
         s = StringIO.new( b )
    @@ -782,6 +791,15 @@ def test_ungetbyte_padding
         assert_equal("b""\0""a", s.string)
       end
     
    +  def test_ungetbyte_fill
    +    count = 100
    +    s = StringIO.new
    +    s.print 'a' * count
    +    s.ungetbyte('b' * (count * 5))
    +    assert_equal((count * 5), s.string.size)
    +    assert_match(/\Ab+\z/, s.string)
    +  end
    +
       def test_frozen
         s = StringIO.new
         s.freeze
    @@ -825,18 +843,17 @@ def test_new_block_warning
       end
     
       def test_overflow
    -    omit if RbConfig::SIZEOF["void*"] > RbConfig::SIZEOF["long"]
    +    return if RbConfig::SIZEOF["void*"] > RbConfig::SIZEOF["long"]
         limit = RbConfig::LIMITS["INTPTR_MAX"] - 0x10
         assert_separately(%w[-rstringio], "#{<<-"begin;"}\n#{<<-"end;"}")
         begin;
           limit = #{limit}
           ary = []
    -      while true
    +      begin
             x = "a"*0x100000
             break if [x].pack("p").unpack("i!")[0] < 0
             ary << x
    -        omit if ary.size > 100
    -      end
    +      end while ary.size <= 100
           s = StringIO.new(x)
           s.gets("xxx", limit)
           assert_equal(0x100000, s.pos)
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

18

News mentions

0

No linked articles in our index yet.