CVE Patch Review

CVE-2026-52778: YesWiki CalcField Moves from eval() to Parser for RCE/ReDoS Mitigation

CVE-2026-52778 · Updated 2026-07-10 Root-cause

Summary

The 4.6.6 patch replaces regex-gated eval() execution in YesWiki Bazar CalcField with a dedicated tokenizer and recursive-descent evaluator backed by an allowlist of math functions. This directly addresses the two reported issues: unauthenticated remote code execution from evaluating attacker-controlled formulas and regex-driven denial of service from a recursive validation pattern. The patch materially improves security posture, though review should still confirm parser completeness, resource bounds, and behavioral compatibility across the full expression grammar.

Analysis

Vulnerability

CVE-2026-52778 describes unauthenticated remote code execution and denial of service in the YesWiki Bazar formula calculator. The vulnerable implementation in tools/bazar/fields/CalcField.php first attempted to validate formulas with a recursive regular expression and then executed the user-controlled expression with eval(). That combination is dangerous in two distinct ways.

First, using eval() on attacker-influenced input creates an RCE sink. Even if the input is prefiltered, the security boundary depends entirely on the correctness of the validator. Any bypass in the regex or parsing assumptions can turn formula input into executable PHP. Second, the validation regex itself is heavily recursive, which is consistent with catastrophic backtracking or stack exhaustion risks under crafted input, enabling ReDoS. The NVD and CVE records identify both impacts, and the referenced YesWiki commit removes the vulnerable pattern entirely: patch commit, CVE record.

$regexpToCheckIfMathFormula = '/^((' . $number . '|' . $functions . '\s*\((?1)+\)|\((?1)+\))(?:' . $operators . '(?1))?)+$/';
if (preg_match($regexpToCheckIfMathFormula, $formula)) {
    $formula = preg_replace('!pi|π!', 'pi()', $formula);
    try {
        eval("\$value = $formula;");
        $value = $value ?? 0;
    } catch (Throwable $th) {
    }
} else {
    $value = 'formula not correct !';
}

From a secure design perspective, the root problem is not merely insufficient validation; it is the use of a general-purpose code execution primitive for a domain that only requires arithmetic expression evaluation.

Patch

The patch in YesWiki 4.6.6 replaces the regex-plus-eval() model with a dedicated expression evaluator. The new code introduces an explicit allowlist of callable math functions, tokenizes the input formula, and parses it through recursive-descent methods such as parseAddSub(), parseMulDivMod(), and parsePower(). This is a structural change away from PHP code execution and away from recursive regex validation.

Key changes visible in the commit include:

  • Removal of the recursive validation regex.
  • Removal of eval() as the execution mechanism.
  • Addition of ALLOWED_FUNCTIONS to constrain callable operations.
  • Addition of tokenization logic for numbers, operators, names, and UTF-8 π.
  • Addition of parser state via $formulaTokens and $formulaPos.
  • Post-evaluation finite-value checking with is_finite().
private const ALLOWED_FUNCTIONS = [
    'sin' => 'sin', 'sinh' => 'sinh',
    'cos' => 'cos', 'cosh' => 'cosh',
    'tan' => 'tan', 'tanh' => 'tanh',
    'asin' => 'asin', 'asinh' => 'asinh',
    'acos' => 'acos', 'acosh' => 'acosh',
    'atan' => 'atan', 'atanh' => 'atanh',
    'abs' => 'abs', 'exp' => 'exp', 'log10' => 'log10',
    'deg2rad' => 'deg2rad', 'rad2deg' => 'rad2deg',
    'sqrt' => 'sqrt', 'ceil' => 'ceil', 'floor' => 'floor', 'round' => 'round',
];

private function evaluateFormula(string $formula): float
{
    $this->formulaTokens = $this->tokenizeFormula($formula);
    $this->formulaPos = 0;
    $result = $this->parseAddSub();
    if ($this->formulaPos < count($this->formulaTokens)) {
        throw new \RuntimeException('Unexpected token at position ' . $this->formulaPos);
    }
    return $result;
}

This patch is source-aligned with the vulnerability description because it removes both the code execution sink and the regex engine behavior that previously mediated formula acceptance. The implementation appears to constrain the language to arithmetic operators, numeric literals, parentheses, and named functions recognized by the allowlist, which is the correct security direction for a calculator feature. Source: YesWiki commit dd2bd8f.

Review

Pros

  • The patch removes eval(), which directly eliminates the primary RCE sink rather than trying to harden it indirectly.
  • The patch removes the recursive regex gate, which directly addresses the reported regex stack overflow / ReDoS class.
  • The new parser is explicit about accepted syntax and uses an allowlist for functions, reducing ambient attack surface.
  • Tokenization rejects unexpected characters early with exceptions, which is safer than permissive transformation.
  • The finite-value check after evaluation helps avoid propagating INF or NAN results into downstream logic.
  • The implementation is easier to reason about than a complex recursive regex plus dynamic PHP execution.

Cons

  • The parser is still recursive-descent code, so extremely deep nesting may still create resource pressure, even though the regex-engine-specific ReDoS vector is removed. The patch excerpt does not show explicit depth or token-count limits.
  • The review material is a partial diff. Full confidence depends on verifying function-call parsing, constant handling, unary operator behavior, exponent associativity, and all error paths in the complete file.
  • Returning 0 on exceptions or divide-by-zero conditions may mask malformed or adversarial input and could change application semantics compared with explicit validation errors.
  • The tokenizer accepts identifiers composed of alphanumerics and underscores; security depends on later enforcement that only ALLOWED_FUNCTIONS names are invocable and that bare names cannot escape into dynamic dispatch.
  • The patch addresses the calculator implementation shown, but broader assurance requires checking for any other formula evaluation paths in the codebase that may still rely on eval() or regex-heavy validation.

Verdict

Root-cause.

This patch appears to remediate the underlying design flaw by replacing general-purpose PHP evaluation with a purpose-built arithmetic parser and by removing the recursive regex validator implicated in ReDoS. Based on the provided commit and the vulnerability records, the fix is well aligned with both reported impacts in NVD and CVE.org. The remaining review focus should be on parser completeness, bounded resource consumption, and compatibility testing, not on whether the patch still relies on the original unsafe execution model.

Sources