From b31a538576a9676065654b0c55d5365845d35a8b Mon Sep 17 00:00:00 2001 From: tomoya ishida Date: Thu, 18 Jan 2024 12:42:15 +0900 Subject: [PATCH] Fix ascii_only? flag in strio_write (#77) Followup of #79 `rb_str_resize()` was changed by https://github.com/ruby/ruby/commit/b0b9f7201acab05c2a3ad92c3043a1f01df3e17f . ```c rb_str_resize(string, shorter) // clear ENC_CODERANGE in some case rb_str_resize(string, longer) // does not clear ENC_CODERANGE anymore ``` ```c // rb_str_resize in string.c if (slen > len && ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) { ENC_CODERANGE_CLEAR(str); } ``` I think this change is based on an assumption that appending null bytes will not change flag `ascii_only?`. `strio_extend()` will make the string longer if needed, and update the flags correctly for appending null bytes. Before `memmove()`, we need to `rb_str_modify()` because updated flags are not updated for `memmove()`. --- ext/stringio/stringio.c | 10 +--------- test/stringio/test_stringio.rb | 6 ++++++ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c index 4eb1511..27c7f65 100644 --- a/ext/stringio/stringio.c +++ b/ext/stringio/stringio.c @@ -915,9 +915,6 @@ strio_extend(struct StringIO *ptr, long pos, long len) if (pos > olen) MEMZERO(RSTRING_PTR(ptr->string) + olen, char, pos - olen); } - else { - rb_str_modify(ptr->string); - } } /* @@ -1464,14 +1461,9 @@ strio_write(VALUE self, VALUE str) } } else { - int cr0 = ENC_CODERANGE(ptr->string); - int cr = ENC_CODERANGE_UNKNOWN; - if (rb_enc_asciicompat(enc) && rb_enc_asciicompat(enc2)) { - cr = ENC_CODERANGE_AND(cr0, ENC_CODERANGE(str)); - } strio_extend(ptr, ptr->pos, len); + rb_str_modify(ptr->string); memmove(RSTRING_PTR(ptr->string)+ptr->pos, RSTRING_PTR(str), len); - if (cr != cr0) ENC_CODERANGE_SET(ptr->string, cr); } RB_GC_GUARD(str); ptr->pos += len; diff --git a/test/stringio/test_stringio.rb b/test/stringio/test_stringio.rb index 15fcc21..8afbcf3 100644 --- a/test/stringio/test_stringio.rb +++ b/test/stringio/test_stringio.rb @@ -961,6 +961,12 @@ def test_coderange_after_overwrite assert_predicate(s.string, :ascii_only?) s.write "\u{431 43e 433 443 441}" assert_not_predicate(s.string, :ascii_only?) + + s = StringIO.new("\u{3042}") + s.rewind + assert_not_predicate(s.string, :ascii_only?) + s.write('aaaa') + assert_predicate(s.string, :ascii_only?) end def assert_string(content, encoding, str, mesg = nil)