From cc9f1e919518edbee41d602ce215175f52f8f5f5 Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 16 Jun 2016 02:15:27 +0000 Subject: [PATCH] string.c: fix terminator * string.c (tr_trans): consider terminator length and fix heap overflow. reported by Guido Vranken . git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55427 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 +++++ string.c | 18 ++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7757759881..869fd9535e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Thu Jun 16 11:15:25 2016 Nobuyoshi Nakada + + * string.c (tr_trans): consider terminator length and fix heap + overflow. reported by Guido Vranken . + Thu Jun 16 00:02:32 2016 Kazuki Yamaguchi * ext/openssl/ossl_ocsp.c (ossl_ocspreq_verify, ossl_ocspbres_verify): diff --git a/string.c b/string.c index 8877c11ba6..7cb6af2727 100644 --- a/string.c +++ b/string.c @@ -6217,6 +6217,7 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag) char *s, *send; VALUE hash = 0; int singlebyte = single_byte_optimizable(str); + int termlen; int cr; #define CHECK_IF_ASCII(c) \ @@ -6298,11 +6299,12 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag) cr = ENC_CODERANGE_7BIT; str_modify_keep_cr(str); s = RSTRING_PTR(str); send = RSTRING_END(str); + termlen = rb_enc_mbminlen(enc); if (sflag) { int clen, tlen; long offset, max = RSTRING_LEN(str); unsigned int save = -1; - char *buf = ALLOC_N(char, max), *t = buf; + char *buf = ALLOC_N(char, max + termlen), *t = buf; while (s < send) { int may_modify = 0; @@ -6343,7 +6345,7 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag) while (t - buf + tlen >= max) { offset = t - buf; max *= 2; - REALLOC_N(buf, char, max); + REALLOC_N(buf, char, max + termlen); t = buf + offset; } rb_enc_mbcput(c, t, enc); @@ -6356,7 +6358,7 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag) if (!STR_EMBED_P(str)) { ruby_sized_xfree(STR_HEAP_PTR(str), STR_HEAP_SIZE(str)); } - TERM_FILL(t, rb_enc_mbminlen(enc)); + TERM_FILL(t, termlen); RSTRING(str)->as.heap.ptr = buf; RSTRING(str)->as.heap.len = t - buf; STR_SET_NOEMBED(str); @@ -6381,9 +6383,9 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag) } } else { - int clen, tlen, max = (int)(RSTRING_LEN(str) * 1.2); - long offset; - char *buf = ALLOC_N(char, max), *t = buf; + int clen, tlen; + long offset, max = (long)((send - s) * 1.2); + char *buf = ALLOC_N(char, max + termlen), *t = buf; while (s < send) { int may_modify = 0; @@ -6416,7 +6418,7 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag) while (t - buf + tlen >= max) { offset = t - buf; max *= 2; - REALLOC_N(buf, char, max); + REALLOC_N(buf, char, max + termlen); t = buf + offset; } if (s != t) { @@ -6432,7 +6434,7 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag) if (!STR_EMBED_P(str)) { ruby_sized_xfree(STR_HEAP_PTR(str), STR_HEAP_SIZE(str)); } - TERM_FILL(t, rb_enc_mbminlen(enc)); + TERM_FILL(t, termlen); RSTRING(str)->as.heap.ptr = buf; RSTRING(str)->as.heap.len = t - buf; STR_SET_NOEMBED(str);