parse.y/directives: Reject directives as statements

Avoid the issue outlined in #2289 where the @if or @else is taken as the
statement of an `if`, `for` or `while` by rejecting such constructs.

Effectively this means the following scripts are now rejected:

    # Print's "cond true" with Zeek 5.0 even though the `if ( F )`
    # should be in effect.

    if ( F )
        @if ( T )
            print "cond true";
        @else
            print "cond false";
        @endif

or

    # Print's "hello" once with Zeek 5.0
    local v = vector( 1, 2, 3 );

    for ( i in v )
        @if ( T )
        print("hello")
        @endif

To make above work as intended, additional braces can be used.

    if ( T )
        {
    @if ( cond )
            print "cond true";
    @else
            print "cond false";
    @endif
        }

    for ( i in v )
        {
    @if ( T )
        print("hello")
    @endif
        }
This commit is contained in:
Arne Welzel 2022-08-23 18:45:22 +02:00
parent 6721248da5
commit 171846a37a
16 changed files with 124 additions and 2 deletions

View file

@ -1773,6 +1773,7 @@ stmt:
| TOK_IF '(' expr ')' stmt
{
reject_directive($5);
set_location(@1, @4);
$$ = new IfStmt({AdoptRef{}, $3}, {AdoptRef{}, $5}, make_intrusive<NullStmt>());
script_coverage_mgr.AddStmt($$);
@ -1780,6 +1781,8 @@ stmt:
| TOK_IF '(' expr ')' stmt TOK_ELSE stmt
{
reject_directive($5);
reject_directive($7);
set_location(@1, @4);
$$ = new IfStmt({AdoptRef{}, $3}, {AdoptRef{}, $5}, {AdoptRef{}, $7});
script_coverage_mgr.AddStmt($$);
@ -1794,12 +1797,14 @@ stmt:
| for_head stmt
{
reject_directive($2);
$1->AsForStmt()->AddBody({AdoptRef{}, $2});
script_coverage_mgr.AddStmt($1);
}
| TOK_WHILE '(' expr ')' stmt
{
reject_directive($5);
$$ = new WhileStmt({AdoptRef{}, $3}, {AdoptRef{}, $5});
script_coverage_mgr.AddStmt($$);
}
@ -1906,7 +1911,7 @@ stmt:
}
| conditional
{ $$ = new NullStmt; }
{ $$ = new NullStmt(true /* is_directive */); }
;
stmt_list: