@@ -1,4 +1,5 @@
#include <assert.h>
+#include <setjmp.h>
#include <unistd.h>
#include <sys/mman.h>
@@ -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);
@@ -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 <setjmp.h>
+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];