summaryrefslogtreecommitdiffhomepage
path: root/src/string.c
diff options
context:
space:
mode:
authorMasamitsu MURASE <[email protected]>2012-06-28 01:01:56 +0900
committerMasamitsu MURASE <[email protected]>2012-06-30 21:42:10 +0900
commit866f797125093cca9563c753716e3cede1cc5a3f (patch)
tree976d08e1b95da5ad830fa6893b3fb58a10be688a /src/string.c
parent4bfd992284ee05148aaddfe98d69630353272288 (diff)
downloadmruby-866f797125093cca9563c753716e3cede1cc5a3f.tar.gz
mruby-866f797125093cca9563c753716e3cede1cc5a3f.zip
Fix str_replace in string.c
- Increment refcnt of shared string. - Free buffer before replacing. - Clear MRB_STR_SHARED after decref is called. - Fix target of aux.capa.
Diffstat (limited to 'src/string.c')
-rw-r--r--src/string.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/src/string.c b/src/string.c
index 8e61e6bb9..02f71ef96 100644
--- a/src/string.c
+++ b/src/string.c
@@ -1549,10 +1549,17 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
{
if (s2->flags & MRB_STR_SHARED) {
L_SHARE:
+ if (s1->flags & MRB_STR_SHARED){
+ mrb_str_decref(mrb, s1->aux.shared);
+ }
+ else {
+ mrb_free(mrb, s1->ptr);
+ }
s1->ptr = s2->ptr;
s1->len = s2->len;
s1->aux.shared = s2->aux.shared;
s1->flags |= MRB_STR_SHARED;
+ s1->aux.shared->refcnt++;
}
else if (s2->len > STR_REPLACE_SHARED_MIN) {
str_make_shared(mrb, s2);
@@ -1561,6 +1568,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
else {
if (s1->flags & MRB_STR_SHARED) {
mrb_str_decref(mrb, s1->aux.shared);
+ s1->flags &= ~MRB_STR_SHARED;
s1->ptr = mrb_malloc(mrb, s2->len+1);
}
else {
@@ -1569,7 +1577,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
memcpy(s1->ptr, s2->ptr, s2->len);
s1->ptr[s2->len] = 0;
s1->len = s2->len;
- s2->aux.capa = s2->len;
+ s1->aux.capa = s2->len;
}
return mrb_obj_value(s1);
}