aboutsummaryrefslogtreecommitdiffstats
path: root/string.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2019-06-19 10:44:54 -0700
committerJeremy Evans <code@jeremyevans.net>2019-07-02 08:34:01 -0700
commit0f283054e7f568f09fbfc952d57ea6daf4abbd88 (patch)
tree18106e6c0c0f743ffcd5028e0ce0a564f3c89610 /string.c
parent7582287eb27e6b649789ce31ffdcbbb9ffcaf726 (diff)
downloadruby-0f283054e7f568f09fbfc952d57ea6daf4abbd88.tar.gz
Check that String#scrub block does not modify receiver
Similar to the check used for String#gsub. Can fix possible segfault. Fixes [Bug #15941]
Diffstat (limited to 'string.c')
-rw-r--r--string.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/string.c b/string.c
index 2bf9586e98..8d7d2ad7b9 100644
--- a/string.c
+++ b/string.c
@@ -10278,9 +10278,10 @@ enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl, int cr)
{
int encidx;
VALUE buf = Qnil;
- const char *rep;
+ const char *rep, *p, *e, *p1, *sp;
long replen = -1;
int tainted = 0;
+ long slen;
if (rb_block_given_p()) {
if (!NIL_P(repl))
@@ -10306,10 +10307,13 @@ enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl, int cr)
rep = replace; replen = (int)sizeof(replace); \
} while (0)
+ slen = RSTRING_LEN(str);
+ p = RSTRING_PTR(str);
+ e = RSTRING_END(str);
+ p1 = p;
+ sp = p;
+
if (rb_enc_asciicompat(enc)) {
- const char *p = RSTRING_PTR(str);
- const char *e = RSTRING_END(str);
- const char *p1 = p;
int rep7bit_p;
if (!replen) {
rep = NULL;
@@ -10374,6 +10378,7 @@ enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl, int cr)
}
else {
repl = rb_yield(rb_enc_str_new(p, clen, enc));
+ str_mod_check(str, sp, slen);
repl = str_compat_and_valid(repl, enc);
tainted |= OBJ_TAINTED_RAW(repl);
rb_str_buf_cat(buf, RSTRING_PTR(repl), RSTRING_LEN(repl));
@@ -10409,6 +10414,7 @@ enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl, int cr)
}
else {
repl = rb_yield(rb_enc_str_new(p, e-p, enc));
+ str_mod_check(str, sp, slen);
repl = str_compat_and_valid(repl, enc);
tainted |= OBJ_TAINTED_RAW(repl);
rb_str_buf_cat(buf, RSTRING_PTR(repl), RSTRING_LEN(repl));
@@ -10419,9 +10425,6 @@ enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl, int cr)
}
else {
/* ASCII incompatible */
- const char *p = RSTRING_PTR(str);
- const char *e = RSTRING_END(str);
- const char *p1 = p;
long mbminlen = rb_enc_mbminlen(enc);
if (!replen) {
rep = NULL;
@@ -10478,6 +10481,7 @@ enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl, int cr)
}
else {
repl = rb_yield(rb_enc_str_new(p, clen, enc));
+ str_mod_check(str, sp, slen);
repl = str_compat_and_valid(repl, enc);
tainted |= OBJ_TAINTED_RAW(repl);
rb_str_buf_cat(buf, RSTRING_PTR(repl), RSTRING_LEN(repl));
@@ -10505,6 +10509,7 @@ enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl, int cr)
}
else {
repl = rb_yield(rb_enc_str_new(p, e-p, enc));
+ str_mod_check(str, sp, slen);
repl = str_compat_and_valid(repl, enc);
tainted |= OBJ_TAINTED_RAW(repl);
rb_str_buf_cat(buf, RSTRING_PTR(repl), RSTRING_LEN(repl));