mirror of
https://github.com/Perl/perl5.git
synced 2026-01-26 08:38:23 +00:00
regcomp: handle cloning the rexc cleanup in the scope stack
Previous on Win32 this could cause a double-free of the RExC state if an emulated fork was done with the free of the state on the scope stack. Use a custom save type and prevent freeing in the cloned process to prevent the double-free. Fixes #23022
This commit is contained in:
parent
a707dec8b1
commit
0c859ae7a5
@ -2791,6 +2791,9 @@ Cp |char * |re_intuit_start|NN REGEXP * const rx \
|
||||
|NULLOK re_scream_pos_data *data
|
||||
Cp |SV * |re_intuit_string \
|
||||
|NN REGEXP * const r
|
||||
|
||||
p |void |release_RExC_state \
|
||||
|NN void *vstate
|
||||
Xp |REGEXP *|re_op_compile |NULLOK SV ** const patternp \
|
||||
|int pat_count \
|
||||
|NULLOK OP *expr \
|
||||
@ -2799,7 +2802,6 @@ Xp |REGEXP *|re_op_compile |NULLOK SV ** const patternp \
|
||||
|NULLOK bool *is_bare_re \
|
||||
|const U32 rx_flags \
|
||||
|const U32 pm_flags
|
||||
|
||||
ATdp |void |repeatcpy |NN char *to \
|
||||
|NN const char *from \
|
||||
|SSize_t len \
|
||||
|
||||
1
embed.h
1
embed.h
@ -1200,6 +1200,7 @@
|
||||
# define refcounted_he_new_pv(a,b,c,d,e) Perl_refcounted_he_new_pv(aTHX_ a,b,c,d,e)
|
||||
# define refcounted_he_new_pvn(a,b,c,d,e,f) Perl_refcounted_he_new_pvn(aTHX_ a,b,c,d,e,f)
|
||||
# define refcounted_he_new_sv(a,b,c,d,e) Perl_refcounted_he_new_sv(aTHX_ a,b,c,d,e)
|
||||
# define release_RExC_state(a) Perl_release_RExC_state(aTHX_ a)
|
||||
# define report_evil_fh(a) Perl_report_evil_fh(aTHX_ a)
|
||||
# define report_wrongway_fh(a,b) Perl_report_wrongway_fh(aTHX_ a,b)
|
||||
# define rpeep(a) Perl_rpeep(aTHX_ a)
|
||||
|
||||
6
proto.h
generated
6
proto.h
generated
@ -3893,6 +3893,12 @@ PERL_CALLCONV void
|
||||
Perl_reginitcolors(pTHX);
|
||||
#define PERL_ARGS_ASSERT_REGINITCOLORS
|
||||
|
||||
PERL_CALLCONV void
|
||||
Perl_release_RExC_state(pTHX_ void *vstate)
|
||||
__attribute__visibility__("hidden");
|
||||
#define PERL_ARGS_ASSERT_RELEASE_REXC_STATE \
|
||||
assert(vstate)
|
||||
|
||||
PERL_CALLCONV void
|
||||
Perl_repeatcpy(char *to, const char *from, SSize_t len, IV count);
|
||||
#define PERL_ARGS_ASSERT_REPEATCPY \
|
||||
|
||||
16
regcomp.c
16
regcomp.c
@ -1356,15 +1356,19 @@ S_is_ssc_worth_it(const RExC_state_t * pRExC_state, const regnode_ssc * ssc)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
release_RExC_state(pTHX_ void *vstate) {
|
||||
RExC_state_t *pRExC_state = (RExC_state_t *)vstate;
|
||||
#ifdef PERL_RE_BUILD_AUX
|
||||
|
||||
void
|
||||
Perl_release_RExC_state(pTHX_ void *vstate) {
|
||||
PERL_ARGS_ASSERT_RELEASE_REXC_STATE;
|
||||
|
||||
RExC_state_t *pRExC_state = (RExC_state_t *)vstate;
|
||||
|
||||
/* Any or all of these might be NULL.
|
||||
|
||||
There's no point in setting them to NULL after the free, since
|
||||
pRExC_state is about to be released.
|
||||
*/
|
||||
*/
|
||||
SvREFCNT_dec(RExC_rx_sv);
|
||||
Safefree(RExC_open_parens);
|
||||
Safefree(RExC_close_parens);
|
||||
@ -1374,6 +1378,8 @@ release_RExC_state(pTHX_ void *vstate) {
|
||||
Safefree(pRExC_state);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Perl_re_op_compile - the perl internal RE engine's function to compile a
|
||||
* regular expression into internal code.
|
||||
@ -1475,7 +1481,7 @@ Perl_re_op_compile(pTHX_ SV ** const patternp, int pat_count,
|
||||
* or error. */
|
||||
Newxz(pRExC_state, 1, RExC_state_t);
|
||||
|
||||
SAVEDESTRUCTOR_X(release_RExC_state, pRExC_state);
|
||||
SAVE_FREE_REXC_STATE(pRExC_state);
|
||||
|
||||
DEBUG_r({
|
||||
/* and then initialize RExC_mysv1 and RExC_mysv2 early so if
|
||||
|
||||
@ -137,6 +137,7 @@ SAVEt_READONLY_OFF
|
||||
SAVEt_FREEPADNAME
|
||||
SAVEt_STRLEN_SMALL
|
||||
SAVEt_FREERCPV
|
||||
SAVEt_FREE_REXC_STATE
|
||||
|
||||
/* two args */
|
||||
|
||||
|
||||
6
scope.c
6
scope.c
@ -1391,6 +1391,12 @@ Perl_leave_scope(pTHX_ I32 base)
|
||||
Safefree(a0.any_ptr);
|
||||
break;
|
||||
|
||||
case SAVEt_FREE_REXC_STATE:
|
||||
a0 = ap[0];
|
||||
if (a0.any_ptr)
|
||||
release_RExC_state(a0.any_ptr);
|
||||
break;
|
||||
|
||||
case SAVEt_CLEARPADRANGE:
|
||||
{
|
||||
I32 i;
|
||||
|
||||
5
scope.h
5
scope.h
@ -183,6 +183,11 @@ scope has the given name. C<name> must be a literal string.
|
||||
#define SAVESETSVFLAGS(sv,mask,val) save_set_svflags(sv,mask,val)
|
||||
#define SAVEFREECOPHH(h) save_pushptr((void *)(h), SAVEt_FREECOPHH)
|
||||
|
||||
#if defined(PERL_CORE) || defined(PERL_EXT)
|
||||
# define SAVE_FREE_REXC_STATE(p) \
|
||||
save_pushptr((void *)(p), SAVEt_FREE_REXC_STATE)
|
||||
#endif
|
||||
|
||||
#define SAVEDELETE(h,k,l) \
|
||||
save_delete(MUTABLE_HV(h), (char*)(k), (I32)(l))
|
||||
#define SAVEHDELETE(h,s) \
|
||||
|
||||
@ -44,44 +44,45 @@
|
||||
#define SAVEt_FREEPADNAME 23
|
||||
#define SAVEt_STRLEN_SMALL 24
|
||||
#define SAVEt_FREERCPV 25
|
||||
#define SAVEt_FREE_REXC_STATE 26
|
||||
|
||||
/* two args */
|
||||
|
||||
#define SAVEt_AV 26
|
||||
#define SAVEt_DESTRUCTOR 27
|
||||
#define SAVEt_DESTRUCTOR_X 28
|
||||
#define SAVEt_GENERIC_PVREF 29
|
||||
#define SAVEt_GENERIC_SVREF 30
|
||||
#define SAVEt_GP 31
|
||||
#define SAVEt_GVSV 32
|
||||
#define SAVEt_HINTS 33
|
||||
#define SAVEt_HPTR 34
|
||||
#define SAVEt_HV 35
|
||||
#define SAVEt_I32 36
|
||||
#define SAVEt_INT 37
|
||||
#define SAVEt_ITEM 38
|
||||
#define SAVEt_IV 39
|
||||
#define SAVEt_PPTR 40
|
||||
#define SAVEt_SAVESWITCHSTACK 41
|
||||
#define SAVEt_SHARED_PVREF 42
|
||||
#define SAVEt_SPTR 43
|
||||
#define SAVEt_STRLEN 44
|
||||
#define SAVEt_SV 45
|
||||
#define SAVEt_SVREF 46
|
||||
#define SAVEt_VPTR 47
|
||||
#define SAVEt_ADELETE 48
|
||||
#define SAVEt_APTR 49
|
||||
#define SAVEt_RCPV 50
|
||||
#define SAVEt_AV 27
|
||||
#define SAVEt_DESTRUCTOR 28
|
||||
#define SAVEt_DESTRUCTOR_X 29
|
||||
#define SAVEt_GENERIC_PVREF 30
|
||||
#define SAVEt_GENERIC_SVREF 31
|
||||
#define SAVEt_GP 32
|
||||
#define SAVEt_GVSV 33
|
||||
#define SAVEt_HINTS 34
|
||||
#define SAVEt_HPTR 35
|
||||
#define SAVEt_HV 36
|
||||
#define SAVEt_I32 37
|
||||
#define SAVEt_INT 38
|
||||
#define SAVEt_ITEM 39
|
||||
#define SAVEt_IV 40
|
||||
#define SAVEt_PPTR 41
|
||||
#define SAVEt_SAVESWITCHSTACK 42
|
||||
#define SAVEt_SHARED_PVREF 43
|
||||
#define SAVEt_SPTR 44
|
||||
#define SAVEt_STRLEN 45
|
||||
#define SAVEt_SV 46
|
||||
#define SAVEt_SVREF 47
|
||||
#define SAVEt_VPTR 48
|
||||
#define SAVEt_ADELETE 49
|
||||
#define SAVEt_APTR 50
|
||||
#define SAVEt_RCPV 51
|
||||
|
||||
/* three args */
|
||||
|
||||
#define SAVEt_HELEM 51
|
||||
#define SAVEt_PADSV_AND_MORTALIZE 52
|
||||
#define SAVEt_SET_SVFLAGS 53
|
||||
#define SAVEt_GVSLOT 54
|
||||
#define SAVEt_AELEM 55
|
||||
#define SAVEt_DELETE 56
|
||||
#define SAVEt_HINTS_HH 57
|
||||
#define SAVEt_HELEM 52
|
||||
#define SAVEt_PADSV_AND_MORTALIZE 53
|
||||
#define SAVEt_SET_SVFLAGS 54
|
||||
#define SAVEt_GVSLOT 55
|
||||
#define SAVEt_AELEM 56
|
||||
#define SAVEt_DELETE 57
|
||||
#define SAVEt_HINTS_HH 58
|
||||
|
||||
static const U8 leave_scope_arg_counts[] = {
|
||||
0, /* SAVEt_ALLOC */
|
||||
@ -110,6 +111,7 @@ static const U8 leave_scope_arg_counts[] = {
|
||||
1, /* SAVEt_FREEPADNAME */
|
||||
1, /* SAVEt_STRLEN_SMALL */
|
||||
1, /* SAVEt_FREERCPV */
|
||||
1, /* SAVEt_FREE_REXC_STATE */
|
||||
2, /* SAVEt_AV */
|
||||
2, /* SAVEt_DESTRUCTOR */
|
||||
2, /* SAVEt_DESTRUCTOR_X */
|
||||
@ -144,6 +146,6 @@ static const U8 leave_scope_arg_counts[] = {
|
||||
3 /* SAVEt_HINTS_HH */
|
||||
};
|
||||
|
||||
#define MAX_SAVEt 57
|
||||
#define MAX_SAVEt 58
|
||||
|
||||
/* ex: set ro ft=c: */
|
||||
|
||||
5
sv.c
5
sv.c
@ -15515,6 +15515,11 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
|
||||
c = (char*)POPPTR(ss,ix);
|
||||
TOPPTR(nss,ix) = pv_dup_inc(c);
|
||||
break;
|
||||
case SAVEt_FREE_REXC_STATE:
|
||||
(void)POPPTR(ss, ix);
|
||||
/* free only once */
|
||||
TOPPTR(nss, ix) = NULL;
|
||||
break;
|
||||
case SAVEt_FREERCPV:
|
||||
c = (char *)POPPTR(ss,ix);
|
||||
TOPPTR(nss,ix) = rcpv_copy(c);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user