Security Advisories (17)
CVE-2020-12723 (2020-06-05)

regcomp.c in Perl before 5.30.3 allows a buffer overflow via a crafted regular expression because of recursive S_study_chunk calls.

CVE-2020-10878 (2020-06-05)

Perl before 5.30.3 has an integer overflow related to mishandling of a "PL_regkind[OP(n)] == NOTHING" situation. A crafted regular expression could lead to malformed bytecode with a possibility of instruction injection.

CVE-2020-10543 (2020-06-05)

Perl before 5.30.3 on 32-bit platforms allows a heap-based buffer overflow because nested regular expression quantifiers have an integer overflow.

CVE-2018-6913 (2018-04-17)

Heap-based buffer overflow in the pack function in Perl before 5.26.2 allows context-dependent attackers to execute arbitrary code via a large item count.

CVE-2018-18314 (2018-12-07)

Perl before 5.26.3 has a buffer overflow via a crafted regular expression that triggers invalid write operations.

CVE-2018-18313 (2018-12-07)

Perl before 5.26.3 has a buffer over-read via a crafted regular expression that triggers disclosure of sensitive information from process memory.

CVE-2018-18312 (2018-12-05)

Perl before 5.26.3 and 5.28.0 before 5.28.1 has a buffer overflow via a crafted regular expression that triggers invalid write operations.

CVE-2018-18311 (2018-12-07)

Perl before 5.26.3 and 5.28.x before 5.28.1 has a buffer overflow via a crafted regular expression that triggers invalid write operations.

CVE-2015-8853 (2016-05-25)

The (1) S_reghop3, (2) S_reghop4, and (3) S_reghopmaybe3 functions in regexec.c in Perl before 5.24.0 allow context-dependent attackers to cause a denial of service (infinite loop) via crafted utf-8 data, as demonstrated by "a\x80."

CVE-2013-1667 (2013-03-14)

The rehash mechanism in Perl 5.8.2 through 5.16.x allows context-dependent attackers to cause a denial of service (memory consumption and crash) via a crafted hash key.

CVE-2016-2381 (2016-04-08)

Perl might allow context-dependent attackers to bypass the taint protection mechanism in a child process via duplicate environment variables in envp.

CVE-2013-7422 (2015-08-16)

Integer underflow in regcomp.c in Perl before 5.20, as used in Apple OS X before 10.10.5 and other products, allows context-dependent attackers to execute arbitrary code or cause a denial of service (application crash) via a long digit string associated with an invalid backreference within a regular expression.

CVE-2023-47100

In Perl before 5.38.2, S_parse_uniprop_string in regcomp.c can write to unallocated space because a property name associated with a \p{...} regular expression construct is mishandled. The earliest affected version is 5.30.0.

CVE-2023-47039 (2023-10-30)

Perl for Windows relies on the system path environment variable to find the shell (cmd.exe). When running an executable which uses Windows Perl interpreter, Perl attempts to find and execute cmd.exe within the operating system. However, due to path search order issues, Perl initially looks for cmd.exe in the current working directory. An attacker with limited privileges can exploit this behavior by placing cmd.exe in locations with weak permissions, such as C:\ProgramData. By doing so, when an administrator attempts to use this executable from these compromised locations, arbitrary code can be executed.

CVE-2025-40909 (2025-05-30)

Perl threads have a working directory race condition where file operations may target unintended paths. If a directory handle is open at thread creation, the process-wide current working directory is temporarily changed in order to clone that handle for the new thread, which is visible from any third (or more) thread already running. This may lead to unintended operations such as loading code or accessing files from unexpected locations, which a local attacker may be able to exploit. The bug was introduced in commit 11a11ecf4bea72b17d250cfb43c897be1341861e and released in Perl version 5.13.6

CVE-2015-8608 (2017-02-07)

The VDir::MapPathA and VDir::MapPathW functions in Perl 5.22 allow remote attackers to cause a denial of service (out-of-bounds read) and possibly execute arbitrary code via a crafted (1) drive letter or (2) pInName argument.

CVE-2016-1238 (2016-08-02)

(1) cpan/Archive-Tar/bin/ptar, (2) cpan/Archive-Tar/bin/ptardiff, (3) cpan/Archive-Tar/bin/ptargrep, (4) cpan/CPAN/scripts/cpan, (5) cpan/Digest-SHA/shasum, (6) cpan/Encode/bin/enc2xs, (7) cpan/Encode/bin/encguess, (8) cpan/Encode/bin/piconv, (9) cpan/Encode/bin/ucmlint, (10) cpan/Encode/bin/unidump, (11) cpan/ExtUtils-MakeMaker/bin/instmodsh, (12) cpan/IO-Compress/bin/zipdetails, (13) cpan/JSON-PP/bin/json_pp, (14) cpan/Test-Harness/bin/prove, (15) dist/ExtUtils-ParseXS/lib/ExtUtils/xsubpp, (16) dist/Module-CoreList/corelist, (17) ext/Pod-Html/bin/pod2html, (18) utils/c2ph.PL, (19) utils/h2ph.PL, (20) utils/h2xs.PL, (21) utils/libnetcfg.PL, (22) utils/perlbug.PL, (23) utils/perldoc.PL, (24) utils/perlivp.PL, and (25) utils/splain.PL in Perl 5.x before 5.22.3-RC2 and 5.24 before 5.24.1-RC2 do not properly remove . (period) characters from the end of the includes directory array, which might allow local users to gain privileges via a Trojan horse module under the current working directory.

