Skip to content

Commit e17c83e

Browse files
committed
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
1 parent 67a545b commit e17c83e

File tree

1 file changed

+17
-2
lines changed

1 file changed

+17
-2
lines changed

string.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7987,7 +7987,14 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
79877987
while (s < send) {
79887988
int may_modify = 0;
79897989

7990-
c0 = c = rb_enc_codepoint_len((char *)s, (char *)send, &clen, e1);
7990+
int r = rb_enc_precise_mbclen((char *)s, (char *)send, e1);
7991+
if (!MBCLEN_CHARFOUND_P(r)) {
7992+
xfree(buf);
7993+
rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(e1));
7994+
}
7995+
clen = MBCLEN_CHARFOUND_LEN(r);
7996+
c0 = c = rb_enc_mbc_to_codepoint((char *)s, (char *)send, e1);
7997+
79917998
tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
79927999

79938000
s += clen;
@@ -8067,7 +8074,15 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
80678074

80688075
while (s < send) {
80698076
int may_modify = 0;
8070-
c0 = c = rb_enc_codepoint_len((char *)s, (char *)send, &clen, e1);
8077+
8078+
int r = rb_enc_precise_mbclen((char *)s, (char *)send, e1);
8079+
if (!MBCLEN_CHARFOUND_P(r)) {
8080+
xfree(buf);
8081+
rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(e1));
8082+
}
8083+
clen = MBCLEN_CHARFOUND_LEN(r);
8084+
c0 = c = rb_enc_mbc_to_codepoint((char *)s, (char *)send, e1);
8085+
80718086
tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
80728087

80738088
if (c < 256) {

0 commit comments

Comments
 (0)