summaryrefslogtreecommitdiff
path: root/regexp.h
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2016-10-30 12:15:03 +0000
committerDavid Mitchell <davem@iabyn.com>2017-01-24 12:09:24 +0000
commit1acab4c5e64e8d27d6452f7758b159adf276d017 (patch)
tree9cccbd251fc88ed45dc8da01c67ba42348864e0c /regexp.h
parent64afbd292eada08042044fb6bc5a8dabf803ec53 (diff)
downloadperl-1acab4c5e64e8d27d6452f7758b159adf276d017.tar.gz
better handle freeing of code blocks in /(?{...})/
[perl #129140] attempting double-free Thus fixes some leaks and double frees in regexes which contain code blocks. During compilation, an array of struct reg_code_block's is malloced. Initially this is just attached to the RExC_state_t struct local var in Perl_re_op_compile(). Later it may be attached to a pattern. The difficulty is ensuring that the array is free()d (and the ref counts contained within decremented) should compilation croak early, while avoiding double frees once the array has been attached to a regex. The current mechanism of making the array the PVX of an SV is a bit flaky, as the array can be realloced(), and code can be re-entered when utf8 is detected mid-compilation. This commit changes the array into separately malloced head and body. The body contains the actual array, and can be realloced. The head contains a pointer to the array, plus size and an 'attached' boolean. This indicates whether the struct has been attached to a regex, and is effectively a 1-bit ref count. Whenever a head is allocated, SAVEDESTRUCTOR_X() is used to call S_free_codeblocks() to free the head and body on scope exit. This function skips the freeing if 'attached' is true, and this flag is set only at the point where the head gets attached to the regex. In one way this complicates the code, since the num_code_blocks field is now not always available (it's only there is a head has been allocated), but mainly its simplifies, since all the book-keeping is now done in the two new static functions S_alloc_code_blocks() and S_free_codeblocks()
Diffstat (limited to 'regexp.h')
-rw-r--r--regexp.h8
1 files changed, 8 insertions, 0 deletions
diff --git a/regexp.h b/regexp.h
index 08b4fc32a8..ed8c7fe8b4 100644
--- a/regexp.h
+++ b/regexp.h
@@ -85,6 +85,14 @@ struct reg_code_block {
REGEXP *src_regex;
};
+/* array of reg_code_block's plus header info */
+
+struct reg_code_blocks {
+ bool attached; /* we're attached to a regex (don't need freeing) */
+ int count; /* how many code blocks */
+ struct reg_code_block *cb; /* array of reg_code_block's */
+};
+
/*
The regexp/REGEXP struct, see L<perlreapi> for further documentation