This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
better handle freeing of code blocks in /(?{...})/
authorDavid Mitchell <davem@iabyn.com>
Sun, 30 Oct 2016 12:15:03 +0000 (12:15 +0000)
committerDavid Mitchell <davem@iabyn.com>
Tue, 24 Jan 2017 12:09:24 +0000 (12:09 +0000)
commit1acab4c5e64e8d27d6452f7758b159adf276d017
tree9cccbd251fc88ed45dc8da01c67ba42348864e0c
parent64afbd292eada08042044fb6bc5a8dabf803ec53
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()
regcomp.c
regcomp.h
regexp.h
t/op/svleak.t
t/re/pat_re_eval.t