summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--file.c3
-rw-r--r--sprintf.c5
-rw-r--r--string.c13
-rw-r--r--test/ruby/test_sprintf.rb10
4 files changed, 23 insertions, 8 deletions
diff --git a/file.c b/file.c
index 5265d3a3a5..92338bb754 100644
--- a/file.c
+++ b/file.c
@@ -4090,6 +4090,9 @@ static VALUE
str_shrink(VALUE str)
{
rb_str_resize(str, RSTRING_LEN(str));
+ // expand_path on Windows can sometimes mutate the string
+ // without clearing its coderange
+ ENC_CODERANGE_CLEAR(str);
return str;
}
diff --git a/sprintf.c b/sprintf.c
index 2b2b34b5b4..1ee293b6d9 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -937,6 +937,8 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
if (RTEST(ruby_verbose)) rb_warn("%s", mesg);
}
rb_str_resize(result, blen);
+ // rb_str_format mutates the string without updating coderange
+ ENC_CODERANGE_CLEAR(result);
return result;
}
@@ -1163,6 +1165,8 @@ ruby_vsprintf0(VALUE result, char *p, const char *fmt, va_list ap)
buffer.value = 0;
BSD_vfprintf(&f, fmt, ap);
RBASIC_SET_CLASS_RAW(result, klass);
+ // vfprintf mutates the string without updating coderange
+ ENC_CODERANGE_CLEAR(result);
rb_str_resize(result, (char *)f._p - RSTRING_PTR(result));
#undef f
}
@@ -1183,7 +1187,6 @@ rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
rb_enc_associate(result, enc);
}
ruby_vsprintf0(result, RSTRING_PTR(result), fmt, ap);
-
return result;
}
diff --git a/string.c b/string.c
index e74783cf92..6f211b2005 100644
--- a/string.c
+++ b/string.c
@@ -2498,7 +2498,6 @@ rb_str_modify_expand(VALUE str, long expand)
else if (expand > 0) {
RESIZE_CAPA_TERM(str, len + expand, termlen);
}
- ENC_CODERANGE_CLEAR(str);
}
/* As rb_str_modify(), but don't clear coderange */
@@ -3073,16 +3072,16 @@ rb_str_set_len(VALUE str, long len)
VALUE
rb_str_resize(VALUE str, long len)
{
- long slen;
- int independent;
-
if (len < 0) {
rb_raise(rb_eArgError, "negative string size (or size too big)");
}
- independent = str_independent(str);
- ENC_CODERANGE_CLEAR(str);
- slen = RSTRING_LEN(str);
+ int independent = str_independent(str);
+ long slen = RSTRING_LEN(str);
+
+ if (slen > len && ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
+ ENC_CODERANGE_CLEAR(str);
+ }
{
long capa;
diff --git a/test/ruby/test_sprintf.rb b/test/ruby/test_sprintf.rb
index f2e73eb58d..b05f4f3e44 100644
--- a/test/ruby/test_sprintf.rb
+++ b/test/ruby/test_sprintf.rb
@@ -507,6 +507,16 @@ class TestSprintf < Test::Unit::TestCase
end
end
+ def test_coderange
+ format_str = "wrong constant name %s"
+ interpolated_str = "\u3042"
+ assert_predicate format_str, :ascii_only?
+ refute_predicate interpolated_str, :ascii_only?
+
+ str = format_str % interpolated_str
+ refute_predicate str, :ascii_only?
+ end
+
def test_named_default
h = Hash.new('world')
assert_equal("hello world", "hello %{location}" % h)