Fix memory leak in String#tr and String#tr_s

rb_enc_codepoint_len could raise, which would cause the memory in buf
to leak.

For example:

    str1 = "\xE0\xA0\xA1#{" " * 100}".force_encoding("EUC-JP")
    str2 = ""
    str3 = "a".force_encoding("Windows-31J")

    10.times do
      1_000_000.times do
        str1.tr_s(str2, str3)
      rescue
      end

      puts `ps -o rss= -p #{$$}`
    end

Before:

    17536
    22752
    28032
    33312
    38688
    43968
    49200
    54432
    59744
    64992

After:

    12176
    12352
    12352
    12448
    12448
    12448
    12448
    12448
    12448
    12448
This commit is contained in:
Peter Zhu 2024-01-16 09:32:21 -05:00
Родитель 67a545b3d2
Коммит e17c83e02c
1 изменённых файлов: 17 добавлений и 2 удалений

Просмотреть файл

@ -7987,7 +7987,14 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
while (s < send) {
int may_modify = 0;
c0 = c = rb_enc_codepoint_len((char *)s, (char *)send, &clen, e1);
int r = rb_enc_precise_mbclen((char *)s, (char *)send, e1);
if (!MBCLEN_CHARFOUND_P(r)) {
xfree(buf);
rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(e1));
}
clen = MBCLEN_CHARFOUND_LEN(r);
c0 = c = rb_enc_mbc_to_codepoint((char *)s, (char *)send, e1);
tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
s += clen;
@ -8067,7 +8074,15 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
while (s < send) {
int may_modify = 0;
c0 = c = rb_enc_codepoint_len((char *)s, (char *)send, &clen, e1);
int r = rb_enc_precise_mbclen((char *)s, (char *)send, e1);
if (!MBCLEN_CHARFOUND_P(r)) {
xfree(buf);
rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(e1));
}
clen = MBCLEN_CHARFOUND_LEN(r);
c0 = c = rb_enc_mbc_to_codepoint((char *)s, (char *)send, e1);
tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
if (c < 256) {