summaryrefslogtreecommitdiff
path: root/string.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-09-12 06:27:15 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-09-12 06:27:15 +0000
commitb031fdbc0e58d5845b071e80efd5d7ee7595c82c (patch)
treef70ff5228f21a39538acd7d8d6b554c87f4c5d1a /string.c
parente78e79e10f37921c7fe82354d1caf9ad14f0fb57 (diff)
* dir.c (glob_helper): prevent memory leak using rb_protect().
* string.c (rb_str_associate): no need to check freeze flag. * string.c (rb_str_resize): should honor STR_ASSOC flag on resize. * string.c (rb_str_resize): proper STR_ASSOC handling. pointed out by Michal Rokos. * string.c (rb_str_buf_cat): ditto. * string.c (rb_str_cat): ditto. * string.c (rb_str_buf_append): ditto. * string.c (rb_str_append): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2856 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'string.c')
-rw-r--r--string.c134
1 files changed, 72 insertions, 62 deletions
diff --git a/string.c b/string.c
index 3149ad7..60d0cce 100644
--- a/string.c
+++ b/string.c
@@ -236,44 +236,10 @@ rb_str_shared_replace(str, str2)
RSTRING(str2)->ptr = 0; /* abandon str2 */
RSTRING(str2)->len = 0;
RSTRING(str2)->aux.capa = 0;
- FL_UNSET(str, ELTS_SHARED|STR_ASSOC);
+ FL_UNSET(str2, ELTS_SHARED|STR_ASSOC);
if (OBJ_TAINTED(str2)) OBJ_TAINT(str);
}
-void
-rb_str_associate(str, add)
- VALUE str, add;
-{
- if (FL_TEST(str, STR_ASSOC)) {
- /* already associated */
- rb_ary_concat(RSTRING(str)->aux.shared, add);
- }
- else {
- if (FL_TEST(str, ELTS_SHARED)) {
- rb_str_modify(str);
- }
- else if (RSTRING(str)->aux.shared) {
- /* str_buf */
- if (RSTRING(str)->aux.capa != RSTRING(str)->len) {
- RESIZE_CAPA(str, RSTRING(str)->len);
- }
- }
- RSTRING(str)->aux.shared = add;
- FL_UNSET(str, ELTS_SHARED);
- FL_SET(str, STR_ASSOC);
- }
-}
-
-VALUE
-rb_str_associated(str)
- VALUE str;
-{
- if (FL_TEST(str, STR_ASSOC)) {
- return RSTRING(str)->aux.shared;
- }
- return Qfalse;
-}
-
static ID id_to_s;
VALUE
@@ -433,6 +399,36 @@ rb_str_modify(str)
str_make_independent(str);
}
+void
+rb_str_associate(str, add)
+ VALUE str, add;
+{
+ if (FL_TEST(str, STR_ASSOC)) {
+ /* already associated */
+ rb_ary_concat(RSTRING(str)->aux.shared, add);
+ }
+ else {
+ if (FL_TEST(str, ELTS_SHARED)) {
+ str_make_independent(str);
+ }
+ else if (RSTRING(str)->aux.capa != RSTRING(str)->len) {
+ RESIZE_CAPA(str, RSTRING(str)->len);
+ }
+ RSTRING(str)->aux.shared = add;
+ FL_SET(str, STR_ASSOC);
+ }
+}
+
+VALUE
+rb_str_associated(str)
+ VALUE str;
+{
+ if (FL_TEST(str, STR_ASSOC)) {
+ return RSTRING(str)->aux.shared;
+ }
+ return Qfalse;
+}
+
VALUE
rb_string_value(ptr)
volatile VALUE *ptr;
@@ -514,9 +510,11 @@ rb_str_resize(str, len)
if (len != RSTRING(str)->len) {
rb_str_modify(str);
-
if (RSTRING(str)->len < len || RSTRING(str)->len - len > 1024) {
- RESIZE_CAPA(str, len);
+ REALLOC_N(RSTRING(str)->ptr, char, len+1);
+ if (!FL_TEST(str, STR_ASSOC)) {
+ RSTRING(str)->aux.capa = len;
+ }
}
RSTRING(str)->len = len;
RSTRING(str)->ptr[len] = '\0'; /* sentinel */
@@ -532,10 +530,18 @@ rb_str_buf_cat(str, ptr, len)
{
long capa, total;
- if (FL_TEST(str, ELTS_SHARED)) {
- rb_str_modify(str);
+ if (len == 0) return str;
+ if (len < 0) {
+ rb_raise(rb_eArgError, "negative string size (or size too big)");
+ }
+ rb_str_modify(str);
+ if (FL_TEST(str, STR_ASSOC)) {
+ FL_UNSET(str, STR_ASSOC);
+ capa = RSTRING(str)->aux.capa = RSTRING(str)->len;
+ }
+ else {
+ capa = RSTRING(str)->aux.capa;
}
- capa = RSTRING(str)->aux.capa;
total = RSTRING(str)->len+len;
if (capa <= total) {
while (total > capa) {
@@ -564,12 +570,12 @@ rb_str_cat(str, ptr, len)
const char *ptr;
long len;
{
- rb_str_modify(str);
- if (len > 0) {
- if (!FL_TEST(str, ELTS_SHARED) && !FL_TEST(str, STR_ASSOC)) {
- return rb_str_buf_cat(str, ptr, len);
- }
- RESIZE_CAPA(str, RSTRING(str)->len + len);
+ if (len < 0) {
+ rb_raise(rb_eArgError, "negative string size (or size too big)");
+ }
+ if (FL_TEST(str, STR_ASSOC)) {
+ rb_str_modify(str);
+ REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len+len);
if (ptr) {
memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len);
}
@@ -578,9 +584,10 @@ rb_str_cat(str, ptr, len)
}
RSTRING(str)->len += len;
RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */
+ return str;
}
- return str;
+ return rb_str_buf_cat(str, ptr, len);
}
VALUE
@@ -597,11 +604,14 @@ rb_str_buf_append(str, str2)
{
long capa, len;
- if (FL_TEST(str, ELTS_SHARED)) {
- rb_str_modify(str);
+ rb_str_modify(str);
+ if (FL_TEST(str, STR_ASSOC)) {
+ FL_UNSET(str, STR_ASSOC);
+ capa = RSTRING(str)->aux.capa = RSTRING(str)->len;
+ }
+ else {
+ capa = RSTRING(str)->aux.capa;
}
- capa = RSTRING(str)->aux.capa;
-
len = RSTRING(str)->len+RSTRING(str2)->len;
if (capa <= len) {
while (len > capa) {
@@ -613,6 +623,7 @@ rb_str_buf_append(str, str2)
RSTRING(str2)->ptr, RSTRING(str2)->len);
RSTRING(str)->len += RSTRING(str2)->len;
RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */
+ OBJ_INFECT(str, str2);
return str;
}
@@ -626,20 +637,19 @@ rb_str_append(str, str2)
StringValue(str2);
rb_str_modify(str);
if (RSTRING(str2)->len > 0) {
- len = RSTRING(str)->len+RSTRING(str2)->len;
- if (!FL_TEST(str, ELTS_SHARED) && !FL_TEST(str, STR_ASSOC)) {
- rb_str_buf_append(str, str2);
- OBJ_INFECT(str, str2);
- return str;
+ if (FL_TEST(str, STR_ASSOC)) {
+ len = RSTRING(str)->len+RSTRING(str2)->len;
+ REALLOC_N(RSTRING(str)->ptr, char, len+1);
+ memcpy(RSTRING(str)->ptr + RSTRING(str)->len,
+ RSTRING(str2)->ptr, RSTRING(str2)->len);
+ RSTRING(str)->ptr[len] = '\0'; /* sentinel */
+ RSTRING(str)->len = len;
+ }
+ else {
+ return rb_str_buf_append(str, str2);
}
- RESIZE_CAPA(str, len);
- memcpy(RSTRING(str)->ptr + RSTRING(str)->len,
- RSTRING(str2)->ptr, RSTRING(str2)->len);
- RSTRING(str)->len += RSTRING(str2)->len;
- RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */
}
OBJ_INFECT(str, str2);
-
return str;
}