summaryrefslogtreecommitdiff
path: root/regcomp.c
diff options
context:
space:
mode:
Diffstat (limited to 'regcomp.c')
-rw-r--r--regcomp.c126
1 files changed, 103 insertions, 23 deletions
diff --git a/regcomp.c b/regcomp.c
index 94640639d8..38bfed5631 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -195,8 +195,7 @@ unset_addr_list_init(UnsetAddrList* uslist, int size)
static void
unset_addr_list_end(UnsetAddrList* uslist)
{
- if (IS_NOT_NULL(uslist->us))
- xfree(uslist->us);
+ xfree(uslist->us);
}
static int
@@ -341,7 +340,7 @@ static int
select_str_opcode(int mb_len, OnigDistance byte_len, int ignore_case)
{
int op;
- OnigDistance str_len = (byte_len + mb_len - 1) / mb_len;
+ OnigDistance str_len = roomof(byte_len, mb_len);
if (ignore_case) {
switch (str_len) {
@@ -1274,6 +1273,10 @@ compile_length_enclose_node(EncloseNode* node, regex_t* reg)
break;
case ENCLOSE_STOP_BACKTRACK:
+ /* Disable POP_STOP_BT optimization for simple repeat under the match cache */
+ /* optimization because the match cache optimization pushes an extra item to */
+ /* the stack and it breaks the assumption for this optimization. */
+#ifndef USE_MATCH_CACHE
if (IS_ENCLOSE_STOP_BT_SIMPLE_REPEAT(node)) {
QtfrNode* qn = NQTFR(node->target);
tlen = compile_length_tree(qn->target, reg);
@@ -1283,8 +1286,11 @@ compile_length_enclose_node(EncloseNode* node, regex_t* reg)
+ SIZE_OP_PUSH + tlen + SIZE_OP_POP + SIZE_OP_JUMP;
}
else {
+#endif
len = SIZE_OP_PUSH_STOP_BT + tlen + SIZE_OP_POP_STOP_BT;
+#ifndef USE_MATCH_CACHE
}
+#endif
break;
case ENCLOSE_CONDITION:
@@ -1396,6 +1402,10 @@ compile_enclose_node(EncloseNode* node, regex_t* reg)
break;
case ENCLOSE_STOP_BACKTRACK:
+ /* Disable POP_STOP_BT optimization for simple repeat under the match cache */
+ /* optimization because the match cache optimization pushes an extra item to */
+ /* the stack and it breaks the assumption for this optimization. */
+#ifndef USE_MATCH_CACHE
if (IS_ENCLOSE_STOP_BT_SIMPLE_REPEAT(node)) {
QtfrNode* qn = NQTFR(node->target);
r = compile_tree_n_times(qn->target, qn->lower, reg);
@@ -1414,12 +1424,15 @@ compile_enclose_node(EncloseNode* node, regex_t* reg)
-((int )SIZE_OP_PUSH + len + (int )SIZE_OP_POP + (int )SIZE_OP_JUMP));
}
else {
+#endif
r = add_opcode(reg, OP_PUSH_STOP_BT);
if (r) return r;
r = compile_tree(node->target, reg);
if (r) return r;
r = add_opcode(reg, OP_POP_STOP_BT);
+#ifndef USE_MATCH_CACHE
}
+#endif
break;
case ENCLOSE_CONDITION:
@@ -3382,7 +3395,7 @@ next_setup(Node* node, Node* next_node, regex_t* reg)
}
else if (type == NT_ENCLOSE) {
EncloseNode* en = NENCLOSE(node);
- if (en->type == ENCLOSE_MEMORY) {
+ if (en->type == ENCLOSE_MEMORY && !IS_ENCLOSE_CALLED(en)) {
node = en->target;
goto retry;
}
@@ -5483,10 +5496,8 @@ clear_optimize_info(regex_t* reg)
reg->sub_anchor = 0;
reg->exact_end = (UChar* )NULL;
reg->threshold_len = 0;
- if (IS_NOT_NULL(reg->exact)) {
- xfree(reg->exact);
- reg->exact = (UChar* )NULL;
- }
+ xfree(reg->exact);
+ reg->exact = (UChar* )NULL;
}
#ifdef ONIG_DEBUG
@@ -5649,12 +5660,12 @@ extern void
onig_free_body(regex_t* reg)
{
if (IS_NOT_NULL(reg)) {
- if (IS_NOT_NULL(reg->p)) xfree(reg->p);
- if (IS_NOT_NULL(reg->exact)) xfree(reg->exact);
- if (IS_NOT_NULL(reg->int_map)) xfree(reg->int_map);
- if (IS_NOT_NULL(reg->int_map_backward)) xfree(reg->int_map_backward);
- if (IS_NOT_NULL(reg->repeat_range)) xfree(reg->repeat_range);
- if (IS_NOT_NULL(reg->chain)) onig_free(reg->chain);
+ xfree(reg->p);
+ xfree(reg->exact);
+ xfree(reg->int_map);
+ xfree(reg->int_map_backward);
+ xfree(reg->repeat_range);
+ onig_free(reg->chain);
#ifdef USE_NAMED_GROUP
onig_names_free(reg);
@@ -5671,6 +5682,80 @@ onig_free(regex_t* reg)
}
}
+static void*
+dup_copy(const void *ptr, size_t size)
+{
+ void *newptr = xmalloc(size);
+ if (IS_NOT_NULL(newptr)) {
+ memcpy(newptr, ptr, size);
+ }
+ return newptr;
+}
+
+extern int
+onig_reg_copy(regex_t** nreg, regex_t* oreg)
+{
+ if (IS_NOT_NULL(oreg)) {
+ regex_t *reg = *nreg = (regex_t* )xmalloc(sizeof(regex_t));
+ if (IS_NULL(reg)) return ONIGERR_MEMORY;
+
+ *reg = *oreg;
+
+# define COPY_FAILED(mem, size) IS_NULL(reg->mem = dup_copy(reg->mem, size))
+
+ if (IS_NOT_NULL(reg->exact)) {
+ size_t exact_size = reg->exact_end - reg->exact;
+ if (COPY_FAILED(exact, exact_size))
+ goto err;
+ (reg)->exact_end = (reg)->exact + exact_size;
+ }
+
+ if (IS_NOT_NULL(reg->int_map)) {
+ if (COPY_FAILED(int_map, sizeof(int) * ONIG_CHAR_TABLE_SIZE))
+ goto err_int_map;
+ }
+ if (IS_NOT_NULL(reg->int_map_backward)) {
+ if (COPY_FAILED(int_map_backward, sizeof(int) * ONIG_CHAR_TABLE_SIZE))
+ goto err_int_map_backward;
+ }
+ if (IS_NOT_NULL(reg->p)) {
+ if (COPY_FAILED(p, reg->alloc))
+ goto err_p;
+ }
+ if (IS_NOT_NULL(reg->repeat_range)) {
+ if (COPY_FAILED(repeat_range, reg->repeat_range_alloc * sizeof(OnigRepeatRange)))
+ goto err_repeat_range;
+ }
+ if (IS_NOT_NULL(reg->name_table)) {
+ if (onig_names_copy(reg, oreg))
+ goto err_name_table;
+ }
+ if (IS_NOT_NULL(reg->chain)) {
+ if (onig_reg_copy(&reg->chain, reg->chain))
+ goto err_chain;
+ }
+ return 0;
+# undef COPY_FAILED
+
+ err_chain:
+ onig_names_free(reg);
+ err_name_table:
+ xfree(reg->repeat_range);
+ err_repeat_range:
+ xfree(reg->p);
+ err_p:
+ xfree(reg->int_map_backward);
+ err_int_map_backward:
+ xfree(reg->int_map);
+ err_int_map:
+ xfree(reg->exact);
+ err:
+ xfree(reg);
+ return ONIGERR_MEMORY;
+ }
+ return 0;
+}
+
#ifdef RUBY
size_t
onig_memsize(const regex_t *reg)
@@ -5927,8 +6012,8 @@ onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
}
onig_node_free(root);
- if (IS_NOT_NULL(scan_env.mem_nodes_dynamic))
- xfree(scan_env.mem_nodes_dynamic);
+ xfree(scan_env.mem_nodes_dynamic);
+
return r;
}
@@ -6000,20 +6085,15 @@ onig_new(regex_t** reg, const UChar* pattern, const UChar* pattern_end,
OnigOptionType option, OnigEncoding enc, const OnigSyntaxType* syntax,
OnigErrorInfo* einfo)
{
- int r;
-
*reg = (regex_t* )xmalloc(sizeof(regex_t));
if (IS_NULL(*reg)) return ONIGERR_MEMORY;
- r = onig_reg_init(*reg, option, ONIGENC_CASE_FOLD_DEFAULT, enc, syntax);
- if (r) goto err;
-
- r = onig_compile(*reg, pattern, pattern_end, einfo);
+ int r = onig_new_without_alloc(*reg, pattern, pattern_end, option, enc, syntax, einfo);
if (r) {
- err:
onig_free(*reg);
*reg = NULL;
}
+
return r;
}