@@ -393,6 +393,51 @@ static int fuzz_csv_reader(const char* data, size_t size) {
393393 return 0 ;
394394}
395395
396+ #define MAX_AST_LITERAL_EVAL_TEST_SIZE 0x10000
397+ PyObject * ast_literal_eval_method = NULL ;
398+ /* Called by LLVMFuzzerTestOneInput for initialization */
399+ static int init_ast_literal_eval (void ) {
400+ PyObject * ast_module = PyImport_ImportModule ("ast" );
401+ if (ast_module == NULL ) {
402+ return 0 ;
403+ }
404+ ast_literal_eval_method = PyObject_GetAttrString (ast_module , "literal_eval" );
405+ return ast_literal_eval_method != NULL ;
406+ }
407+ /* Fuzz ast.literal_eval(x) */
408+ static int fuzz_ast_literal_eval (const char * data , size_t size ) {
409+ if (size > MAX_AST_LITERAL_EVAL_TEST_SIZE ) {
410+ return 0 ;
411+ }
412+ /* Ignore non null-terminated strings since ast can't handle
413+ embedded nulls */
414+ if (memchr (data , '\0' , size ) == NULL ) {
415+ return 0 ;
416+ }
417+
418+ PyObject * s = PyUnicode_FromString (data );
419+ /* Ignore exceptions until we have a valid string */
420+ if (s == NULL ) {
421+ PyErr_Clear ();
422+ return 0 ;
423+ }
424+
425+ PyObject * literal = PyObject_CallOneArg (ast_literal_eval_method , s );
426+ /* Ignore some common errors thrown by ast.literal_eval */
427+ if (literal == NULL && (PyErr_ExceptionMatches (PyExc_ValueError ) ||
428+ PyErr_ExceptionMatches (PyExc_TypeError ) ||
429+ PyErr_ExceptionMatches (PyExc_SyntaxError ) ||
430+ PyErr_ExceptionMatches (PyExc_MemoryError ) ||
431+ PyErr_ExceptionMatches (PyExc_RecursionError ))
432+ ) {
433+ PyErr_Clear ();
434+ }
435+
436+ Py_XDECREF (literal );
437+ Py_DECREF (s );
438+ return 0 ;
439+ }
440+
396441/* Run fuzzer and abort on failure. */
397442static int _run_fuzz (const uint8_t * data , size_t size , int (* fuzzer )(const char * , size_t )) {
398443 int rv = fuzzer ((const char * ) data , size );
@@ -507,6 +552,17 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
507552 }
508553
509554 rv |= _run_fuzz (data , size , fuzz_csv_reader );
555+ #endif
556+ #if !defined(_Py_FUZZ_ONE ) || defined(_Py_FUZZ_fuzz_ast_literal_eval )
557+ static int AST_LITERAL_EVAL_INITIALIZED = 0 ;
558+ if (!AST_LITERAL_EVAL_INITIALIZED && !init_ast_literal_eval ()) {
559+ PyErr_Print ();
560+ abort ();
561+ } else {
562+ AST_LITERAL_EVAL_INITIALIZED = 1 ;
563+ }
564+
565+ rv |= _run_fuzz (data , size , fuzz_ast_literal_eval );
510566#endif
511567 return rv ;
512568}
0 commit comments