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

parent 0fbdd71d
...@@ -288,7 +288,7 @@ tr_free_pattern(mrb_state *mrb, struct tr_pattern *pat) ...@@ -288,7 +288,7 @@ tr_free_pattern(mrb_state *mrb, struct tr_pattern *pat)
} }
static struct tr_pattern* 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); const char *pattern = RSTRING_PTR(v_pattern);
mrb_int pattern_length = RSTRING_LEN(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 ...@@ -308,6 +308,7 @@ tr_parse_pattern(mrb_state *mrb, struct tr_pattern *ret, const mrb_value v_patte
? ret ? ret
: (struct tr_pattern*)mrb_malloc_simple(mrb, sizeof(struct tr_pattern)); : (struct tr_pattern*)mrb_malloc_simple(mrb, sizeof(struct tr_pattern));
if (pat1 == NULL) { if (pat1 == NULL) {
if (pat0) tr_free_pattern(mrb, pat0);
tr_free_pattern(mrb, ret); tr_free_pattern(mrb, ret);
mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err)); mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
return NULL; /* not reached */ return NULL; /* not reached */
...@@ -335,6 +336,7 @@ tr_parse_pattern(mrb_state *mrb, struct tr_pattern *ret, const mrb_value v_patte ...@@ -335,6 +336,7 @@ tr_parse_pattern(mrb_state *mrb, struct tr_pattern *ret, const mrb_value v_patte
len = i - start_pos; len = i - start_pos;
if (len > UINT16_MAX) { if (len > UINT16_MAX) {
if (pat0) tr_free_pattern(mrb, pat0);
tr_free_pattern(mrb, ret); tr_free_pattern(mrb, ret);
if (ret != pat1) mrb_free(mrb, pat1); if (ret != pat1) mrb_free(mrb, pat1);
mrb_raise(mrb, E_ARGUMENT_ERROR, "tr pattern too long (max 65535)"); mrb_raise(mrb, E_ARGUMENT_ERROR, "tr pattern too long (max 65535)");
...@@ -482,18 +484,17 @@ static mrb_bool ...@@ -482,18 +484,17 @@ static mrb_bool
str_tr(mrb_state *mrb, mrb_value str, mrb_value p1, mrb_value p2, mrb_bool squeeze) 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 pat = STATIC_TR_PATTERN;
struct tr_pattern rep_storage = STATIC_TR_PATTERN; struct tr_pattern rep = STATIC_TR_PATTERN;
char *s; char *s;
mrb_int len; mrb_int len;
mrb_int i; mrb_int i;
mrb_int j; mrb_int j;
mrb_bool flag_changed = FALSE; mrb_bool flag_changed = FALSE;
mrb_int lastch = -1; mrb_int lastch = -1;
struct tr_pattern *rep;
mrb_str_modify(mrb, mrb_str_ptr(str)); mrb_str_modify(mrb, mrb_str_ptr(str));
tr_parse_pattern(mrb, &pat, p1, TRUE); tr_parse_pattern(mrb, &pat, p1, TRUE, NULL);
rep = tr_parse_pattern(mrb, &rep_storage, p2, FALSE); tr_parse_pattern(mrb, &rep, p2, FALSE, &pat);
s = RSTRING_PTR(str); s = RSTRING_PTR(str);
len = RSTRING_LEN(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 ...@@ -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 (i>j) s[j] = s[i];
if (n >= 0) { if (n >= 0) {
flag_changed = TRUE; flag_changed = TRUE;
if (rep == NULL) { mrb_int c = tr_get_character(&rep, RSTRING_PTR(p2), n);
j--;
}
else {
mrb_int c = tr_get_character(rep, RSTRING_PTR(p2), n);
if (c < 0 || (squeeze && c == lastch)) { if (c < 0 || (squeeze && c == lastch)) {
j--; j--;
...@@ -515,17 +512,16 @@ str_tr(mrb_state *mrb, mrb_value str, mrb_value p1, mrb_value p2, mrb_bool squee ...@@ -515,17 +512,16 @@ str_tr(mrb_state *mrb, mrb_value str, mrb_value p1, mrb_value p2, mrb_bool squee
} }
if (c > 0x80) { if (c > 0x80) {
tr_free_pattern(mrb, &pat); 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); mrb_raisef(mrb, E_ARGUMENT_ERROR, "character (%i) out of range", c);
} }
lastch = c; lastch = c;
s[i] = (char)c; s[i] = (char)c;
} }
} }
}
tr_free_pattern(mrb, &pat); tr_free_pattern(mrb, &pat);
tr_free_pattern(mrb, rep); tr_free_pattern(mrb, &rep);
if (flag_changed) { if (flag_changed) {
RSTR_SET_LEN(RSTRING(str), j); RSTR_SET_LEN(RSTRING(str), j);
...@@ -658,7 +654,7 @@ str_squeeze(mrb_state *mrb, mrb_value str, mrb_value v_pat) ...@@ -658,7 +654,7 @@ str_squeeze(mrb_state *mrb, mrb_value str, mrb_value v_pat)
mrb_str_modify(mrb, mrb_str_ptr(str)); mrb_str_modify(mrb, mrb_str_ptr(str));
if (!mrb_nil_p(v_pat)) { 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_compile_pattern(pat, v_pat, bitmap);
tr_free_pattern(mrb, pat); tr_free_pattern(mrb, pat);
} }
...@@ -749,7 +745,7 @@ str_delete(mrb_state *mrb, mrb_value str, mrb_value v_pat) ...@@ -749,7 +745,7 @@ str_delete(mrb_state *mrb, mrb_value str, mrb_value v_pat)
uint8_t bitmap[32]; uint8_t bitmap[32];
mrb_str_modify(mrb, mrb_str_ptr(str)); 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_compile_pattern(&pat, v_pat, bitmap);
tr_free_pattern(mrb, &pat); tr_free_pattern(mrb, &pat);
...@@ -817,7 +813,7 @@ mrb_str_count(mrb_state *mrb, mrb_value str) ...@@ -817,7 +813,7 @@ mrb_str_count(mrb_state *mrb, mrb_value str)
uint8_t bitmap[32]; uint8_t bitmap[32];
mrb_get_args(mrb, "S", &v_pat); 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_compile_pattern(&pat, v_pat, bitmap);
tr_free_pattern(mrb, &pat); tr_free_pattern(mrb, &pat);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment