Skip to content

Commit 3e449b6

Browse files
committed
ParseXS: make most ENABLE keywords stricter
These four keywords are supposed to have only ENABLE or DISABLE as their value: EXPORT_XSUB_SYMBOLS: SCOPE: VERSIONCHECK: PROTOTYPES: It turns out that the XS parser is very lax and allows all sorts of rubbish as the keyword's value. For example all these are valid, and the first of them was originally interpreted as *DISABLE*, due to case-insensitive validation, but case-sensitive value interpretation: KEYWORD: Enable KEYWORD: ENABLE; KEYWORD: ENABLE # comment KEYWORD: ENABLE the quick brown fox An earlier commit in this branch, in the course of refactoring, silently made the value matching to be case insensitive for *all* keywords (originally it was only CI for SCOPE). So originally, PROTOTYPES: Enable actually disabled prototypes; now it enables them. This commit and the next will restore the original behaviour and/or make things stricter. This commit makes all such keywords stricter, apart from PROTOTYPES, which is much more widely used (often incorrectly) and will require more careful backwards-compatibility handling. It's behaviour is left untouched by this commit; the next commit will update it. For the first three keywords, this commit makes the only acceptable values to match be /^(ENABLE|DISABLE)\s*$/.
1 parent 6d6660a commit 3e449b6

File tree

2 files changed

+79
-22
lines changed

2 files changed

+79
-22
lines changed

