Issue #12757 has been reported by Kazuki Yamaguchi.

----------------------------------------
Bug #12757: Wrong overflow check in rb_str_set_len()
https://bugs.ruby-lang.org/issues/12757

* Author: Kazuki Yamaguchi
* Status: Open
* Priority: Normal
* Assignee: 
* ruby -v: 
* Backport: 2.1: UNKNOWN, 2.2: REQUIRED, 2.3: REQUIRED
----------------------------------------
string.c:

~~~c
void
rb_str_set_len(VALUE str, long len)
{
    long capa;
    const int termlen = TERM_LEN(str);

    str_modifiable(str);
    if (STR_SHARED_P(str)) {
        rb_raise(rb_eRuntimeError, "can't set length of shared string");
    }
    if (len + termlen - 1 > (capa = (long)rb_str_capacity(str))) {
        rb_bug("probable buffer overflow: %ld for %ld", len, capa);
    }
    STR_SET_LEN(str, len);
    TERM_FILL(&RSTRING_PTR(str)[len], termlen);
}
~~~

The overflow check `len + termlen - 1 > (capa = (long)rb_str_capacity(str))` is wrong, as the `capa` does not include the space for termlen. This can cause false-positive [BUG] for String with multi-byte termlen when setting the length to the number equal to the capacity.

For example, the following code that internally calls rb_str_set_len() causes the [BUG]:

~~~ruby
str = String.new(capacity: 100, encoding: "UTF-32BE")
IO.pipe { |r, w|
  w.write("x"*100)
  r.read(100, str)
}
~~~



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>