Skip to content

Commit b0b9f72

Browse files
committed
rb_str_resize: Only clear coderange on truncation
If we are expanding the string or only stripping extra capacity then coderange won't change, so clearing it is wasteful.
1 parent fe61cad commit b0b9f72

File tree

4 files changed

+23
-8
lines changed

4 files changed

+23
-8
lines changed

file.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4090,6 +4090,9 @@ static VALUE
40904090
str_shrink(VALUE str)
40914091
{
40924092
rb_str_resize(str, RSTRING_LEN(str));
4093+
// expand_path on Windows can sometimes mutate the string
4094+
// without clearing its coderange
4095+
ENC_CODERANGE_CLEAR(str);
40934096
return str;
40944097
}
40954098

sprintf.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,8 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
937937
if (RTEST(ruby_verbose)) rb_warn("%s", mesg);
938938
}
939939
rb_str_resize(result, blen);
940+
// rb_str_format mutates the string without updating coderange
941+
ENC_CODERANGE_CLEAR(result);
940942

941943
return result;
942944
}
@@ -1163,6 +1165,8 @@ ruby_vsprintf0(VALUE result, char *p, const char *fmt, va_list ap)
11631165
buffer.value = 0;
11641166
BSD_vfprintf(&f, fmt, ap);
11651167
RBASIC_SET_CLASS_RAW(result, klass);
1168+
// vfprintf mutates the string without updating coderange
1169+
ENC_CODERANGE_CLEAR(result);
11661170
rb_str_resize(result, (char *)f._p - RSTRING_PTR(result));
11671171
#undef f
11681172
}
@@ -1183,7 +1187,6 @@ rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
11831187
rb_enc_associate(result, enc);
11841188
}
11851189
ruby_vsprintf0(result, RSTRING_PTR(result), fmt, ap);
1186-
11871190
return result;
11881191
}
11891192

string.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2498,7 +2498,6 @@ rb_str_modify_expand(VALUE str, long expand)
24982498
else if (expand > 0) {
24992499
RESIZE_CAPA_TERM(str, len + expand, termlen);
25002500
}
2501-
ENC_CODERANGE_CLEAR(str);
25022501
}
25032502

25042503
/* As rb_str_modify(), but don't clear coderange */
@@ -3073,16 +3072,16 @@ rb_str_set_len(VALUE str, long len)
30733072
VALUE
30743073
rb_str_resize(VALUE str, long len)
30753074
{
3076-
long slen;
3077-
int independent;
3078-
30793075
if (len < 0) {
30803076
rb_raise(rb_eArgError, "negative string size (or size too big)");
30813077
}
30823078

3083-
independent = str_independent(str);
3084-
ENC_CODERANGE_CLEAR(str);
3085-
slen = RSTRING_LEN(str);
3079+
int independent = str_independent(str);
3080+
long slen = RSTRING_LEN(str);
3081+
3082+
if (slen > len && ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
3083+
ENC_CODERANGE_CLEAR(str);
3084+
}
30863085

30873086
{
30883087
long capa;

test/ruby/test_sprintf.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,16 @@ def test_named_typed_enc
507507
end
508508
end
509509

510+
def test_coderange
511+
format_str = "wrong constant name %s"
512+
interpolated_str = "\u3042"
513+
assert_predicate format_str, :ascii_only?
514+
refute_predicate interpolated_str, :ascii_only?
515+
516+
str = format_str % interpolated_str
517+
refute_predicate str, :ascii_only?
518+
end
519+
510520
def test_named_default
511521
h = Hash.new('world')
512522
assert_equal("hello world", "hello %{location}" % h)

0 commit comments

Comments
 (0)