Skip to content

Commit dabf343

Browse files
committed
regcomp.c - increase size of CURLY nodes so the min/max is a I32
This allows us to resolve a test inconsistency between CURLYX and CURLY and CURLYM, which have different maximums. We use I32 and not U32 because the existing count logic uses -1 internally and using an I32 for the min/max prevents warnings about comparing signed and unsigned values when the count is compared against the min or max.
1 parent cafd81a commit dabf343

File tree

5 files changed

+48
-36
lines changed

5 files changed

+48
-36
lines changed

regcomp.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4739,13 +4739,13 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
47394739
if (RExC_use_BRANCHJ) {
47404740
reginsert(pRExC_state, LONGJMP, ret, depth+1);
47414741
reginsert(pRExC_state, NOTHING, ret, depth+1);
4742-
NEXT_OFF(REGNODE_p(ret)) = 3; /* Go over LONGJMP. */
4742+
REGNODE_STEP_OVER(ret,tregnode_NOTHING,tregnode_LONGJMP,3);
47434743
}
47444744
reginsert(pRExC_state, CURLYX, ret, depth+1);
4745-
47464745
if (RExC_use_BRANCHJ)
4747-
NEXT_OFF(REGNODE_p(ret)) = 3; /* Go over NOTHING to
4748-
LONGJMP. */
4746+
/* Go over NOTHING to LONGJMP. */
4747+
REGNODE_STEP_OVER(ret,tregnode_CURLYX,tregnode_NOTHING,3);
4748+
47494749
if (! REGTAIL(pRExC_state, ret, reg_node(pRExC_state,
47504750
NOTHING)))
47514751
{
@@ -4758,8 +4758,8 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
47584758
/* Finish up the CURLY/CURLYX case */
47594759
FLAGS(REGNODE_p(ret)) = 0;
47604760

4761-
ARG1_SET(REGNODE_p(ret), (U16)min);
4762-
ARG2_SET(REGNODE_p(ret), (U16)max);
4761+
ARG1_SET(REGNODE_p(ret), min);
4762+
ARG2_SET(REGNODE_p(ret), max);
47634763

47644764
done_main_op:
47654765

regcomp.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -216,13 +216,13 @@ struct regnode_2L {
216216
I32 arg2;
217217
};
218218

219-
/* 'Two field' -- Two 16 bit unsigned args */
219+
/* 'Two field' -- Two 32 bit signed args */
220220
struct regnode_2 {
221221
U8 flags;
222222
U8 type;
223223
U16 next_off;
224-
U16 arg1;
225-
U16 arg2;
224+
I32 arg1;
225+
I32 arg2;
226226
};
227227

228228
#define REGNODE_BBM_BITMAP_LEN \
@@ -317,22 +317,22 @@ struct regnode_ssc {
317317
Impose a limit of REG_INFTY on various pattern matching operations
318318
to limit stack growth and to avoid "infinite" recursions.
319319
*/
320-
/* The default size for REG_INFTY is U16_MAX, which is the same as
321-
USHORT_MAX (see perl.h). Unfortunately U16 isn't necessarily 16 bits
322-
(see handy.h). On the Cray C90, sizeof(short)==4 and hence U16_MAX is
323-
((1<<32)-1), while on the Cray T90, sizeof(short)==8 and U16_MAX is
324-
((1<<64)-1). To limit stack growth to reasonable sizes, supply a
320+
/* The default size for REG_INFTY is I32_MAX, which is the same as UINT_MAX
321+
(see perl.h). Unfortunately I32 isn't necessarily 32 bits (see handy.h).
322+
On the Cray C90, or Cray T90, I32_MAX is considerably larger than it
323+
might be elsewhere. To limit stack growth to reasonable sizes, supply a
325324
smaller default.
326325
--Andy Dougherty 11 June 1998
326+
--Amended by Yves Orton 15 Jan 2023
327327
*/
328-
#if SHORTSIZE > 2
328+
#if INTSIZE > 4
329329
# ifndef REG_INFTY
330-
# define REG_INFTY nBIT_UMAX(16)
330+
# define REG_INFTY nBIT_IMAX(32)
331331
# endif
332332
#endif
333333

334334
#ifndef REG_INFTY
335-
# define REG_INFTY U16_MAX
335+
# define REG_INFTY I32_MAX
336336
#endif
337337

338338
#define ARG_VALUE(arg) (arg)

regcomp_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,5 +1245,7 @@ static const scan_data_t zero_scan_data = {
12451245
CLEAR_OPTSTART; \
12461246
node = dumpuntil(r,start,(b),(e),last,sv,indent+1,depth+1);
12471247

1248+
#define REGNODE_STEP_OVER(ret,t1,t2,k) \
1249+
NEXT_OFF(REGNODE_p(ret)) = ((sizeof(t1)+sizeof(t2))/sizeof(regnode))
12481250

12491251
#endif /* REGCOMP_INTERNAL_H */

t/re/pat.t

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -350,31 +350,36 @@ sub run_tests {
350350

351351
# Defaults assumed if this fails
352352
eval { require Config; };
353-
$::reg_infty = $Config::Config{reg_infty} // 65535;
353+
$::reg_infty = $Config::Config{reg_infty} // ((1<<31)-1);
354354
$::reg_infty_m = $::reg_infty - 1;
355355
$::reg_infty_p = $::reg_infty + 1;
356356
$::reg_infty_m = $::reg_infty_m; # Suppress warning.
357357

358358
# As well as failing if the pattern matches do unexpected things, the
359359
# next three tests will fail if you should have picked up a lower-than-
360360
# default value for $reg_infty from Config.pm, but have not.
361-
362-
is(eval q{('aaa' =~ /(a{1,$::reg_infty_m})/)[0]}, 'aaa', $message);
363-
is($@, '', $message);
364-
is(eval q{('a' x $::reg_infty_m) =~ /a{$::reg_infty_m}/}, 1, $message);
365-
is($@, '', $message);
366-
isnt(q{('a' x ($::reg_infty_m - 1)) !~ /a{$::reg_infty_m}/}, 1, $message);
367-
is($@, '', $message);
361+
SKIP: {
362+
skip "REG_INFTY too big to test ($::reg_infty)", 7
363+
if $::reg_infty > (1<<16);
364+
365+
is(eval q{('aaa' =~ /(a{1,$::reg_infty_m})/)[0]}, 'aaa', $message);
366+
is($@, '', $message);
367+
is(eval q{('a' x $::reg_infty_m) =~ /a{$::reg_infty_m}/}, 1, $message);
368+
is($@, '', $message);
369+
isnt(q{('a' x ($::reg_infty_m - 1)) !~ /a{$::reg_infty_m}/}, 1, $message);
370+
is($@, '', $message);
371+
372+
# It should be 'a' x 2147483647, but that exhausts memory on
373+
# reasonably sized modern machines
374+
like('a' x $::reg_infty_m, qr/a{1,}/,
375+
"{1,} matches more times than REG_INFTY");
376+
}
368377

369378
eval "'aaa' =~ /a{1,$::reg_infty}/";
370379
like($@, qr/^\QQuantifier in {,} bigger than/, $message);
371380
eval "'aaa' =~ /a{1,$::reg_infty_p}/";
372381
like($@, qr/^\QQuantifier in {,} bigger than/, $message);
373382

374-
# It should be 'a' x 2147483647, but that exhausts memory on
375-
# reasonably sized modern machines
376-
like('a' x $::reg_infty_p, qr/a{1,}/,
377-
"{1,} matches more times than REG_INFTY");
378383
}
379384

380385
{
@@ -393,12 +398,17 @@ sub run_tests {
393398

394399
for my $l (@trials) { # Ordered to free memory
395400
my $a = 'a' x $l;
396-
my $message = "Long monster, length = $l";
397-
like("ba$a=", qr/a$a=/, $message);
398-
unlike("b$a=", qr/a$a=/, $message);
399-
like("b$a=", qr/ba+=/, $message);
400-
401-
like("ba$a=", qr/b(?:a|b)+=/, $message);
401+
# we do not use like() or unlike() here as the string
402+
# is very long and is not useful if the match fails,
403+
# the useful part
404+
ok("ba$a=" =~ m/a$a=/, sprintf
405+
'Long monster: ("ba".("a" x %d)."=") =~ m/aa...a=/', $l);
406+
ok("b$a=" !~ m/a$a=/, sprintf
407+
'Long monster: ("b" .("a" x %d)."=") !~ m/aa...a=/', $l);
408+
ok("b$a=" =~ m/ba+=/, sprintf
409+
'Long monster: ("b" .("a" x %d)."=") =~ m/ba+=/', $l);
410+
ok("ba$a=" =~ m/b(?:a|b)+=/, sprintf
411+
'Long monster: ("ba".("a" x %d)."=") =~ m/b(?:a|b)+=/', $l);
402412
}
403413
}
404414

t/re/reg_mesg.t

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ sub mark_as_utf8 {
108108
return @ret;
109109
}
110110

111-
my $inf_m1 = ($Config::Config{reg_infty} || 65535) - 1;
111+
my $inf_m1 = ($Config::Config{reg_infty} || ((1<<31)-1)) - 1;
112112
my $inf_p1 = $inf_m1 + 2;
113113

114114
my $B_hex = sprintf("\\x%02X", ord "B");

0 commit comments

Comments
 (0)