summaryrefslogtreecommitdiff
path: root/string.c
diff options
context:
space:
mode:
authornagachika <nagachika@ruby-lang.org>2023-09-30 13:51:18 +0900
committernagachika <nagachika@ruby-lang.org>2023-09-30 13:51:18 +0900
commitddbab4f837460f070942e8127de9a9f1b9868fff (patch)
treeedfc27866027033b4c319dbd0b1848762acc26e0 /string.c
parent128d8728d39c2da21e5433c7af169f73e18fd133 (diff)
merge revision(s) 6b66b5fdedb2c9a9ee48e290d57ca7f8d55e01a2: [Backport #19902]
[Bug #19902] Update the coderange regarding the changed region --- ext/-test-/string/set_len.c | 10 ++++++++++ string.c | 27 +++++++++++++++++++++++++++ test/-ext-/string/test_set_len.rb | 29 +++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+)
Diffstat (limited to 'string.c')
-rw-r--r--string.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/string.c b/string.c
index 2d16c910c8..1007ff091e 100644
--- a/string.c
+++ b/string.c
@@ -3029,6 +3029,33 @@ rb_str_set_len(VALUE str, long len)
if (len > (capa = (long)str_capacity(str, termlen)) || len < 0) {
rb_bug("probable buffer overflow: %ld for %ld", len, capa);
}
+
+ int cr = ENC_CODERANGE(str);
+ if (cr == ENC_CODERANGE_UNKNOWN) {
+ /* Leave unknown. */
+ }
+ else if (len > RSTRING_LEN(str)) {
+ if (ENC_CODERANGE_CLEAN_P(cr)) {
+ /* Update the coderange regarding the extended part. */
+ const char *const prev_end = RSTRING_END(str);
+ const char *const new_end = RSTRING_PTR(str) + len;
+ rb_encoding *enc = rb_enc_get(str);
+ rb_str_coderange_scan_restartable(prev_end, new_end, enc, &cr);
+ ENC_CODERANGE_SET(str, cr);
+ }
+ else if (cr == ENC_CODERANGE_BROKEN) {
+ /* May be valid now, by appended part. */
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_UNKNOWN);
+ }
+ }
+ else if (len < RSTRING_LEN(str)) {
+ if (cr != ENC_CODERANGE_7BIT) {
+ /* ASCII-only string is keeping after truncated. Valid
+ * and broken may be invalid or valid, leave unknown. */
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_UNKNOWN);
+ }
+ }
+
STR_SET_LEN(str, len);
TERM_FILL(&RSTRING_PTR(str)[len], termlen);
}