diff options
author | Adam Hess <[email protected]> | 2023-11-01 00:01:55 -0700 |
---|---|---|
committer | Peter Zhu <[email protected]> | 2023-11-08 08:05:58 -0500 |
commit | 05cde4155cd43a79733ab4996db2d8b1f64c4fb5 (patch) | |
tree | 72c44dc195827af20ff9b61a69dc62b62bece56f /regparse.c | |
parent | b4bf8c9ee2d716adf5fc08e67c4b26d6a8f929c2 (diff) |
fix regex from regex memory corruption
before this change, creating a regex from a regex with a named capture, Regexp.new(/(?<name>)/), causes memory to be shared between the two named capture groups which can cause a segfault if the original is GCed.
Diffstat (limited to 'regparse.c')
-rw-r--r-- | regparse.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/regparse.c b/regparse.c index 33480a66b8..f1c34a8f5c 100644 --- a/regparse.c +++ b/regparse.c @@ -275,7 +275,7 @@ onig_strcpy(UChar* dest, const UChar* src, const UChar* end) #ifdef USE_NAMED_GROUP static UChar* -strdup_with_null(OnigEncoding enc, UChar* s, UChar* end) +strdup_with_null(OnigEncoding enc, const UChar* s, const UChar* end) { ptrdiff_t slen; int term_len, i; @@ -551,12 +551,36 @@ onig_names_free(regex_t* reg) return 0; } +static int +copy_named_captures_iter(const OnigUChar *name, const OnigUChar *name_end, + int back_num, int *back_refs, OnigRegex regex, void *arg) +{ + NameTable *copy_table = (NameTable *)arg; + NameEntry *entry_copy = (NameEntry* )xmalloc(sizeof(NameEntry)); + + entry_copy->name_len = name_end - name; + entry_copy->back_num = back_num; + entry_copy->back_alloc = back_num; + entry_copy->back_ref1 = back_refs[0]; + entry_copy->back_refs = xmalloc(back_num * (sizeof(int*))); + for (int i = 0; i < back_num; i++) { + entry_copy->back_refs[i] = back_refs[i]; + } + + UChar *new_name = strdup_with_null(regex->enc, name, name_end); + entry_copy->name = new_name; + + onig_st_insert_strend(copy_table, new_name, (new_name + entry_copy->name_len), (hash_data_type)entry_copy); + return ST_CONTINUE; +} + extern int onig_names_copy(regex_t* reg, regex_t* oreg) { NameTable* table = oreg->name_table; if (table) { - NameTable* t = st_copy(table); + NameTable * t = onig_st_init_strend_table_with_size(onig_number_of_names(oreg)); + onig_foreach_name(oreg, copy_named_captures_iter, (void*)t); reg->name_table = t; } return 0; |