@@ -165,8 +165,9 @@ SourceRange SourceRangeFromParserRuleContext(
165165
166166class ParserMacroExprFactory final : public MacroExprFactory {
167167 public:
168- explicit ParserMacroExprFactory (const cel::Source& source)
169- : source_(source) {}
168+ explicit ParserMacroExprFactory (const cel::Source& source,
169+ int expression_node_limit)
170+ : source_(source), expression_node_limit_(expression_node_limit) {}
170171
171172 void BeginMacro (SourceRange macro_position) {
172173 macro_position_ = macro_position;
@@ -203,12 +204,18 @@ class ParserMacroExprFactory final : public MacroExprFactory {
203204
204205 int64_t NextId (const SourceRange& range) {
205206 auto id = expr_id_++;
207+ if (id > expression_node_limit_ && !node_limit_exceeded_) {
208+ node_limit_exceeded_ = true ;
209+ ReportError (range, " expression node limit exceeded" );
210+ }
206211 if (range.begin != -1 || range.end != -1 ) {
207212 positions_.insert (std::pair{id, range});
208213 }
209214 return id;
210215 }
211216
217+ bool is_node_limit_exceeded () const { return node_limit_exceeded_; }
218+
212219 bool HasErrors () const { return error_count_ != 0 ; }
213220
214221 std::vector<cel::ParseIssue> CollectIssues () {
@@ -409,6 +416,8 @@ class ParserMacroExprFactory final : public MacroExprFactory {
409416 std::vector<ParserError> errors_;
410417 size_t error_count_ = 0 ;
411418 const Source& source_;
419+ int expression_node_limit_;
420+ bool node_limit_exceeded_ = false ;
412421 SourceRange macro_position_;
413422};
414423
@@ -623,13 +632,14 @@ class ParserVisitor final : public CelBaseVisitor,
623632 public antlr4::BaseErrorListener {
624633 public:
625634 ParserVisitor (const cel::Source& source, int max_recursion_depth,
635+ int max_expression_node_count,
626636 const cel::MacroRegistry& macro_registry,
627637 bool add_macro_calls = false ,
628638 bool enable_optional_syntax = false ,
629639 bool enable_quoted_identifiers = false ,
630640 bool enable_variadic_logical_operators = false )
631641 : source_(source),
632- factory_ (source_),
642+ factory_ (source_, max_expression_node_count ),
633643 macro_registry_(macro_registry),
634644 recursion_depth_(0 ),
635645 max_recursion_depth_(max_recursion_depth),
@@ -1227,6 +1237,8 @@ std::vector<ListExprElement> ParserVisitor::visitList(
12271237 if (!enable_optional_syntax_ && expr_ctx->opt != nullptr ) {
12281238 factory_.ReportError (SourceRangeFromParserRuleContext (ctx),
12291239 " unsupported syntax '?'" );
1240+ // Still generate an ID to detect node limit exceeded.
1241+ factory_.NextId (SourceRangeFromParserRuleContext (ctx));
12301242 rv.push_back (factory_.NewListElement (factory_.NewUnspecified (0 ), false ));
12311243 continue ;
12321244 }
@@ -1298,6 +1310,9 @@ std::vector<MapExprEntry> ParserVisitor::visitEntries(
12981310 if (!enable_optional_syntax_ && ctx->keys [i]->opt ) {
12991311 factory_.ReportError (SourceRangeFromParserRuleContext (ctx),
13001312 " unsupported syntax '?'" );
1313+ // Still generate an ID to detect node limit exceeded.
1314+ factory_.NextId (SourceRangeFromParserRuleContext (ctx));
1315+ factory_.NextId (SourceRangeFromParserRuleContext (ctx));
13011316 res.push_back (factory_.NewMapEntry (0 , factory_.NewUnspecified (0 ),
13021317 factory_.NewUnspecified (0 ), false ));
13031318 continue ;
@@ -1461,60 +1476,74 @@ std::vector<cel::ParseIssue> ParserVisitor::CollectIssues() {
14611476Expr ParserVisitor::GlobalCallOrMacroImpl (int64_t expr_id,
14621477 absl::string_view function,
14631478 std::vector<Expr> args) {
1464- if (auto macro = macro_registry_.FindMacro (function, args.size (), false );
1465- macro) {
1466- std::vector<Expr> macro_args;
1467- if (add_macro_calls_) {
1468- macro_args.reserve (args.size ());
1469- for (const auto & arg : args) {
1470- macro_args.push_back (factory_.BuildMacroCallArg (arg));
1471- }
1479+ auto macro = macro_registry_.FindMacro (function, args.size (), false );
1480+ if (!macro) {
1481+ return factory_.NewCall (expr_id, function, std::move (args));
1482+ }
1483+ if (factory_.is_node_limit_exceeded ()) {
1484+ return factory_.ReportError (
1485+ factory_.GetSourceRange (expr_id),
1486+ " could not expand macro: expression node limit exceeded" );
1487+ }
1488+ std::vector<Expr> macro_args;
1489+ if (add_macro_calls_) {
1490+ macro_args.reserve (args.size ());
1491+ for (const auto & arg : args) {
1492+ macro_args.push_back (factory_.BuildMacroCallArg (arg));
14721493 }
1473- factory_.BeginMacro (factory_.GetSourceRange (expr_id));
1474- auto expr = macro->Expand (factory_, std::nullopt , absl::MakeSpan (args));
1475- factory_.EndMacro ();
1476- if (expr) {
1477- if (add_macro_calls_) {
1478- factory_.AddMacroCall (expr->id (), function, std::nullopt ,
1479- std::move (macro_args));
1480- }
1481- // We did not end up using `expr_id`. Delete metadata.
1482- factory_.EraseId (expr_id);
1483- return std::move (*expr);
1494+ }
1495+ factory_.BeginMacro (factory_.GetSourceRange (expr_id));
1496+ auto expr = macro->Expand (factory_, std::nullopt , absl::MakeSpan (args));
1497+ factory_.EndMacro ();
1498+ if (expr) {
1499+ if (add_macro_calls_) {
1500+ factory_.AddMacroCall (expr->id (), function, std::nullopt ,
1501+ std::move (macro_args));
14841502 }
1503+ // We did not end up using `expr_id`. Delete metadata.
1504+ factory_.EraseId (expr_id);
1505+ return std::move (*expr);
14851506 }
1486-
14871507 return factory_.NewCall (expr_id, function, std::move (args));
14881508}
14891509
14901510Expr ParserVisitor::ReceiverCallOrMacroImpl (int64_t expr_id,
14911511 absl::string_view function,
14921512 Expr target,
14931513 std::vector<Expr> args) {
1494- if (auto macro = macro_registry_.FindMacro (function, args.size (), true );
1495- macro) {
1496- Expr macro_target;
1497- std::vector<Expr> macro_args;
1498- if (add_macro_calls_) {
1499- macro_args.reserve (args.size ());
1500- macro_target = factory_.BuildMacroCallArg (target);
1501- for (const auto & arg : args) {
1502- macro_args.push_back (factory_.BuildMacroCallArg (arg));
1503- }
1514+ auto macro = macro_registry_.FindMacro (function, args.size (), true );
1515+ if (!macro) {
1516+ return factory_.NewMemberCall (expr_id, function, std::move (target),
1517+ std::move (args));
1518+ }
1519+ if (factory_.is_node_limit_exceeded ()) {
1520+ return factory_.ReportError (
1521+ factory_.GetSourceRange (expr_id),
1522+ " could not expand macro: expression node limit exceeded" );
1523+ }
1524+
1525+ Expr macro_target;
1526+ std::vector<Expr> macro_args;
1527+ if (add_macro_calls_) {
1528+ macro_args.reserve (args.size ());
1529+ macro_target = factory_.BuildMacroCallArg (target);
1530+ for (const auto & arg : args) {
1531+ macro_args.push_back (factory_.BuildMacroCallArg (arg));
15041532 }
1505- factory_.BeginMacro (factory_.GetSourceRange (expr_id));
1506- auto expr = macro->Expand (factory_, std::ref (target), absl::MakeSpan (args));
1507- factory_.EndMacro ();
1508- if (expr) {
1509- if (add_macro_calls_) {
1510- factory_.AddMacroCall (expr->id (), function, std::move (macro_target),
1511- std::move (macro_args));
1512- }
1513- // We did not end up using `expr_id`. Delete metadata.
1514- factory_.EraseId (expr_id);
1515- return std::move (*expr);
1533+ }
1534+ factory_.BeginMacro (factory_.GetSourceRange (expr_id));
1535+ auto expr = macro->Expand (factory_, std::ref (target), absl::MakeSpan (args));
1536+ factory_.EndMacro ();
1537+ if (expr) {
1538+ if (add_macro_calls_) {
1539+ factory_.AddMacroCall (expr->id (), function, std::move (macro_target),
1540+ std::move (macro_args));
15161541 }
1542+ // We did not end up using `expr_id`. Delete metadata.
1543+ factory_.EraseId (expr_id);
1544+ return std::move (*expr);
15171545 }
1546+
15181547 return factory_.NewMemberCall (expr_id, function, std::move (target),
15191548 std::move (args));
15201549}
@@ -1677,8 +1706,9 @@ absl::StatusOr<ParseResult> ParseImpl(
16771706 CelParser parser (&tokens);
16781707 ExprRecursionListener listener (options.max_recursion_depth );
16791708 ParserVisitor visitor (
1680- source, options.max_recursion_depth , registry, options.add_macro_calls ,
1681- options.enable_optional_syntax , options.enable_quoted_identifiers ,
1709+ source, options.max_recursion_depth , options.expression_node_limit ,
1710+ registry, options.add_macro_calls , options.enable_optional_syntax ,
1711+ options.enable_quoted_identifiers ,
16821712 options.enable_variadic_logical_operators );
16831713
16841714 lexer.removeErrorListeners ();
0 commit comments