Skip to content

Doubly nested parentheses in a selector throw "Recursion error detected" (e.g. li:not(:not(:nth-child(1)))) #120

Closed

Description

@gravitypdf-bot

Description of the bug

A selector whose parentheses nest two levels deep fails to parse, throwing a QueryPath\Exception from the CSS scanner instead of matching:

QueryPath\Exception: Recursion error detected at iteration 31.

Thrown from QueryPath\CSS\Scanner::nextToken() (src/CSS/Scanner.php), which raises it when the input stream is exhausted while $this->recurse is set.

It is not specific to :has(): any functional pseudo-class nested inside another one with its own parenthesised argument triggers it. One level of nesting, or two levels where the inner pseudo-class takes no argument, is fine.

Selector Result
li:not(:not(:nth-child(1))) throws
li:not(:not(:eq(0))) throws
li:not(:matches(:nth-child(1))) throws
ul:has(li:not(:nth-child(1))) throws
ul:not(:has(li:nth-child(3))) throws
li:not(:not(:first-child)) ok
ul:not(:has(li)) ok
ul:not(:nth-child(1)) ok

Both selector engines are affected (find() and remove() throw the same exception), which points at the shared scanner/parser rather than either engine.

Minimal reproducible PHP+HTML snippet to replicate bug

<?php
require __DIR__ . '/vendor/autoload.php';

$xml = '<?xml version="1.0"?><root><ul><li/><li/></ul></root>';

qp($xml)->find('li:not(:not(:nth-child(1)))');
// QueryPath\Exception: Recursion error detected at iteration 29.

QueryPath version

main at 95dbf53. Found while working on #84 / #119.

PHP Version and environment

PHP 8.5 CLI (macOS). Not version-specific as far as tested.

Related

:has() in the DOMTraverser engine also never matches, independently of this; see #121.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions