cppgraphqlgen: Invalid escaped character in string will crash the parser.

Hi,

It is possible to crash the parser (client/query/subscription) by having an invalid escaped character.

For example using a directive:

@something( s : "\." )

This looks like it causes an infinite recursion

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 23 (12 by maintainers)

Commits related to this issue

Most upvoted comments

Here is a patch for 3.7.1 with my fix using PEGTL limit_depth on the selection_set rule, note that the depth of 18 I have used here is the maximum safe limit when using a 4MB stack, it is much smaller when using the default 1MB stack.

 .../include/graphqlservice/internal/Grammar.h              | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/include/graphqlservice/internal/Grammar.h b/include/graphqlservice/internal/Grammar.h
index 806891d2..50560966 100644
--- a/include/graphqlservice/internal/Grammar.h
+++ b/include/graphqlservice/internal/Grammar.h
@@ -15,7 +15,7 @@
 
 #include <tao/pegtl.hpp>
 #include <tao/pegtl/contrib/parse_tree.hpp>
-
+#include <tao/pegtl/contrib/limit_depth.hpp>
 #include <functional>
 
 namespace graphql::peg {
@@ -1192,6 +1192,18 @@ struct schema_document : must<schema_document_content>
 {
 };
 
+
+template <typename Rule>
+struct ast_action : nothing<Rule>
+{
+};
+
+template <>
+struct ast_action<selection_set> : limit_depth<18>
+{
+};
+
+
 } // namespace graphql::peg
 
 #endif // GRAPHQLGRAMMAR_H
 /src/SyntaxTree.cpp | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/SyntaxTree.cpp b/src/SyntaxTree.cpp
index 7304a446..bf5b7ca2 100644
--- a/src/SyntaxTree.cpp
+++ b/src/SyntaxTree.cpp
@@ -849,7 +849,7 @@ ast parseSchemaString(std::string_view input)
 	{
 		// Try a smaller grammar with only schema type definitions first.
 		result.root =
-			parse_tree::parse<schema_document, ast_node, schema_selector, nothing, ast_control>(
+			parse_tree::parse<schema_document, ast_node, schema_selector, ast_action, ast_control>(
 				memory_input<>(data.data(), data.size(), "GraphQL"));
 	}
 	catch (const peg::parse_error&)
@@ -857,7 +857,7 @@ ast parseSchemaString(std::string_view input)
 		// Try again with the full document grammar so validation can handle the unexepected
 		// executable definitions if this is a mixed document.
 		result.root =
-			parse_tree::parse<mixed_document, ast_node, schema_selector, nothing, ast_control>(
+			parse_tree::parse<mixed_document, ast_node, schema_selector, ast_action, ast_control>(
 				memory_input<>(data.data(), data.size(), "GraphQL"));
 	}
 
@@ -877,7 +877,7 @@ ast parseSchemaFile(std::string_view filename)
 
 		// Try a smaller grammar with only schema type definitions first.
 		result.root =
-			parse_tree::parse<schema_document, ast_node, schema_selector, nothing, ast_control>(
+			parse_tree::parse<schema_document, ast_node, schema_selector, ast_action, ast_control>(
 				std::move(in));
 	}
 	catch (const peg::parse_error&)
@@ -890,7 +890,7 @@ ast parseSchemaFile(std::string_view filename)
 		// Try again with the full document grammar so validation can handle the unexepected
 		// executable definitions if this is a mixed document.
 		result.root =
-			parse_tree::parse<mixed_document, ast_node, schema_selector, nothing, ast_control>(
+			parse_tree::parse<mixed_document, ast_node, schema_selector, ast_action, ast_control>(
 				std::move(in));
 	}
 
@@ -908,15 +908,15 @@ ast parseString(std::string_view input)
 	{
 		// Try a smaller grammar with only executable definitions first.
 		result.root = parse_tree::
-			parse<executable_document, ast_node, executable_selector, nothing, ast_control>(
+			parse<executable_document, ast_node, executable_selector, ast_action, ast_control>(
 				memory_input<>(data.data(), data.size(), "GraphQL"));
 	}
 	catch (const peg::parse_error&)
 	{
 		// Try again with the full document grammar so validation can handle the unexepected type
 		// definitions if this is a mixed document.
-		result.root =
-			parse_tree::parse<mixed_document, ast_node, executable_selector, nothing, ast_control>(
+		result.root = parse_tree::
+			parse<mixed_document, ast_node, executable_selector, ast_action, ast_control>(
 				memory_input<>(data.data(), data.size(), "GraphQL"));
 	}
 
@@ -936,7 +936,7 @@ ast parseFile(std::string_view filename)
 
 		// Try a smaller grammar with only executable definitions first.
 		result.root = parse_tree::
-			parse<executable_document, ast_node, executable_selector, nothing, ast_control>(
+			parse<executable_document, ast_node, executable_selector, ast_action, ast_control>(
 				std::move(in));
 	}
 	catch (const peg::parse_error&)
@@ -948,8 +948,8 @@ ast parseFile(std::string_view filename)
 
 		// Try again with the full document grammar so validation can handle the unexepected type
 		// definitions if this is a mixed document.
-		result.root =
-			parse_tree::parse<mixed_document, ast_node, executable_selector, nothing, ast_control>(
+		result.root = parse_tree::
+			parse<mixed_document, ast_node, executable_selector, ast_action, ast_control>(
 				std::move(in));
 	}