use crate::tests::utils::parse_executable;
use crate::tests::utils::parse_mixed;
use crate::tests::utils::parse_schema;
use crate::GraphQLParser;
#[test]
fn fuzz_regression_variable_in_const_list_no_oom() {
let input = "e\0\0directive @dce(n:Sg =[g s$t";
let result = parse_schema(input);
assert!(result.has_errors());
let clean_input =
"directive @d(arg: [String] = [$x]) on FIELD";
let clean_result = parse_schema(clean_input);
assert!(clean_result.has_errors());
}
#[test]
fn fuzz_regression_type_keyword_in_executable_doc_no_oom() {
let result = parse_executable("p}type i");
assert!(result.has_errors());
}
#[test]
fn fuzz_regression_description_before_type_in_executable_no_oom() {
let result = parse_executable("t\"\"type");
assert!(result.has_errors());
let result = parse_executable("\"desc\" type Foo { f: Int }");
assert!(result.has_errors());
let result =
parse_executable("\"\"\"block desc\"\"\" interface Bar");
assert!(result.has_errors());
}
#[test]
fn wrong_document_kind_keywords_in_executable_no_oom() {
let keywords = [
"type Foo",
"interface Foo",
"union Foo",
"enum Foo",
"scalar Foo",
"input Foo",
"directive @foo on FIELD",
"schema { query: Q }",
"extend type Foo",
];
for keyword_input in keywords {
let result = parse_executable(keyword_input);
assert!(
result.has_errors(),
"expected error for executable doc input: \
`{keyword_input}`",
);
}
}
#[test]
fn wrong_document_kind_description_keywords_in_executable_no_oom() {
let keywords = [
"\"d\" type Foo",
"\"d\" interface Foo",
"\"d\" union Foo",
"\"d\" enum Foo",
"\"d\" scalar Foo",
"\"d\" input Foo",
"\"d\" directive @foo on FIELD",
"\"d\" schema { query: Q }",
"\"d\" extend type Foo",
];
for keyword_input in keywords {
let result = parse_executable(keyword_input);
assert!(
result.has_errors(),
"expected error for executable doc input: \
`{keyword_input}`",
);
}
}
#[test]
fn wrong_document_kind_keywords_in_schema_no_oom() {
let keywords = [
"query { f }",
"mutation { f }",
"subscription { f }",
"fragment F on T { f }",
];
for keyword_input in keywords {
let result = parse_schema(keyword_input);
assert!(
result.has_errors(),
"expected error for schema doc input: \
`{keyword_input}`",
);
}
}
#[test]
fn fuzz_regression_invalid_description_string_no_oom() {
let result = parse_schema(":\"\\d\"scalar");
assert!(
result.has_errors(),
"expected error for invalid string escape in description",
);
}
#[test]
fn invalid_description_string_before_schema_keywords_no_oom() {
let inputs = [
"\"\\d\"type Foo { f: Int }",
"\"\\d\"interface Foo { f: Int }",
"\"\\d\"union Foo = Bar",
"\"\\d\"enum Foo { BAR }",
"\"\\d\"scalar Foo",
"\"\\d\"input Foo { f: Int }",
"\"\\d\"directive @foo on FIELD",
"\"\\d\"schema { query: Q }",
"\"\\d\"extend type Foo { f: Int }",
];
for input in inputs {
let result = parse_schema(input);
assert!(
result.has_errors(),
"expected error for schema doc input: `{input}`",
);
}
}
#[test]
fn invalid_description_string_before_mixed_keywords_no_oom() {
let inputs = [
"\"\\d\"type Foo { f: Int }",
"\"\\d\"scalar Foo",
"\"\\d\"directive @foo on FIELD",
];
for input in inputs {
let result = parse_mixed(input);
assert!(
result.has_errors(),
"expected error for mixed doc input: `{input}`",
);
}
}
#[test]
fn unexpected_token_in_schema_catchall_no_oom() {
let inputs = [
"{ foo }",
"@foo",
"123",
"!",
"(",
];
for input in inputs {
let result = parse_schema(input);
assert!(
result.has_errors(),
"expected error for schema doc input: `{input}`",
);
}
}
#[test]
fn unexpected_token_in_executable_catchall_no_oom() {
let inputs = [
"@foo",
"123",
"!",
"(",
];
for input in inputs {
let result = parse_executable(input);
assert!(
result.has_errors(),
"expected error for executable doc input: `{input}`",
);
}
}
#[test]
fn unexpected_token_in_mixed_catchall_no_oom() {
let inputs = [
"@foo",
"123",
"!",
"(",
];
for input in inputs {
let result = parse_mixed(input);
assert!(
result.has_errors(),
"expected error for mixed doc input: `{input}`",
);
}
}
#[test]
fn fuzz_regression_deep_nested_list_value_no_stack_overflow() {
let deep_list = format!(
"{{ field(arg: {open}) }}",
open = "[".repeat(200),
);
let result = GraphQLParser::new(&deep_list)
.parse_executable_document();
assert!(
result.has_errors(),
"expected error for deeply nested list value",
);
let errors = result.errors();
assert!(
errors.iter().any(|e| {
e.message().contains("maximum nesting depth exceeded")
}),
"expected 'maximum nesting depth exceeded' error, \
got: {:?}",
errors.iter().map(|e| e.message()).collect::<Vec<_>>(),
);
}
#[test]
fn fuzz_regression_deep_nested_selection_set_no_stack_overflow() {
let deep_fields = format!(
"{open}{close}",
open = "{ f ".repeat(200),
close = "}".repeat(200),
);
let result = GraphQLParser::new(&deep_fields)
.parse_executable_document();
assert!(
result.has_errors(),
"expected error for deeply nested selection set",
);
let errors = result.errors();
assert!(
errors.iter().any(|e| {
e.message().contains("maximum nesting depth exceeded")
}),
"expected 'maximum nesting depth exceeded' error, \
got: {:?}",
errors.iter().map(|e| e.message()).collect::<Vec<_>>(),
);
}
#[test]
fn fuzz_regression_deep_nested_type_annotation_no_stack_overflow() {
let deep_type = format!(
"type Query {{ field: {open}String{close} }}",
open = "[".repeat(200),
close = "]".repeat(200),
);
let result = GraphQLParser::new(&deep_type)
.parse_schema_document();
assert!(
result.has_errors(),
"expected error for deeply nested type annotation",
);
let errors = result.errors();
assert!(
errors.iter().any(|e| {
e.message().contains("maximum nesting depth exceeded")
}),
"expected 'maximum nesting depth exceeded' error, \
got: {:?}",
errors.iter().map(|e| e.message()).collect::<Vec<_>>(),
);
}
#[test]
fn fuzz_regression_block_string_unicode_whitespace_no_panic() {
let input = "{ f(a: \"\"\"\n\u{2000} line1\n line2\n\"\"\") }";
let result = parse_executable(input);
let _ = result;
}
#[test]
fn fuzz_regression_block_string_nel_whitespace_no_panic() {
let input = "{ f(a: \"\"\"\n\u{85}\n line\n\"\"\") }";
let result = parse_executable(input);
let _ = result;
}