Skip to content

Infinite loop or segmentation fault on grammar with many binary operators #82

@Gismo359

Description

@Gismo359

ctpg::parser does not build properly with lots of binary operators. Depending on whether the parser is constexpr you see two results:

  • If yes, the compiler emits note: constexpr evaluation hit maximum step limit; possible infinite loop?. The stacktrace afterwards is different depending on how many operators I add, but it is always somewhere in sa.analyze_states().
  • If no, it will cause a segmentation fault/bus error when entering ctpg::parser's constructor because it is hitting the stack limit.

If I increase the stack size, then it will run and produce the correct result, but I have to make it absolutely huge (~1024x the default!):

ulimit -s 8388608

Default size:

ulimit -s
8192

Library version used:

❯ yay ctpg
1 aur/ctpg-git 1.3.7.r12.g0482730-1 (+0 0.00) (Installed: 1.3.7.r14.g624b4d1-1

Compiler used:

❯ clang++ --version
clang version 20.1.8
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

Example to reproduce:

#include <ctpg/ctpg.hpp>

constexpr ctpg::nterm<std::string> expr{"expr"};

static constexpr ctpg::parser p(
    expr,
    ctpg::terms(
        "+=",
        "-=",
        "*=",
        "/=",
        "<<=",
        ">>=",
        "<<",
        ">>",
        "<",
        ">",
        "<=",
        ">=",
        "==",
        "!=",
        "&",
        "|",
        "^",
        "&&",
        "||",
        "+",
        "-",
        "*",
        "/",
        "%",
        "x"
    ),
    ctpg::nterms(expr),
    ctpg::rules(
        expr(expr, "+=", expr) >>= std::identity{},
        expr(expr, "-=", expr) >>= std::identity{},
        expr(expr, "*=", expr) >>= std::identity{},
        expr(expr, "/=", expr) >>= std::identity{},
        expr(expr, "<<=", expr) >>= std::identity{},
        expr(expr, ">>=", expr) >>= std::identity{},
        expr(expr, "<<", expr) >>= std::identity{},
        expr(expr, ">>", expr) >>= std::identity{},
        expr(expr, "<", expr) >>= std::identity{},
        expr(expr, ">", expr) >>= std::identity{},
        expr(expr, "<=", expr) >>= std::identity{},
        expr(expr, ">=", expr) >>= std::identity{},
        expr(expr, "==", expr) >>= std::identity{},
        expr(expr, "!=", expr) >>= std::identity{},
        expr(expr, "&", expr) >>= std::identity{},
        expr(expr, "|", expr) >>= std::identity{},
        expr(expr, "^", expr) >>= std::identity{},
        expr(expr, "&&", expr) >>= std::identity{},
        expr(expr, "||", expr) >>= std::identity{},
        expr(expr, "+", expr) >>= std::identity{},
        expr(expr, "-", expr) >>= std::identity{},
        expr(expr, "*", expr) >>= std::identity{},
        expr(expr, "/", expr) >>= std::identity{},
        expr(expr, "%", expr) >>= std::identity{},
        expr("x") >>= std::identity{}
    )
);

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