NAME

TAP::Parser::Grammar - A grammar for the Test Anything Protocol.

VERSION

Version 3.26

SYNOPSIS

use TAP::Parser::Grammar;
my $grammar = $self->make_grammar({
  iterator => $tap_parser_iterator,
  parser   => $tap_parser,
  version  => 12,
});

my $result = $grammar->tokenize;

DESCRIPTION

TAP::Parser::Grammar tokenizes lines from a TAP::Parser::Iterator and constructs TAP::Parser::Result subclasses to represent the tokens.

Do not attempt to use this class directly. It won't make sense. It's mainly here to ensure that we will be able to have pluggable grammars when TAP is expanded at some future date (plus, this stuff was really cluttering the parser).

METHODS

Class Methods

new

my $grammar = TAP::Parser::Grammar->new({
    iterator => $iterator,
    parser   => $parser,
    version  => $version,
});

Returns TAP::Parser grammar object that will parse the TAP stream from the specified iterator. Both iterator and parser are required arguments. If version is not set it defaults to 12 (see "set_version" for more details).

Instance Methods

set_version

$grammar->set_version(13);

Tell the grammar which TAP syntax version to support. The lowest supported version is 12. Although 'TAP version' isn't valid version 12 syntax it is accepted so that higher version numbers may be parsed.

tokenize

my $token = $grammar->tokenize;

This method will return a TAP::Parser::Result object representing the current line of TAP.

token_types

my @types = $grammar->token_types;

Returns the different types of tokens which this grammar can parse.

syntax_for

my $syntax = $grammar->syntax_for($token_type);

Returns a pre-compiled regular expression which will match a chunk of TAP corresponding to the token type. For example (not that you should really pay attention to this, $grammar->syntax_for('comment') will return qr/^#(.*)/.

handler_for

my $handler = $grammar->handler_for($token_type);

Returns a code reference which, when passed an appropriate line of TAP, returns the lexed token corresponding to that line. As a result, the basic TAP parsing loop looks similar to the following:

my @tokens;
my $grammar = TAP::Grammar->new;
LINE: while ( defined( my $line = $parser->_next_chunk_of_tap ) ) {
    for my $type ( $grammar->token_types ) {
        my $syntax  = $grammar->syntax_for($type);
        if ( $line =~ $syntax ) {
            my $handler = $grammar->handler_for($type);
            push @tokens => $grammar->$handler($line);
            next LINE;
        }
    }
    push @tokens => $grammar->_make_unknown_token($line);
}

TAP GRAMMAR

NOTE: This grammar is slightly out of date. There's still some discussion about it and a new one will be provided when we have things better defined.

The TAP::Parser does not use a formal grammar because TAP is essentially a stream-based protocol. In fact, it's quite legal to have an infinite stream. For the same reason that we don't apply regexes to streams, we're not using a formal grammar here. Instead, we parse the TAP in lines.

For purposes for forward compatibility, any result which does not match the following grammar is currently referred to as TAP::Parser::Result::Unknown. It is not a parse error.

A formal grammar would look similar to the following:

(*
    For the time being, I'm cheating on the EBNF by allowing
    certain terms to be defined by POSIX character classes by
    using the following syntax:

      digit ::= [:digit:]

    As far as I am aware, that's not valid EBNF.  Sue me.  I
    didn't know how to write "char" otherwise (Unicode issues).
    Suggestions welcome.
*)

tap            ::= version? { comment | unknown } leading_plan lines
                   |
                   lines trailing_plan {comment}

version        ::= 'TAP version ' positiveInteger {positiveInteger} "\n"

leading_plan   ::= plan skip_directive? "\n"

trailing_plan  ::= plan "\n"

plan           ::= '1..' nonNegativeInteger

lines          ::= line {line}

line           ::= (comment | test | unknown | bailout ) "\n"

test           ::= status positiveInteger? description? directive?

status         ::= 'not '? 'ok '

description    ::= (character - (digit | '#')) {character - '#'}

directive      ::= todo_directive | skip_directive

todo_directive ::= hash_mark 'TODO' ' ' {character}

skip_directive ::= hash_mark 'SKIP' ' ' {character}

comment        ::= hash_mark {character}

hash_mark      ::= '#' {' '}

bailout        ::= 'Bail out!' {character}

unknown        ::= { (character - "\n") }

(* POSIX character classes and other terminals *)

digit              ::= [:digit:]
character          ::= ([:print:] - "\n")
positiveInteger    ::= ( digit - '0' ) {digit}
nonNegativeInteger ::= digit {digit}

SUBCLASSING

Please see "SUBCLASSING" in TAP::Parser for a subclassing overview.

If you really want to subclass TAP::Parser's grammar the best thing to do is read through the code. There's no easy way of summarizing it here.

SEE ALSO

TAP::Object, TAP::Parser, TAP::Parser::Iterator, TAP::Parser::Result,