mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* string.c (str_gsub): use a string object for exception safeness.
[ruby-dev:24601] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7117 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
c7b31b0048
commit
ee51d0f9fd
2 changed files with 36 additions and 29 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
Wed Oct 27 09:17:30 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* string.c (str_gsub): use a string object for exception safeness.
|
||||||
|
[ruby-dev:24601]
|
||||||
|
|
||||||
Tue Oct 26 23:30:39 2004 Dave Thomas <dave@pragprog.com>
|
Tue Oct 26 23:30:39 2004 Dave Thomas <dave@pragprog.com>
|
||||||
|
|
||||||
* lib/rdoc/code_objects.rb (RDoc::Context::add_class_or_module):
|
* lib/rdoc/code_objects.rb (RDoc::Context::add_class_or_module):
|
||||||
|
|
58
string.c
58
string.c
|
@ -36,6 +36,17 @@ VALUE rb_cString;
|
||||||
|
|
||||||
VALUE rb_fs;
|
VALUE rb_fs;
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
str_mod_check(s, p, len)
|
||||||
|
VALUE s;
|
||||||
|
char *p;
|
||||||
|
long len;
|
||||||
|
{
|
||||||
|
if (RSTRING(s)->ptr != p || RSTRING(s)->len != len) {
|
||||||
|
rb_raise(rb_eRuntimeError, "string modified");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE str_alloc _((VALUE));
|
static VALUE str_alloc _((VALUE));
|
||||||
static VALUE
|
static VALUE
|
||||||
str_alloc(klass)
|
str_alloc(klass)
|
||||||
|
@ -2008,7 +2019,7 @@ str_gsub(argc, argv, str, bang)
|
||||||
VALUE str;
|
VALUE str;
|
||||||
int bang;
|
int bang;
|
||||||
{
|
{
|
||||||
VALUE pat, val, repl, match;
|
VALUE pat, val, repl, match, dest;
|
||||||
struct re_registers *regs;
|
struct re_registers *regs;
|
||||||
long beg, n;
|
long beg, n;
|
||||||
long offset, blen, len;
|
long offset, blen, len;
|
||||||
|
@ -2037,7 +2048,8 @@ str_gsub(argc, argv, str, bang)
|
||||||
}
|
}
|
||||||
|
|
||||||
blen = RSTRING(str)->len + 30; /* len + margin */
|
blen = RSTRING(str)->len + 30; /* len + margin */
|
||||||
buf = ALLOC_N(char, blen);
|
dest = rb_str_new5(str, 0, blen);
|
||||||
|
buf = RSTRING(dest)->ptr;
|
||||||
bp = buf;
|
bp = buf;
|
||||||
cp = RSTRING(str)->ptr;
|
cp = RSTRING(str)->ptr;
|
||||||
|
|
||||||
|
@ -2048,9 +2060,7 @@ str_gsub(argc, argv, str, bang)
|
||||||
if (iter) {
|
if (iter) {
|
||||||
rb_match_busy(match);
|
rb_match_busy(match);
|
||||||
val = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match)));
|
val = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match)));
|
||||||
if (RSTRING(str)->ptr == buf) {
|
str_mod_check(dest, buf, blen);
|
||||||
rb_raise(rb_eRuntimeError, "gsub reentered");
|
|
||||||
}
|
|
||||||
rb_backref_set(match);
|
rb_backref_set(match);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2061,7 +2071,9 @@ str_gsub(argc, argv, str, bang)
|
||||||
if (blen < len) {
|
if (blen < len) {
|
||||||
while (blen < len) blen *= 2;
|
while (blen < len) blen *= 2;
|
||||||
len = bp - buf;
|
len = bp - buf;
|
||||||
REALLOC_N(buf, char, blen);
|
RESIZE_CAPA(dest, blen);
|
||||||
|
RSTRING(dest)->len = blen;
|
||||||
|
buf = RSTRING(dest)->ptr;
|
||||||
bp = buf + len;
|
bp = buf + len;
|
||||||
}
|
}
|
||||||
len = beg - offset; /* copy pre-match substr */
|
len = beg - offset; /* copy pre-match substr */
|
||||||
|
@ -2087,30 +2099,32 @@ str_gsub(argc, argv, str, bang)
|
||||||
}
|
}
|
||||||
if (RSTRING(str)->len > offset) {
|
if (RSTRING(str)->len > offset) {
|
||||||
len = bp - buf;
|
len = bp - buf;
|
||||||
if (blen - len < RSTRING(str)->len - offset + 1) {
|
if (blen - len < RSTRING(str)->len - offset) {
|
||||||
REALLOC_N(buf, char, len + RSTRING(str)->len - offset + 1);
|
blen = len + RSTRING(str)->len - offset;
|
||||||
|
RESIZE_CAPA(dest, blen);
|
||||||
|
buf = RSTRING(dest)->ptr;
|
||||||
bp = buf + len;
|
bp = buf + len;
|
||||||
}
|
}
|
||||||
memcpy(bp, cp, RSTRING(str)->len - offset);
|
memcpy(bp, cp, RSTRING(str)->len - offset);
|
||||||
bp += RSTRING(str)->len - offset;
|
bp += RSTRING(str)->len - offset;
|
||||||
}
|
}
|
||||||
rb_backref_set(match);
|
rb_backref_set(match);
|
||||||
|
*bp = '\0';
|
||||||
if (bang) {
|
if (bang) {
|
||||||
if (str_independent(str)) {
|
if (str_independent(str)) {
|
||||||
free(RSTRING(str)->ptr);
|
free(RSTRING(str)->ptr);
|
||||||
}
|
}
|
||||||
FL_UNSET(str, ELTS_SHARED|STR_ASSOC);
|
FL_UNSET(str, ELTS_SHARED|STR_ASSOC);
|
||||||
|
RSTRING(str)->ptr = buf;
|
||||||
|
RSTRING(str)->aux.capa = blen;
|
||||||
|
RSTRING(dest)->ptr = 0;
|
||||||
|
RSTRING(dest)->len = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
VALUE dup = str_alloc(rb_obj_class(str));
|
OBJ_INFECT(dest, str);
|
||||||
|
str = dest;
|
||||||
OBJ_INFECT(dup, str);
|
|
||||||
str = dup;
|
|
||||||
}
|
}
|
||||||
RSTRING(str)->ptr = buf;
|
RSTRING(str)->len = bp - buf;
|
||||||
RSTRING(str)->len = len = bp - buf;
|
|
||||||
RSTRING(str)->ptr[len] = '\0';
|
|
||||||
RSTRING(str)->aux.capa = len;
|
|
||||||
|
|
||||||
if (tainted) OBJ_TAINT(str);
|
if (tainted) OBJ_TAINT(str);
|
||||||
return str;
|
return str;
|
||||||
|
@ -3592,18 +3606,6 @@ rb_f_split(argc, argv)
|
||||||
return rb_str_split_m(argc, argv, uscore_get());
|
return rb_str_split_m(argc, argv, uscore_get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
str_mod_check(s, p, len)
|
|
||||||
VALUE s;
|
|
||||||
char *p;
|
|
||||||
long len;
|
|
||||||
{
|
|
||||||
if (RSTRING(s)->ptr != p || RSTRING(s)->len != len) {
|
|
||||||
rb_raise(rb_eRuntimeError, "string modified");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* str.each(separator=$/) {|substr| block } => str
|
* str.each(separator=$/) {|substr| block } => str
|
||||||
|
|
Loading…
Reference in a new issue