string-ext.c: fix memory leak in `tr_parse_pattern`.
MODIFY
mrbgems/mruby-string-ext/src/string.c
mrbgems/mruby-string-ext/src/string.c
@@ -288,7 +288,7 @@ tr_free_pattern(mrb_state *mrb, struct tr_pattern *pat)
}
static struct tr_pattern*
-tr_parse_pattern(mrb_state *mrb, struct tr_pattern *ret, const mrb_value v_pattern, mrb_bool flag_reverse_enable)
+tr_parse_pattern(mrb_state *mrb, struct tr_pattern *ret, const mrb_value v_pattern, mrb_bool flag_reverse_enable, struct tr_pattern *pat0)
{
const char *pattern = RSTRING_PTR(v_pattern);
mrb_int pattern_length = RSTRING_LEN(v_pattern);
@@ -308,6 +308,7 @@ tr_parse_pattern(mrb_state *mrb, struct tr_pattern *ret, const mrb_value v_patte
? ret
: (struct tr_pattern*)mrb_malloc_simple(mrb, sizeof(struct tr_pattern));
if (pat1 == NULL) {
+ if (pat0) tr_free_pattern(mrb, pat0);
tr_free_pattern(mrb, ret);
mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
return NULL; /* not reached */
@@ -335,6 +336,7 @@ tr_parse_pattern(mrb_state *mrb, struct tr_pattern *ret, const mrb_value v_patte
len = i - start_pos;
if (len > UINT16_MAX) {
+ if (pat0) tr_free_pattern(mrb, pat0);
tr_free_pattern(mrb, ret);
if (ret != pat1) mrb_free(mrb, pat1);
mrb_raise(mrb, E_ARGUMENT_ERROR, "tr pattern too long (max 65535)");
@@ -482,18 +484,17 @@ static mrb_bool
str_tr(mrb_state *mrb, mrb_value str, mrb_value p1, mrb_value p2, mrb_bool squeeze)
{
struct tr_pattern pat = STATIC_TR_PATTERN;
- struct tr_pattern rep_storage = STATIC_TR_PATTERN;
+ struct tr_pattern rep = STATIC_TR_PATTERN;
char *s;
mrb_int len;
mrb_int i;
mrb_int j;
mrb_bool flag_changed = FALSE;
mrb_int lastch = -1;
- struct tr_pattern *rep;
mrb_str_modify(mrb, mrb_str_ptr(str));
- tr_parse_pattern(mrb, &pat, p1, TRUE);
- rep = tr_parse_pattern(mrb, &rep_storage, p2, FALSE);
+ tr_parse_pattern(mrb, &pat, p1, TRUE, NULL);
+ tr_parse_pattern(mrb, &rep, p2, FALSE, &pat);
s = RSTRING_PTR(str);
len = RSTRING_LEN(str);
@@ -503,11 +504,7 @@ str_tr(mrb_state *mrb, mrb_value str, mrb_value p1, mrb_value p2, mrb_bool squee
if (i>j) s[j] = s[i];
if (n >= 0) {
flag_changed = TRUE;
- if (rep == NULL) {
- j--;
- }
- else {
- mrb_int c = tr_get_character(rep, RSTRING_PTR(p2), n);
+ mrb_int c = tr_get_character(&rep, RSTRING_PTR(p2), n);
if (c < 0 || (squeeze && c == lastch)) {
j--;
@@ -515,17 +512,16 @@ str_tr(mrb_state *mrb, mrb_value str, mrb_value p1, mrb_value p2, mrb_bool squee
}
if (c > 0x80) {
tr_free_pattern(mrb, &pat);
- tr_free_pattern(mrb, rep);
+ tr_free_pattern(mrb, &rep);
mrb_raisef(mrb, E_ARGUMENT_ERROR, "character (%i) out of range", c);
}
lastch = c;
s[i] = (char)c;
}
}
- }
tr_free_pattern(mrb, &pat);
- tr_free_pattern(mrb, rep);
+ tr_free_pattern(mrb, &rep);
if (flag_changed) {
RSTR_SET_LEN(RSTRING(str), j);
@@ -658,7 +654,7 @@ str_squeeze(mrb_state *mrb, mrb_value str, mrb_value v_pat)
mrb_str_modify(mrb, mrb_str_ptr(str));
if (!mrb_nil_p(v_pat)) {
- pat = tr_parse_pattern(mrb, &pat_storage, v_pat, TRUE);
+ pat = tr_parse_pattern(mrb, &pat_storage, v_pat, TRUE, NULL);
tr_compile_pattern(pat, v_pat, bitmap);
tr_free_pattern(mrb, pat);
}
@@ -749,7 +745,7 @@ str_delete(mrb_state *mrb, mrb_value str, mrb_value v_pat)
uint8_t bitmap[32];
mrb_str_modify(mrb, mrb_str_ptr(str));
- tr_parse_pattern(mrb, &pat, v_pat, TRUE);
+ tr_parse_pattern(mrb, &pat, v_pat, TRUE, NULL);
tr_compile_pattern(&pat, v_pat, bitmap);
tr_free_pattern(mrb, &pat);
@@ -817,7 +813,7 @@ mrb_str_count(mrb_state *mrb, mrb_value str)
uint8_t bitmap[32];
mrb_get_args(mrb, "S", &v_pat);
- tr_parse_pattern(mrb, &pat, v_pat, TRUE);
+ tr_parse_pattern(mrb, &pat, v_pat, TRUE, NULL);
tr_compile_pattern(&pat, v_pat, bitmap);
tr_free_pattern(mrb, &pat);

string-ext.c: fix memory leak in `tr_parse_pattern`.