@@ -82,13 +82,17 @@ def __init__(self, envvar: str = "PATH") -> None:
8282 compiler_paths : List [str ] = [f"{ path } /{ compiler } " for path in potential_paths if os .path .isfile (path + '/' + compiler )]
8383 if len (compiler_paths ) == 0 :
8484
85- # if not in envvar, check to see if user supplied absolute path
85+ # if not in earlier envvar, check to see if user supplied absolute path
8686 if os .path .isfile (compiler ):
8787 self .compiler : str = compiler
8888
8989 # .. or check if in $PATH before tossing exception
9090 else :
91- for path in os .environ .get ("PATH" ).split (os .pathsep ):
91+ path_env : Optional [str ] = os .environ .get ("PATH" )
92+ if path_env is None :
93+ raise FuzzFrontendError ("$PATH envvar is not defined." )
94+
95+ for path in path_env .split (os .pathsep ):
9296 compiler_path : str = os .path .join (path , compiler )
9397
9498 L .debug (f"Checking if `{ compiler_path } ` is a valid compiler path" )
@@ -106,6 +110,9 @@ def __init__(self, envvar: str = "PATH") -> None:
106110
107111 L .debug (f"Initialized compiler: { self .compiler } " )
108112
113+ # store envvar for re-use across API
114+ self .env : str = env
115+
109116 # in case name supplied as `bin/fuzzer`, strip executable name
110117 self .name : str = fuzzer_name .split ('/' )[- 1 ] if '/' in fuzzer_name else fuzzer_name
111118 L .debug (f"Fuzzer name: { self .name } " )
@@ -125,7 +132,7 @@ def __init__(self, envvar: str = "PATH") -> None:
125132 self .num_workers : int = 1
126133
127134 self .compile_test : Optional [str ] = None
128- self .compiler_args : List [str ] = []
135+ self .compiler_args : Optional [str ] = None
129136 self .out_test_name : str = "out"
130137
131138 self .enable_sync : bool = False
@@ -134,6 +141,7 @@ def __init__(self, envvar: str = "PATH") -> None:
134141 self .sync_dir : str = "out_sync"
135142
136143 self .which_test : Optional [str ] = None
144+ self .post_stats : bool = False
137145
138146
139147 def __repr__ (self ) -> str :
@@ -191,6 +199,12 @@ def parse_args(cls) -> Optional[argparse.Namespace]:
191199 help = "Time in seconds the executor should sync to sync directory (default is 5 seconds)." )
192200
193201
202+ # Post-processing
203+ post_group = parser .add_argument_group ("Execution Post-processing" )
204+ post_group .add_argument ("--post_stats" , action = "store_true" ,
205+ help = "Output post-fuzzing statistics to user (if any)." )
206+
207+
194208 # Miscellaneous options
195209 parser .add_argument (
196210 "--fuzzer_help" , action = "store_true" ,
@@ -201,6 +215,8 @@ def parse_args(cls) -> Optional[argparse.Namespace]:
201215 cls .parser = parser
202216 super (FuzzerFrontend , cls ).parse_args ()
203217
218+ return None
219+
204220
205221 def print_help (self ) -> None :
206222 """
@@ -214,18 +230,18 @@ def print_help(self) -> None:
214230 ##############################################
215231
216232
217- def compile (self , lib_path : str , flags : List [str ], _out_bin : str , env = os .environ .copy ()) -> Optional [ str ] :
233+ def compile (self , lib_path : str , flags : List [str ], _out_bin : str , env = os .environ .copy ()) -> None :
218234 """
219235 Provides a simple interface that allows the user to compile a test harness
220236 with instrumentation using the specified compiler. Users should implement an
221237 inherited method that constructs the arguments necessary, and then pass it to the
222- base object. Returns string of generated binary if successful.
238+ base object.
223239
224240 `compile()` also supports compiling arbitrary harnesses without instrumentation if a compiler
225241 isn't set.
226242
227243 :param lib_path: path to DeepState static library for linking
228- :param flags: list of compiler flags (TODO: parse from compilation database)
244+ :param flags: list of compiler flags (TODO: support parsing from compilation database path )
229245 :param _out_bin: name of linked test harness binary
230246 :param env: optional envvars to set during compilation
231247 """
@@ -237,7 +253,7 @@ def compile(self, lib_path: str, flags: List[str], _out_bin: str, env = os.envir
237253 raise FuzzFrontendError (f"User-specified test binary conflicts with compiling from source." )
238254
239255 if not os .path .isfile (lib_path ):
240- raise FuzzFrontendError ("No {}-instrumented DeepState static library found in {}" .format (cls , lib_path ))
256+ raise FuzzFrontendError ("No {}-instrumented DeepState static library found in {}" .format (self , lib_path ))
241257 L .debug (f"Static library path: { lib_path } " )
242258
243259 # initialize compiler envvars
@@ -246,8 +262,7 @@ def compile(self, lib_path: str, flags: List[str], _out_bin: str, env = os.envir
246262 L .debug (f"CC={ env ['CC' ]} and CXX={ env ['CXX' ]} " )
247263
248264 # initialize command with prepended compiler
249- compiler_args = ["-std=c++11" , self .compile_test ] + flags + \
250- ["-o" , _out_bin ]
265+ compiler_args : List [str ] = ["-std=c++11" , self .compile_test ] + flags + ["-o" , _out_bin ] # type: ignore
251266 compile_cmd = [self .compiler ] + compiler_args
252267 L .debug (f"Compilation command: { str (compile_cmd )} " )
253268
@@ -259,7 +274,7 @@ def compile(self, lib_path: str, flags: List[str], _out_bin: str, env = os.envir
259274 raise FuzzFrontendError (f"{ self .compiler } interrupted due to exception:" , e )
260275
261276 # extra check if target binary was successfully compiled, and set that as target binary
262- out_bin = os .path .join (os .environ . get ( "PWD" ), _out_bin )
277+ out_bin = os .path .join (os .getcwd ( ), _out_bin )
263278 if os .path .exists (out_bin ):
264279 self .binary = out_bin
265280
@@ -351,7 +366,7 @@ def _dict_to_cmd(cmd_dict: Dict[str, Optional[str]]) -> List[Optional[str]]:
351366 return cmd_args
352367
353368
354- def build_cmd (self , cmd_dict : Dict [str , Optional [ str ] ], input_symbol : str = "@@" ) -> Dict [str , Optional [str ]]:
369+ def build_cmd (self , cmd_dict : Dict [str , Any ], input_symbol : str = "@@" ) -> Dict [str , Optional [str ]]:
355370 """
356371 Helper method to be invoked by child fuzzer class's cmd() property method in order
357372 to finalize command called by the fuzzer executable with appropriate arguments for the
@@ -409,15 +424,15 @@ def run(self, compiler: Optional[str] = None, no_exec: bool = False):
409424 self .pre_exec ()
410425
411426 # initialize cmd from property
412- command = [self .fuzzer ] + self ._dict_to_cmd (self .cmd )
427+ command = [self .fuzzer ] + self ._dict_to_cmd (self .cmd ) # type: ignore
413428
414429 # prepend compiler that invokes fuzzer
415430 if compiler :
416431 command .insert (0 , compiler )
417432
418433 results : List [int ] = []
419434 pool = multiprocessing .Pool (processes = self .num_workers )
420- results = pool .apply_async (self ._run , args = (command ,))
435+ results = pool .apply_async (self ._run , args = (command ,)) # type: ignore
421436
422437 pool .close ()
423438 pool .join ()
0 commit comments