mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
merge revision(s) 49405-49408:
* string.c (str_make_independent_expand): terminate String when moved from heap to embedded. [Fix GH-821]. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_2@49644 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
490165e5e3
commit
d43dcc67ce
4 changed files with 48 additions and 11 deletions
|
@ -1,3 +1,8 @@
|
|||
Thu Feb 19 15:32:26 2015 Dave Stevens <dave@crowdlab.com>
|
||||
|
||||
* string.c (str_make_independent_expand): terminate String when
|
||||
moved from heap to embedded. [Fix GH-821].
|
||||
|
||||
Thu Feb 19 13:35:21 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* ext/sdbm/_sdbm.c: include ruby/ruby.h for PRIdPTRDIFF when a
|
||||
|
|
32
string.c
32
string.c
|
@ -98,6 +98,9 @@ VALUE rb_cSymbol;
|
|||
|
||||
#define RESIZE_CAPA(str,capacity) do {\
|
||||
const int termlen = TERM_LEN(str);\
|
||||
RESIZE_CAPA_TERM(str,capacity,termlen);\
|
||||
} while (0)
|
||||
#define RESIZE_CAPA_TERM(str,capacity,termlen) do {\
|
||||
if (STR_EMBED_P(str)) {\
|
||||
if ((capacity) > RSTRING_EMBED_LEN_MAX) {\
|
||||
char *const tmp = ALLOC_N(char, (capacity)+termlen);\
|
||||
|
@ -1589,10 +1592,11 @@ str_make_independent_expand(VALUE str, long expand)
|
|||
|
||||
if (len > capa) len = capa;
|
||||
|
||||
if (capa <= RSTRING_EMBED_LEN_MAX && !STR_EMBED_P(str)) {
|
||||
if (capa + termlen - 1 <= RSTRING_EMBED_LEN_MAX && !STR_EMBED_P(str)) {
|
||||
ptr = RSTRING(str)->as.heap.ptr;
|
||||
STR_SET_EMBED(str);
|
||||
memcpy(RSTRING(str)->as.ary, ptr, len);
|
||||
TERM_FILL(RSTRING(str)->as.ary + len, termlen);
|
||||
STR_SET_EMBED_LEN(str, len);
|
||||
return;
|
||||
}
|
||||
|
@ -2166,23 +2170,30 @@ rb_str_resize(VALUE str, long len)
|
|||
static VALUE
|
||||
str_buf_cat(VALUE str, const char *ptr, long len)
|
||||
{
|
||||
long capa, total, off = -1;
|
||||
long capa, total, olen, off = -1;
|
||||
char *sptr;
|
||||
const int termlen = TERM_LEN(str);
|
||||
|
||||
if (ptr >= RSTRING_PTR(str) && ptr <= RSTRING_END(str)) {
|
||||
off = ptr - RSTRING_PTR(str);
|
||||
RSTRING_GETMEM(str, sptr, olen);
|
||||
if (ptr >= sptr && ptr <= sptr + olen) {
|
||||
off = ptr - sptr;
|
||||
}
|
||||
rb_str_modify(str);
|
||||
if (len == 0) return 0;
|
||||
if (STR_EMBED_P(str)) {
|
||||
capa = RSTRING_EMBED_LEN_MAX;
|
||||
sptr = RSTRING(str)->as.ary;
|
||||
olen = RSTRING_EMBED_LEN(str);
|
||||
}
|
||||
else {
|
||||
capa = RSTRING(str)->as.heap.aux.capa;
|
||||
sptr = RSTRING(str)->as.heap.ptr;
|
||||
olen = RSTRING(str)->as.heap.len;
|
||||
}
|
||||
if (RSTRING_LEN(str) >= LONG_MAX - len) {
|
||||
if (olen >= LONG_MAX - len) {
|
||||
rb_raise(rb_eArgError, "string sizes too big");
|
||||
}
|
||||
total = RSTRING_LEN(str)+len;
|
||||
total = olen + len;
|
||||
if (capa <= total) {
|
||||
while (total > capa) {
|
||||
if (capa > LONG_MAX / 2) {
|
||||
|
@ -2191,14 +2202,15 @@ str_buf_cat(VALUE str, const char *ptr, long len)
|
|||
}
|
||||
capa = 2 * capa;
|
||||
}
|
||||
RESIZE_CAPA(str, capa);
|
||||
RESIZE_CAPA_TERM(str, capa, termlen);
|
||||
sptr = RSTRING_PTR(str);
|
||||
}
|
||||
if (off != -1) {
|
||||
ptr = RSTRING_PTR(str) + off;
|
||||
ptr = sptr + off;
|
||||
}
|
||||
memcpy(RSTRING_PTR(str) + RSTRING_LEN(str), ptr, len);
|
||||
memcpy(sptr + olen, ptr, len);
|
||||
STR_SET_LEN(str, total);
|
||||
RSTRING_PTR(str)[total] = '\0'; /* sentinel */
|
||||
TERM_FILL(sptr + total, termlen); /* sentinel */
|
||||
|
||||
return str;
|
||||
}
|
||||
|
|
|
@ -86,6 +86,26 @@ class Test_StringCStr < Test::Unit::TestCase
|
|||
}
|
||||
end
|
||||
|
||||
def test_embedded_from_heap
|
||||
gh821 = "[GH-821]"
|
||||
embedded_string = "abcdefghi"
|
||||
string = embedded_string.gsub("efg", "123")
|
||||
{}[string] = 1
|
||||
non_terminated = "#{string}#{nil}"
|
||||
assert_nil(Bug::String.cstr_term_char(non_terminated), gh821)
|
||||
|
||||
result = {}
|
||||
WCHARS.map do |enc|
|
||||
embedded_string = "ab".encode(enc)
|
||||
string = embedded_string.gsub("b".encode(enc), "1".encode(enc))
|
||||
{}[string] = 1
|
||||
non_terminated = "#{string}#{nil}"
|
||||
c = Bug::String.cstr_term_char(non_terminated)
|
||||
result[enc] = c if c
|
||||
end
|
||||
assert_empty(result, gh821)
|
||||
end
|
||||
|
||||
def assert_wchars_term_char(str)
|
||||
result = {}
|
||||
WCHARS.map do |enc|
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#define RUBY_VERSION "2.2.0"
|
||||
#define RUBY_RELEASE_DATE "2015-02-19"
|
||||
#define RUBY_PATCHLEVEL 54
|
||||
#define RUBY_PATCHLEVEL 55
|
||||
|
||||
#define RUBY_RELEASE_YEAR 2015
|
||||
#define RUBY_RELEASE_MONTH 2
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue