Skip to content

Commit 0c859ae

Browse files
tonycozmauke
authored andcommitted
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
1 parent a707dec commit 0c859ae

File tree

9 files changed

+73
-39
lines changed

9 files changed

+73
-39
lines changed

embed.fnc

+3-1
Original file line numberDiff line numberDiff line change
@@ -2791,6 +2791,9 @@ Cp |char * |re_intuit_start|NN REGEXP * const rx \
27912791
|NULLOK re_scream_pos_data *data
27922792
Cp |SV * |re_intuit_string \
27932793
|NN REGEXP * const r
2794+
2795+
p |void |release_RExC_state \
2796+
|NN void *vstate
27942797
Xp |REGEXP *|re_op_compile |NULLOK SV ** const patternp \
27952798
|int pat_count \
27962799
|NULLOK OP *expr \
@@ -2799,7 +2802,6 @@ Xp |REGEXP *|re_op_compile |NULLOK SV ** const patternp \
27992802
|NULLOK bool *is_bare_re \
28002803
|const U32 rx_flags \
28012804
|const U32 pm_flags
2802-
28032805
ATdp |void |repeatcpy |NN char *to \
28042806
|NN const char *from \
28052807
|SSize_t len \

embed.h

+1
Original file line numberDiff line numberDiff line change
@@ -1200,6 +1200,7 @@
12001200
# define refcounted_he_new_pv(a,b,c,d,e) Perl_refcounted_he_new_pv(aTHX_ a,b,c,d,e)
12011201
# define refcounted_he_new_pvn(a,b,c,d,e,f) Perl_refcounted_he_new_pvn(aTHX_ a,b,c,d,e,f)
12021202
# define refcounted_he_new_sv(a,b,c,d,e) Perl_refcounted_he_new_sv(aTHX_ a,b,c,d,e)
1203+
# define release_RExC_state(a) Perl_release_RExC_state(aTHX_ a)
12031204
# define report_evil_fh(a) Perl_report_evil_fh(aTHX_ a)
12041205
# define report_wrongway_fh(a,b) Perl_report_wrongway_fh(aTHX_ a,b)
12051206
# define rpeep(a) Perl_rpeep(aTHX_ a)

proto.h

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

regcomp.c

+11-5
Original file line numberDiff line numberDiff line change
@@ -1356,15 +1356,19 @@ S_is_ssc_worth_it(const RExC_state_t * pRExC_state, const regnode_ssc * ssc)
13561356
return true;
13571357
}
13581358