dist/ExtUtils-ParseXS/lib/ExtUtils/ParseXS/Node.pm

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3422,14 +3422,25 @@ sub parse {
34223422
$self->SUPER::parse($pxs); # set file/line_no, self->{text}
34233423
my $s = $self->{text};
34243424

3425-
#XXX note that for backwards compatibility, matching DIS/ENABLE is
3426-
#very lax: it is case insensitive, and ignores any trailing garbage
3427-
# on the line
3428-
unless ($s =~ /^(ENABLE|DISABLE)\b/i) {
3429-
my ($keyword) = ($self =~ /(\w+)=/); # final component of class name
3430-
$pxs->death("Error: $keyword: ENABLE/DISABLE")
3425+
my ($keyword) = ($self =~ /(\w+)=/); # final component of class name
3426+
3427+
if ($keyword eq 'PROTOTYPES') {
3428+
# XXX note that for backwards compatibility, parsing the PROTOTYPES
3429+
# keyword's value is very lax: it is case insensitive, and ignores
3430+
# any trailing garbage on the line
3431+
unless ($s =~ /^(ENABLE|DISABLE)\b/i) {
3432+
my ($keyword) = ($self =~ /(\w+)=/); # final component of class name
3433+
$pxs->death("Error: $keyword: ENABLE/DISABLE")
3434+
}
3435+
$self->{enable} = uc($1) eq 'ENABLE' ? 1 : 0;
3436+
}
3437+
else {
3438+
# SCOPE / VERSIONCHECK / EXPORT_XSUB_SYMBOLS
3439+
$s =~ /^(ENABLE|DISABLE)\s*$/
3440+
or $pxs->death("Error: $keyword: ENABLE/DISABLE");
3441+
$self->{enable} = $1 eq 'ENABLE' ? 1 : 0;
34313442
}
3432-
$self->{enable} = uc($1) eq 'ENABLE' ? 1 : 0;
3443+
34333444
1;
34343445
}
34353446

dist/ExtUtils-ParseXS/t/001-basic.t

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4279,18 +4279,32 @@ EOF
42794279
42804280
my @test_fns = (
42814281
[
4282-
"VERSIONCHECK long word",
4282+
"VERSIONCHECK: long word",
42834283
[ Q(<<'EOF') ],
42844284
|VERSIONCHECK: ENABLEblah
42854285
EOF
42864286
[ 1, 0, qr{Error: VERSIONCHECK: ENABLE/DISABLE}, "should die" ],
42874287
],
42884288
[
4289-
"VERSIONCHECK trailing text (stupid but legal)",
4289+
"VERSIONCHECK: trailing text",
42904290
[ Q(<<'EOF') ],
4291-
|VERSIONCHECK: diSAble blah # bloo +$%
4291+
|VERSIONCHECK: DISABLE blah # bloo +$%
42924292
EOF
4293-
[ 0, 0, qr{dXSARGS}, "boot fn generated" ],
4293+
[ 1, 0, qr{Error: VERSIONCHECK: ENABLE/DISABLE}, "should die" ],
4294+
],
4295+
[
4296+
"VERSIONCHECK: lower case",
4297+
[ Q(<<'EOF') ],
4298+
|VERSIONCHECK: disable
4299+
EOF
4300+
[ 1, 0, qr{Error: VERSIONCHECK: ENABLE/DISABLE}, "should die" ],
4301+
],
4302+
[
4303+
"VERSIONCHECK: semicolon",
4304+
[ Q(<<'EOF') ],
4305+
|VERSIONCHECK: DISABLE;
4306+
EOF
4307+
[ 1, 0, qr{Error: VERSIONCHECK: ENABLE/DISABLE}, "should die" ],
42944308
],
42954309
42964310
[
@@ -4316,19 +4330,35 @@ EOF
43164330
[ 1, 0, qr{Error: EXPORT_XSUB_SYMBOLS: ENABLE/DISABLE}, "should die" ],
43174331
],
43184332
[
4319-
"EXPORT_XSUB_SYMBOLS: trailing text (stupid but legal)",
4333+
"EXPORT_XSUB_SYMBOLS: trailing text",
43204334
[ Q(<<'EOF') ],
43214335
|EXPORT_XSUB_SYMBOLS: diSAble blah # bloo +$%
43224336
EOF
4323-
[ 0, 0, qr{dXSARGS}, "boot fn generated" ],
4337+
[ 1, 0, qr{Error: EXPORT_XSUB_SYMBOLS: ENABLE/DISABLE}, "should die" ],
4338+
],
4339+
[
4340+
"EXPORT_XSUB_SYMBOLS: lower case",
4341+
[ Q(<<'EOF') ],
4342+
|EXPORT_XSUB_SYMBOLS: disable
4343+
EOF
4344+
[ 1, 0, qr{Error: EXPORT_XSUB_SYMBOLS: ENABLE/DISABLE}, "should die" ],
43244345
],
43254346
43264347
[
4327-
"file SCOPE long word",
4348+
"file SCOPE: long word",
43284349
[ Q(<<'EOF') ],
43294350
|SCOPE: ENABLEblah
43304351
|void
43314352
|foo()
4353+
EOF
4354+
[ 1, 0, qr{Error: SCOPE: ENABLE/DISABLE}, "should die" ],
4355+
],
4356+
[
4357+
"file SCOPE: lower case",
4358+
[ Q(<<'EOF') ],
4359+
|SCOPE: enable
4360+
|void
4361+
|foo()
43324362
EOF
43334363
[ 1, 0, qr{Error: SCOPE: ENABLE/DISABLE}, "should die" ],
43344364
],
@@ -4358,30 +4388,46 @@ EOF
43584388
43594389
my @test_fns = (
43604390
[
4361-
"file SCOPE trailing text (stupid but legal)",
4391+
"file SCOPE: trailing text",
43624392
[ Q(<<'EOF') ],
43634393
|SCOPE: EnAble blah # bloo +$%
43644394
|void
43654395
|foo()
43664396
EOF
4367-
[ 0, 0, qr{ENTER;\s+{\s+\Qfoo();\E\s+}\s+LEAVE;},
4368-
"has ENTER/LEAVE" ],
4397+
[ 1, 0, qr{Error: SCOPE: ENABLE/DISABLE}, "should die" ],
43694398
],
43704399
[
4371-
"xsub SCOPE trailing text (stupid but legal)",
4400+
"xsub SCOPE: trailing text",
43724401
[ Q(<<'EOF') ],
43734402
|void
43744403
|foo()
43754404
|SCOPE: EnAble blah # bloo +$%
43764405
EOF
4377-
[ 0, 0, qr{ENTER;\s+{\s+\Qfoo();\E\s+}\s+LEAVE;},
4378-
"has ENTER/LEAVE" ],
4406+
[ 1, 0, qr{Error: SCOPE: ENABLE/DISABLE}, "should die" ],
4407+
],
4408+
[
4409+
"xsub SCOPE: lower case",
4410+
[ Q(<<'EOF') ],
4411+
|void
4412+
|foo()
4413+
|SCOPE: enable
4414+
EOF
4415+
[ 1, 0, qr{Error: SCOPE: ENABLE/DISABLE}, "should die" ],
4416+
],
4417+
[
4418+
"xsub SCOPE: semicolon",
4419+
[ Q(<<'EOF') ],
4420+
|void
4421+
|foo()
4422+
|SCOPE: ENABLE;
4423+
EOF
4424+
[ 1, 0, qr{Error: SCOPE: ENABLE/DISABLE}, "should die" ],
43794425
],
43804426
43814427
[
43824428
"SCOPE: as file-scoped keyword",
43834429
[ Q(<<'EOF') ],
4384-
|SCOPE: EnablE
4430+
|SCOPE: ENABLE
43854431
|void
43864432
|foo()
43874433
|C_ARGS: a,b,c
@@ -4395,7 +4441,7 @@ EOF
43954441
|void
43964442
|foo()
43974443
|C_ARGS: a,b,c
4398-
|SCOPE: EnablE
4444+
|SCOPE: ENABLE
43994445
EOF
44004446
[ 0, 0, qr{ENTER;\s+{\s+\Qfoo(a,b,c);\E\s+}\s+LEAVE;},
44014447
"has ENTER/LEAVE" ],

0 commit comments

Comments
 (0)