summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--string.c18
-rw-r--r--version.h2
3 files changed, 16 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 3e24ce7fd3..9c3ffb1b41 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Sat Jul 2 04:00:50 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>.
+
Sat Jul 2 03:33:28 2016 Shugo Maeda <shugo@ruby-lang.org>
* vm.c (invoke_bmethod, invoke_block_from_c_0): revert r52104
diff --git a/string.c b/string.c
index bc27b8cfdd..318acf38ff 100644
--- a/string.c
+++ b/string.c
@@ -5981,6 +5981,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) \
@@ -6062,11 +6063,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;
@@ -6107,7 +6109,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);
@@ -6120,7 +6122,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);
@@ -6145,9 +6147,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;
@@ -6180,7 +6182,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) {
@@ -6196,7 +6198,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);
diff --git a/version.h b/version.h
index 1baf03ef28..b6e35a02df 100644
--- a/version.h
+++ b/version.h
@@ -1,6 +1,6 @@
#define RUBY_VERSION "2.3.2"
#define RUBY_RELEASE_DATE "2016-07-02"
-#define RUBY_PATCHLEVEL 136
+#define RUBY_PATCHLEVEL 137
#define RUBY_RELEASE_YEAR 2016
#define RUBY_RELEASE_MONTH 7