From 56de8294fbda14d7c2a1248ecfd7b2a94c3b04f1 Mon Sep 17 00:00:00 2001 From: "Paul \"LeoNerd\" Evans" Date: Fri, 22 Nov 2024 21:00:44 +0000 Subject: [PATCH] Forbid use of any/all with a deferred expression; only accept BLOCK --- op.c | 18 ++++++++++++++++++ pod/perldiag.pod | 16 ++++++++++++++++ t/lib/croak/op | 14 ++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/op.c b/op.c index c669d3cd2f189..4b754388240c3 100644 --- a/op.c +++ b/op.c @@ -13228,6 +13228,24 @@ Perl_ck_grep(pTHX_ OP *o) Perl_croak(aTHX_ "panic: ck_grep, type=%u", (unsigned) kid->op_type); kid = kUNOP->op_first; + switch(o->op_type) { + case OP_ANYSTART: + case OP_ALLSTART: + /* any { BLOCK } would create an OP_NULL[OP_SCOPE[...]] or + * OP_NULL[OP_LEAVE[...]] here. If we don't see this structure + * then it must have been any EXPR, ... which we forbid + * TODO: See if we can forbid this somehow in perly.y itself + */ + if(!OP_TYPE_IS(kid, OP_NULL) || + !(OP_TYPE_IS(kUNOP->op_first, OP_SCOPE) || OP_TYPE_IS(kUNOP->op_first, OP_LEAVE))) { + /* diag_listed_as: any EXPR, LIST is not allowed */ + /* diag_listed_as: all EXPR, LIST is not allowed */ + croak("%s EXPR, LIST is not allowed", + o->op_type == OP_ANYSTART ? "any" : "all"); + } + break; + } + gwop = alloc_LOGOP(type, o, LINKLIST(kid)); kid->op_next = (OP*)gwop; o->op_private = gwop->op_private = 0; diff --git a/pod/perldiag.pod b/pod/perldiag.pod index c65ba5a8ef7cb..f4eda7115fc66 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -75,6 +75,14 @@ removed in a future Perl version: use feature "refaliasing"; \$x = \$y; +=item all EXPR, LIST is not allowed + +(F) An attempt was made to use the C keyword with a deferred expression, +which is permitted for C but not for C. You need to put the +expression in a block instead, as + + $result = all { EXPR } LIST; + =item all is experimental (S experimental::any_all) This warning is emitted if you use the C @@ -188,6 +196,14 @@ which 'splits' output into two streams, such as } close OUT; +=item any EXPR, LIST is not allowed + +(F) An attempt was made to use the C keyword with a deferred expression, +which is permitted for C but not for C. You need to put the +expression in a block instead, as + + $result = any { EXPR } LIST; + =item any is experimental (S experimental::any_all) This warning is emitted if you use the C diff --git a/t/lib/croak/op b/t/lib/croak/op index f24268c728173..1b22ab2fbaad1 100644 --- a/t/lib/croak/op +++ b/t/lib/croak/op @@ -326,3 +326,17 @@ use 5.012; use 5.010; EXPECT Downgrading a use VERSION declaration to below v5.11 is not permitted at - line 3. +######## +# any with deferred LIST expression +use feature 'any_all'; +no warnings 'experimental::any_all'; +any length, qw( a b c ) +EXPECT +any EXPR, LIST is not allowed at - line 4. +######## +# all with deferred LIST expression +use feature 'any_all'; +no warnings 'experimental::any_all'; +all length, qw( a b c ) +EXPECT +all EXPR, LIST is not allowed at - line 4.