summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorNobuyoshi Nakada <[email protected]>2024-10-26 21:56:38 +0900
committergit <[email protected]>2024-11-05 05:01:03 +0000
commit348a53415339076afc4a02fcd09f3ae36e9c4c61 (patch)
tree9bf2ae1d762b087fd541b3fc53a5da914dbd708d /ext
parent511954dd5c22d8b63cd66c726d453c8db1408d3b (diff)
[ruby/stringio] Copy from the relocated string
When ungetting the string same as the same buffer string, extending the buffer can move the pointer in the argument. Reported by manun Manu (manun) at https://hackerone.com/reports/2805165. https://github.com/ruby/stringio/commit/95c1194832
Diffstat (limited to 'ext')
-rw-r--r--ext/stringio/stringio.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c
index 4a9cd6f1d9..7fe4180339 100644
--- a/ext/stringio/stringio.c
+++ b/ext/stringio/stringio.c
@@ -930,6 +930,18 @@ strio_extend(struct StringIO *ptr, long pos, long len)
}
}
+static void
+strio_unget_string(struct StringIO *ptr, VALUE c)
+{
+ const char *cp = NULL;
+ long cl = RSTRING_LEN(c);
+ if (cl > 0) {
+ if (c != ptr->string) cp = RSTRING_PTR(c);
+ strio_unget_bytes(ptr, cp, cl);
+ RB_GC_GUARD(c);
+ }
+}
+
/*
* call-seq:
* ungetc(character) -> nil
@@ -967,8 +979,7 @@ strio_ungetc(VALUE self, VALUE c)
if (enc != enc2 && enc != rb_ascii8bit_encoding()) {
c = rb_str_conv_enc(c, enc2, enc);
}
- strio_unget_bytes(ptr, RSTRING_PTR(c), RSTRING_LEN(c));
- RB_GC_GUARD(c);
+ strio_unget_string(ptr, c);
return Qnil;
}
}
@@ -995,13 +1006,8 @@ strio_ungetbyte(VALUE self, VALUE c)
strio_unget_bytes(ptr, &cc, 1);
}
else {
- long cl;
StringValue(c);
- cl = RSTRING_LEN(c);
- if (cl > 0) {
- strio_unget_bytes(ptr, RSTRING_PTR(c), cl);
- RB_GC_GUARD(c);
- }
+ strio_unget_string(ptr, c);
}
return Qnil;
}
@@ -1032,7 +1038,7 @@ strio_unget_bytes(struct StringIO *ptr, const char *cp, long cl)
if (rest > cl) memset(s + len, 0, rest - cl);
pos -= cl;
}
- memcpy(s + pos, cp, cl);
+ memcpy(s + pos, (cp ? cp : s), cl);
ptr->pos = pos;
return Qnil;
}