Skip to content

FoldingWhiteSpace: CRLFAtTheEnd check is unreachable dead code #415

@ruttydm

Description

@ruttydm

Bug

In FoldingWhiteSpace::checkCRLFInFWS(), the CRLFAtTheEnd error can never be returned because the exact same condition is checked twice in sequence, with no lexer advancement between them.

Version: 4.0.4

Code

FoldingWhiteSpace.php lines 61–77:

protected function checkCRLFInFWS(): Result
{
    if (!$this->lexer->current->isA(EmailLexer::CRLF)) {
        return new ValidEmail();
    }

    if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) {
        return new InvalidEmail(new CRLFX2(), $this->lexer->current->value);
    }

    //this has no coverage. Condition is repeated from above one
    if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) {
        return new InvalidEmail(new CRLFAtTheEnd(), $this->lexer->current->value);
    }

    return new ValidEmail();
}

Analysis

isNextTokenAny() is read-only — it checks $this->lookahead without advancing the lexer position (confirmed in doctrine/lexer AbstractLexer::isNextTokenAny(), which only reads $this->lookahead->isA()). The only method that advances the lexer is moveNext().

Since both conditions on lines 67 and 72 check the same lookahead token with the same parameters:

  • If line 67 is true (next token is NOT SP/HTAB) → returns CRLFX2, never reaches line 72
  • If line 67 is false (next token IS SP/HTAB) → line 72 is also false, so CRLFAtTheEnd is never returned

The existing comment on line 71 confirms this: "this has no coverage. Condition is repeated from above one"

Impact

The CRLFAtTheEnd validation is dead — emails with CRLF at the end of folding whitespace that should be rejected with CRLFAtTheEnd are either rejected with the wrong reason (CRLFX2) or accepted as valid.

A moveNext() call was likely intended between the two checks to advance to the next token.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions