string.c: fix terminator

* string.c (tr_trans): consider terminator length and fix heap
  overflow.  reported by Guido Vranken <guido AT guidovranken.nl>.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55427 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2016-06-16 02:15:27 +00:00
parent 9b75ddaafb
commit cc9f1e9195
2 changed files with 15 additions and 8 deletions

View File

@ -1,3 +1,8 @@
Thu Jun 16 11:15:25 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
* string.c (tr_trans): consider terminator length and fix heap
overflow. reported by Guido Vranken <guido AT guidovranken.nl>.
Thu Jun 16 00:02:32 2016 Kazuki Yamaguchi <k@rhe.jp> Thu Jun 16 00:02:32 2016 Kazuki Yamaguchi <k@rhe.jp>
* ext/openssl/ossl_ocsp.c (ossl_ocspreq_verify, ossl_ocspbres_verify): * ext/openssl/ossl_ocsp.c (ossl_ocspreq_verify, ossl_ocspbres_verify):

View File

@ -6217,6 +6217,7 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
char *s, *send; char *s, *send;
VALUE hash = 0; VALUE hash = 0;
int singlebyte = single_byte_optimizable(str); int singlebyte = single_byte_optimizable(str);
int termlen;
int cr; int cr;
#define CHECK_IF_ASCII(c) \ #define CHECK_IF_ASCII(c) \
@ -6298,11 +6299,12 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
cr = ENC_CODERANGE_7BIT; cr = ENC_CODERANGE_7BIT;
str_modify_keep_cr(str); str_modify_keep_cr(str);
s = RSTRING_PTR(str); send = RSTRING_END(str); s = RSTRING_PTR(str); send = RSTRING_END(str);
termlen = rb_enc_mbminlen(enc);
if (sflag) { if (sflag) {
int clen, tlen; int clen, tlen;
long offset, max = RSTRING_LEN(str); long offset, max = RSTRING_LEN(str);
unsigned int save = -1; unsigned int save = -1;
char *buf = ALLOC_N(char, max), *t = buf; char *buf = ALLOC_N(char, max + termlen), *t = buf;
while (s < send) { while (s < send) {
int may_modify = 0; int may_modify = 0;
@ -6343,7 +6345,7 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
while (t - buf + tlen >= max) { while (t - buf + tlen >= max) {
offset = t - buf; offset = t - buf;
max *= 2; max *= 2;
REALLOC_N(buf, char, max); REALLOC_N(buf, char, max + termlen);
t = buf + offset; t = buf + offset;
} }
rb_enc_mbcput(c, t, enc); 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)) { if (!STR_EMBED_P(str)) {
ruby_sized_xfree(STR_HEAP_PTR(str), STR_HEAP_SIZE(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.ptr = buf;
RSTRING(str)->as.heap.len = t - buf; RSTRING(str)->as.heap.len = t - buf;
STR_SET_NOEMBED(str); STR_SET_NOEMBED(str);
@ -6381,9 +6383,9 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
} }
} }
else { else {
int clen, tlen, max = (int)(RSTRING_LEN(str) * 1.2); int clen, tlen;
long offset; long offset, max = (long)((send - s) * 1.2);
char *buf = ALLOC_N(char, max), *t = buf; char *buf = ALLOC_N(char, max + termlen), *t = buf;
while (s < send) { while (s < send) {
int may_modify = 0; int may_modify = 0;
@ -6416,7 +6418,7 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
while (t - buf + tlen >= max) { while (t - buf + tlen >= max) {
offset = t - buf; offset = t - buf;
max *= 2; max *= 2;
REALLOC_N(buf, char, max); REALLOC_N(buf, char, max + termlen);
t = buf + offset; t = buf + offset;
} }
if (s != t) { if (s != t) {
@ -6432,7 +6434,7 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
if (!STR_EMBED_P(str)) { if (!STR_EMBED_P(str)) {
ruby_sized_xfree(STR_HEAP_PTR(str), STR_HEAP_SIZE(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.ptr = buf;
RSTRING(str)->as.heap.len = t - buf; RSTRING(str)->as.heap.len = t - buf;
STR_SET_NOEMBED(str); STR_SET_NOEMBED(str);