diff --git a/checkpolicy/fuzz/checkpolicy-fuzzer.c b/checkpolicy/fuzz/checkpolicy-fuzzer.c index ab1a6bb8..6c5ce02f 100644 --- a/checkpolicy/fuzz/checkpolicy-fuzzer.c +++ b/checkpolicy/fuzz/checkpolicy-fuzzer.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -30,6 +31,7 @@ extern void yyrestart(FILE *); extern int yylex_destroy(void); extern void set_source_file(const char *name); +jmp_buf fuzzing_pre_parse_stack_state; // Set to 1 for verbose libsepol logging #define VERBOSE 0 @@ -99,6 +101,13 @@ static int read_source_policy(policydb_t *p, const uint8_t *data, size_t size) init_parser(1); + if (!setjmp(fuzzing_pre_parse_stack_state)) { + queue_destroy(id_queue); + fclose(yyin); + yylex_destroy(); + return -1; + } + rc = yyparse(); // TODO: drop global variable policydb_errors if proven to be redundant assert(rc || !policydb_errors); diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l index 62f28c11..e46677a8 100644 --- a/checkpolicy/policy_scan.l +++ b/checkpolicy/policy_scan.l @@ -41,6 +41,21 @@ int werror = 0; int yyerror(const char *msg); int yywarn(const char *msg); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +/* + * Version that does not exit, like yy_fatal_error(), + * since fuzz targets must not call exit(). + */ +#include +extern jmp_buf fuzzing_pre_parse_stack_state; +void yyfatal(const char *msg) +{ + yyerror(msg); + longjmp(fuzzing_pre_parse_stack_state, 1); +} +#define YY_FATAL_ERROR(msg) yyfatal(msg) +#endif + void set_source_file(const char *name); char source_file[PATH_MAX];