summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2019-06-22 01:56:07 +0000
committernagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2019-06-22 01:56:07 +0000
commitf5022fcf06982ab54fbf32848e3ae6d3234f070d (patch)
tree60ee3de403ab86ac9768181271b4994d06290ea0
parentaccd7f69736c5eade1631f7b092cc96c2046725f (diff)
merge revision(s) 5e23b1138f16af0defb184d7deeffadfd2ce3c04: [Backport #15820]
Fix potential memory leak git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_6@67712 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--string.c49
-rw-r--r--version.h4
2 files changed, 34 insertions, 19 deletions
diff --git a/string.c b/string.c
index 855d594b84..156d124e59 100644
--- a/string.c
+++ b/string.c
@@ -6448,6 +6448,23 @@ typedef struct mapping_buffer {
OnigUChar space[FLEX_ARY_LEN];
} mapping_buffer;
+static void
+mapping_buffer_free(void *p)
+{
+ mapping_buffer *previous_buffer;
+ mapping_buffer *current_buffer = p;
+ while (current_buffer) {
+ previous_buffer = current_buffer;
+ current_buffer = current_buffer->next;
+ ruby_sized_xfree(previous_buffer, previous_buffer->capa);
+ }
+}
+
+static const rb_data_type_t mapping_buffer_type = {
+ "mapping_buffer",
+ {0, mapping_buffer_free,}
+};
+
static VALUE
rb_str_casemap(VALUE source, OnigCaseFoldType *flags, rb_encoding *enc)
{
@@ -6455,8 +6472,9 @@ rb_str_casemap(VALUE source, OnigCaseFoldType *flags, rb_encoding *enc)
OnigUChar *source_current, *source_end;
int target_length = 0;
- mapping_buffer pre_buffer, /* only next pointer used */
- *current_buffer = &pre_buffer;
+ VALUE buffer_anchor;
+ mapping_buffer *current_buffer = 0;
+ mapping_buffer **pre_buffer;
size_t buffer_count = 0;
int buffer_length_or_invalid;
@@ -6465,14 +6483,17 @@ rb_str_casemap(VALUE source, OnigCaseFoldType *flags, rb_encoding *enc)
source_current = (OnigUChar*)RSTRING_PTR(source);
source_end = (OnigUChar*)RSTRING_END(source);
+ buffer_anchor = TypedData_Wrap_Struct(0, &mapping_buffer_type, 0);
+ pre_buffer = (mapping_buffer **)&DATA_PTR(buffer_anchor);
while (source_current < source_end) {
/* increase multiplier using buffer count to converge quickly */
size_t capa = (size_t)(source_end-source_current)*++buffer_count + CASE_MAPPING_ADDITIONAL_LENGTH;
if (CASEMAP_DEBUG) {
fprintf(stderr, "Buffer allocation, capa is %"PRIuSIZE"\n", capa); /* for tuning */
}
- current_buffer->next = xmalloc(offsetof(mapping_buffer, space) + capa);
- current_buffer = current_buffer->next;
+ current_buffer = xmalloc(offsetof(mapping_buffer, space) + capa);
+ *pre_buffer = current_buffer;
+ pre_buffer = &current_buffer->next;
current_buffer->next = NULL;
current_buffer->capa = capa;
buffer_length_or_invalid = enc->case_map(flags,
@@ -6481,14 +6502,9 @@ rb_str_casemap(VALUE source, OnigCaseFoldType *flags, rb_encoding *enc)
current_buffer->space+current_buffer->capa,
enc);
if (buffer_length_or_invalid < 0) {
- mapping_buffer *previous_buffer;
-
- current_buffer = pre_buffer.next;
- while (current_buffer) {
- previous_buffer = current_buffer;
- current_buffer = current_buffer->next;
- ruby_sized_xfree(previous_buffer, previous_buffer->capa);
- }
+ current_buffer = DATA_PTR(buffer_anchor);
+ DATA_PTR(buffer_anchor) = 0;
+ mapping_buffer_free(current_buffer);
rb_raise(rb_eArgError, "input string invalid");
}
target_length += current_buffer->used = buffer_length_or_invalid;
@@ -6499,23 +6515,22 @@ rb_str_casemap(VALUE source, OnigCaseFoldType *flags, rb_encoding *enc)
if (buffer_count==1) {
target = rb_str_new_with_class(source, (const char*)current_buffer->space, target_length);
- ruby_sized_xfree(current_buffer, current_buffer->capa);
}
else {
char *target_current;
- mapping_buffer *previous_buffer;
target = rb_str_new_with_class(source, 0, target_length);
target_current = RSTRING_PTR(target);
- current_buffer=pre_buffer.next;
+ current_buffer = DATA_PTR(buffer_anchor);
while (current_buffer) {
memcpy(target_current, current_buffer->space, current_buffer->used);
target_current += current_buffer->used;
- previous_buffer = current_buffer;
current_buffer = current_buffer->next;
- ruby_sized_xfree(previous_buffer, previous_buffer->capa);
}
}
+ current_buffer = DATA_PTR(buffer_anchor);
+ DATA_PTR(buffer_anchor) = 0;
+ mapping_buffer_free(current_buffer);
/* TODO: check about string terminator character */
OBJ_INFECT_RAW(target, source);
diff --git a/version.h b/version.h
index b31b2676c4..6594e9c8b6 100644
--- a/version.h
+++ b/version.h
@@ -1,10 +1,10 @@
#define RUBY_VERSION "2.6.3"
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
-#define RUBY_PATCHLEVEL 64
+#define RUBY_PATCHLEVEL 65
#define RUBY_RELEASE_YEAR 2019
#define RUBY_RELEASE_MONTH 6
-#define RUBY_RELEASE_DAY 16
+#define RUBY_RELEASE_DAY 22
#include "ruby/version.h"