1359-
static void
1360-
release_RExC_state(pTHX_ void *vstate) {
1361-
RExC_state_t *pRExC_state = (RExC_state_t *)vstate;
1359+
#ifdef PERL_RE_BUILD_AUX
1360+
1361+
void
1362+
Perl_release_RExC_state(pTHX_ void *vstate) {
1363+
PERL_ARGS_ASSERT_RELEASE_REXC_STATE;
13621364

1365+
RExC_state_t *pRExC_state = (RExC_state_t *)vstate;
1366+
13631367
/* Any or all of these might be NULL.
13641368

13651369
There's no point in setting them to NULL after the free, since
13661370
pRExC_state is about to be released.
1367-
*/
1371+
*/
13681372
SvREFCNT_dec(RExC_rx_sv);
13691373
Safefree(RExC_open_parens);
13701374
Safefree(RExC_close_parens);
@@ -1374,6 +1378,8 @@ release_RExC_state(pTHX_ void *vstate) {
13741378
Safefree(pRExC_state);
13751379
}
13761380

1381+
#endif
1382+
13771383
/*
13781384
* Perl_re_op_compile - the perl internal RE engine's function to compile a
13791385
* regular expression into internal code.
@@ -1475,7 +1481,7 @@ Perl_re_op_compile(pTHX_ SV ** const patternp, int pat_count,
14751481
* or error. */
14761482
Newxz(pRExC_state, 1, RExC_state_t);
14771483

1478-
SAVEDESTRUCTOR_X(release_RExC_state, pRExC_state);
1484+
SAVE_FREE_REXC_STATE(pRExC_state);
14791485

14801486
DEBUG_r({
14811487
/* and then initialize RExC_mysv1 and RExC_mysv2 early so if

regen/scope_types.pl

+1
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ BEGIN
137137
SAVEt_FREEPADNAME
138138
SAVEt_STRLEN_SMALL
139139
SAVEt_FREERCPV
140+
SAVEt_FREE_REXC_STATE
140141
141142
/* two args */
142143

scope.c

+6
Original file line numberDiff line numberDiff line change
@@ -1391,6 +1391,12 @@ Perl_leave_scope(pTHX_ I32 base)
13911391
Safefree(a0.any_ptr);
13921392
break;
13931393

1394+
case SAVEt_FREE_REXC_STATE:
1395+
a0 = ap[0];
1396+
if (a0.any_ptr)
1397+
release_RExC_state(a0.any_ptr);
1398+
break;
1399+
13941400
case SAVEt_CLEARPADRANGE:
13951401
{
13961402
I32 i;

scope.h

+5
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,11 @@ scope has the given name. C<name> must be a literal string.
183183
#define SAVESETSVFLAGS(sv,mask,val) save_set_svflags(sv,mask,val)
184184
#define SAVEFREECOPHH(h) save_pushptr((void *)(h), SAVEt_FREECOPHH)
185185

186+
#if defined(PERL_CORE) || defined(PERL_EXT)
187+
# define SAVE_FREE_REXC_STATE(p) \
188+
save_pushptr((void *)(p), SAVEt_FREE_REXC_STATE)
189+
#endif
190+
186191
#define SAVEDELETE(h,k,l) \
187192
save_delete(MUTABLE_HV(h), (char*)(k), (I32)(l))
188193
#define SAVEHDELETE(h,s) \

scope_types.h

+35-33
Original file line numberDiff line numberDiff line change
@@ -44,44 +44,45 @@
4444
#define SAVEt_FREEPADNAME 23
4545
#define SAVEt_STRLEN_SMALL 24
4646
#define SAVEt_FREERCPV 25
47+
#define SAVEt_FREE_REXC_STATE 26
4748

4849
/* two args */
4950

50-
#define SAVEt_AV 26
51-
#define SAVEt_DESTRUCTOR 27
52-
#define SAVEt_DESTRUCTOR_X 28
53-
#define SAVEt_GENERIC_PVREF 29
54-
#define SAVEt_GENERIC_SVREF 30
55-
#define SAVEt_GP 31
56-
#define SAVEt_GVSV 32
57-
#define SAVEt_HINTS 33
58-
#define SAVEt_HPTR 34
59-
#define SAVEt_HV 35
60-
#define SAVEt_I32 36
61-
#define SAVEt_INT 37
62-
#define SAVEt_ITEM 38
63-
#define SAVEt_IV 39
64-
#define SAVEt_PPTR 40
65-
#define SAVEt_SAVESWITCHSTACK 41
66-
#define SAVEt_SHARED_PVREF 42
67-
#define SAVEt_SPTR 43
68-
#define SAVEt_STRLEN 44
69-
#define SAVEt_SV 45
70-
#define SAVEt_SVREF 46
71-
#define SAVEt_VPTR 47
72-
#define SAVEt_ADELETE 48
73-
#define SAVEt_APTR 49
74-
#define SAVEt_RCPV 50
51+
#define SAVEt_AV 27
52+
#define SAVEt_DESTRUCTOR 28
53+
#define SAVEt_DESTRUCTOR_X 29
54+
#define SAVEt_GENERIC_PVREF 30
55+
#define SAVEt_GENERIC_SVREF 31
56+
#define SAVEt_GP 32
57+
#define SAVEt_GVSV 33
58+
#define SAVEt_HINTS 34
59+
#define SAVEt_HPTR 35
60+
#define SAVEt_HV 36
61+
#define SAVEt_I32 37
62+
#define SAVEt_INT 38
63+
#define SAVEt_ITEM 39
64+
#define SAVEt_IV 40
65+
#define SAVEt_PPTR 41
66+
#define SAVEt_SAVESWITCHSTACK 42
67+
#define SAVEt_SHARED_PVREF 43
68+
#define SAVEt_SPTR 44
69+
#define SAVEt_STRLEN 45
70+
#define SAVEt_SV 46
71+
#define SAVEt_SVREF 47
72+
#define SAVEt_VPTR 48
73+
#define SAVEt_ADELETE 49
74+
#define SAVEt_APTR 50
75+
#define SAVEt_RCPV 51
7576

7677
/* three args */
7778

78-
#define SAVEt_HELEM 51
79-
#define SAVEt_PADSV_AND_MORTALIZE 52
80-
#define SAVEt_SET_SVFLAGS 53
81-
#define SAVEt_GVSLOT 54
82-
#define SAVEt_AELEM 55
83-
#define SAVEt_DELETE 56
84-
#define SAVEt_HINTS_HH 57
79+
#define SAVEt_HELEM 52
80+
#define SAVEt_PADSV_AND_MORTALIZE 53
81+
#define SAVEt_SET_SVFLAGS 54
82+
#define SAVEt_GVSLOT 55
83+
#define SAVEt_AELEM 56
84+
#define SAVEt_DELETE 57
85+
#define SAVEt_HINTS_HH 58
8586

8687
static const U8 leave_scope_arg_counts[] = {
8788
0, /* SAVEt_ALLOC */
@@ -110,6 +111,7 @@ static const U8 leave_scope_arg_counts[] = {
110111
1, /* SAVEt_FREEPADNAME */
111112
1, /* SAVEt_STRLEN_SMALL */
112113
1, /* SAVEt_FREERCPV */
114+
1, /* SAVEt_FREE_REXC_STATE */
113115
2, /* SAVEt_AV */
114116
2, /* SAVEt_DESTRUCTOR */
115117
2, /* SAVEt_DESTRUCTOR_X */
@@ -144,6 +146,6 @@ static const U8 leave_scope_arg_counts[] = {
144146
3 /* SAVEt_HINTS_HH */
145147
};
146148

147-
#define MAX_SAVEt 57
149+
#define MAX_SAVEt 58
148150

149151
/* ex: set ro ft=c: */

sv.c

+5
Original file line numberDiff line numberDiff line change
@@ -15515,6 +15515,11 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
1551515515
c = (char*)POPPTR(ss,ix);
1551615516
TOPPTR(nss,ix) = pv_dup_inc(c);
1551715517
break;
15518+
case SAVEt_FREE_REXC_STATE:
15519+
(void)POPPTR(ss, ix);
15520+
/* free only once */
15521+
TOPPTR(nss, ix) = NULL;
15522+
break;
1551815523
case SAVEt_FREERCPV:
1551915524
c = (char *)POPPTR(ss,ix);
1552015525
TOPPTR(nss,ix) = rcpv_copy(c);

0 commit comments

Comments
 (0)