# Python package of Futag
```bash
    **************************************************
    **      ______  __  __  ______  ___     ______  **
    **     / ____/ / / / / /_  __/ /   |   / ____/  **
    **    / /_    / / / /   / /   / /| |  / / __    **
    **   / __/   / /_/ /   / /   / ___ | / /_/ /    **
    **  /_/      \____/   /_/   /_/  |_| \____/     **
    **                                              **
    **     Fuzzing target Automated Generator       **
    **             a tool of ISP RAS                **
    **************************************************
    ** This package is for building, generating,    **
    **  compiling fuzz-drivers of library functions **
    **************************************************
```
This python package is for building library, generating and compiling fuzz-drivers of functions.
* Package url: https://github.com/ispras/Futag/tree/main/src/python/futag-package
* Bug Tracker = https://github.com/ispras/Futag/issues
## 1. Install

```bash 
pip install dist/futag-2.1.1.tar.gz
```

## 2. Preprocessor
* Prerequisite: You must have [llvm-package with Futag checker](https://github.com/ispras/Futag/blob/main/README.en.md#22-build-and-install) to analyze your library.

The preprocessor module tries to configure and build your library with configure file or cmake, you should specify path to futag-llvm and path. The library then will be built with address sanitizer and Futag-checker. The class Builder of this module has 4 method:
- auto-build: automatically builds your library
- build_configure(): builds your library with configure file
- build_cmake(): builds your library with cmake
- analyze(): analyzes the result of Futag-checker. This method will generate json file futag-analysis-result.json.

Example:
```python
from futag.preprocessor import *

test_lib = Builder(
    "../../futag-llvm", #path to Futag package
    "json-c-json-c-0.13.1-20180305", #path to testing library
    #clean=True, #delete all folders generated by Futag
    #processes=8, #number of processors for building
)
test_lib.auto_build()
test_lib.analyze()
```

For more parameters of Builder please refer to docstring of this class.
```bash
class Builder(builtins.object)
 |  Builder(futag_llvm_package: str, library_root: str, flags: str = '-fsanitize=address', clean: bool = False, build_path: str = '.futag-build', install_path: str = '.futag-install', analysis_path: str = '.futag-analysis', process
es: int = 4, build_ex_params='')
 |  
 |  Futag Builder Class
 |  
 |  Methods defined here:
 |  
 |  __init__(self, futag_llvm_package: str, library_root: str, flags: str = '-fsanitize=address', clean: bool = False, build_path: str = '.futag-build', install_path: str = '.futag-install', analysis_path: str = '.futag-analysis', 
processes: int = 4, build_ex_params='')
 |      Constructor of class Builder
 |      
 |      Args:
 |          futag_llvm_package (str): path to the futag-llvm package (with binaries, scripts, etc.).
 |          library_root (str): path to the library root.
 |          flags (str, optional): flags for compiling.. Defaults to COMPILER_FLAGS.
 |          clean (bool, optional): Option for deleting futag folders if they are exist, for example futag-build, futag-install, futag-analysis. Defaults to False.
 |          build_path (str, optional): path to the build directory. Be careful, this directory will be deleted and create again if clean set to True. Defaults to BUILD_PATH.
 |          install_path (str, optional): path for saving report of analysis. Be careful, this directory will be deleted and create again if clean set to True. Defaults to INSTALL_PATH.
 |          analysis_path (str, optional): path for saving report of analysis. Be careful, this directory will be deleted and create again if clean set to True. Defaults to ANALYSIS_PATH.
 |          processes (int, optional): number of processes while building. Defaults to 4.
 |          build_ex_params (_type_, optional): extra params for building, for example "--with-openssl" for building curl. Defaults to BUILD_EX_PARAMS.
 |      
 |      Raises:
 |          ValueError: INVALID_FUTAG_PATH: Invalid path of futag-llvm.
 |          ValueError: INVALID_LIBPATH: Invalid path of library.
 |          ValueError: INVALID_INPUT_PROCESSES: the input value of "processes" is not a number or negative.
 |  
 |  analyze(self)
 |      This function reads analysis result of Futag checker
 |  
 |  auto_build(self) -> bool
 |      This function tries to automatically build your library. It finds in your library source code whether Makefile, file configure, or CMakeList.txt file exists.
 |      
 |      Returns:
 |          bool: result of auto build.
 |  
 |  build_cmake(self) -> bool
 |      This function tries to build your library with cmake.
 |      
 |      Raises:
 |          ValueError: LIB_CONFIGURE_FAILED: Futag can not configure library.
 |          ValueError: LIB_ANALYZING_FAILED: Futag can not analyze library with its own checkers.
 |          ValueError: LIB_BUILD_FAILED: Futag can not build the library.
 |          ValueError: LIB_INSTALL_FAILED: Futag can not install the library.
 |      
 |      Returns:
 |          bool: result of building with cmake.
 |  
 |  build_configure(self) -> bool
 |      This function tries to build your library with configure.
 |      
 |      Raises:
 |          ValueError: LIB_CONFIGURE_FAILED: Futag can not configure library.
 |          ValueError: LIB_ANALYZING_FAILED: Futag can not analyze library with its own checkers.
 |          ValueError: LIB_BUILD_FAILED: Futag can not build the library.
 |          ValueError: LIB_INSTALL_FAILED: Futag can not install the library.
 |      
 |      Returns:
 |          bool: result of building with file "configure".
 |  
 |  build_makefile(self) -> bool
 |      This function tries to build your library with Makefile.
 |      
 |      Raises:
 |          ValueError: LIB_ANALYZING_FAILED: Futag can not analyze library with its own checkers.
 |          ValueError: LIB_BUILD_FAILED: Futag can not build the library.
 |          ValueError: LIB_INSTALL_FAILED: Futag can not install the library.
 |      
 |      Returns:
 |          bool: result of building with Makefile.
 |  
 |  ----------------------------------------------------------------------
```

## 3. Generator
The module Generator is for generating, compiling fuzz-drivers. You should specify path to analysis result (file futag-analysis-result.json), path to futag-llvm and the path to library. For more detail please refer to docstring of module.

Example:
```python
from futag.generator import * 
generator = Generator(
    "../../futag-llvm", #path to Futag package
    "json-c-json-c-0.13.1-20180305", #path to testing library
)
generator.gen_targets(anonymous=False) #generate fuzzing wrapper for private function
generator.compile_targets(16) #number of processes while compiling
```
The fuzz-drivers of libjson will be generated in futag-fuzz-drivers inside the library root.

```bash
class Generator(builtins.object)
 |  Generator(futag_llvm_package: str, library_root: str, target_type: int = 0, json_file: str = '.futag-analysis/futag-analysis-result.json', output_path='futag-fuzz-drivers', build_path='.futag-build', install_path='.futag-install')
 |  
 |  Futag Generator
 |  
 |  Methods defined here:
 |  
 |  __init__(self, futag_llvm_package: str, library_root: str, target_type: int = 0, json_file: str = '.futag-analysis/futag-analysis-result.json', output_path='futag-fuzz-drivers', build_path='.futag-build', install_path='.futag-install')
 |      Constructor of Generator class.
 |      
 |      Args:
 |          futag_llvm_package (str): path to the futag-llvm package (with binaries, scripts, etc.).
 |          library_root (str): path to the library root.
 |          target_type (int, optional): format of fuzz-drivers (LIBFUZZER or AFLPLUSPLUS). Defaults to LIBFUZZER.
 |          json_file (str, optional): path to the futag-analysis-result.json file. Defaults to ANALYSIS_FILE_PATH.
 |          output_path (_type_, optional): where to save fuzz-drivers, if this path exists, Futag will delete it and create new one. Defaults to FUZZ_DRIVER_PATH.
 |          build_path (_type_, optional): path to the build directory. Defaults to BUILD_PATH.
 |          install_path (_type_, optional): path to the install directory. Defaults to INSTALL_PATH.
 |      
 |      Raises:
 |          ValueError: INVALID_TARGET_TYPE: Invalid the type of target.
 |          ValueError: INVALID_FUTAG_PATH: Invalid path of futag-llvm.
 |          ValueError: INVALID_LIBPATH: Invalid path of library.
 |          ValueError: INVALID_ANALYSIS_FILE: Invalid path to analysis result file.
 |          ValueError: INVALID_BUILPATH: Invalid path to the library build path.
 |          ValueError: INVALID_INSTALLPATH: Invalid path to the library install path.
 |  
 |  compile_driver_worker(self, bgen_args)
 |  
 |  compile_targets(self, workers: int = 4, keep_failed: bool = False, extra_include: str = '', extra_dynamiclink: str = '', flags: str = '-fsanitize=address,fuzzer', coverage: bool = False)
 |      Parameters
 |      ----------
 |      workers: int
 |          number of processes for compiling, default to 4.
 |      keep_failed: bool
 |          option for saving not compiled fuzz-targets, default to False.
 |      extra_include: str
 |          option for add included directories while compiling, default to empty string.
 |      extra_dynamiclink: str
 |          option for add dynamic libraries while compiling, default to empty string.
 |      flags: str
 |          flags for compiling fuzz-drivers, default to "-fsanitize=address,fuzzer -g -O0".
 |  
 |  gen_targets(self, anonymous: bool = False)
 |      Parameters
 |      ----------
 |      anonymous: bool
 |          option for generating fuzz-targets of non-public functions, default to False.
 |  
 |  ----------------------------------------------------------------------
```

## 4. Fuzzer

The class Fuzzer helps automatically fuzz targets. It's just a simple script for testing and may contains some unexpected bugs. 
Be careful use this function, you should test libraries in a virtual environment like Docker or VM

```python
from futag.fuzzer import *
f = Fuzzer(
    "../../futag-llvm", #path to Futag package
    "json-c-json-c-0.13.1-20180305/futag-fuzz-drivers", #path to folder, which contains all the generated fuzz-targets"
)
f.fuzz()
```

```bash
class Fuzzer(builtins.object)
 |  Fuzzer(futag_llvm_package: str, fuzz_driver_path: str = 'futag-fuzz-drivers', debug: bool = False, gdb: bool = False, svres: bool = False, fork: int = 1, totaltime: int = 300, timeout: int = 10, memlimit: int = 2048, coverage: bool = False, leak: bool = False, introspect: bool = False)
 |  
 |  Futag Fuzzer
 |  
 |  Methods defined here:
 |  
 |  __init__(self, futag_llvm_package: str, fuzz_driver_path: str = 'futag-fuzz-drivers', debug: bool = False, gdb: bool = False, svres: bool = False, fork: int = 1, totaltime: int = 300, timeout: int = 10, memlimit: int = 2048, coverage: bool = False, leak: bool = False, introspect: bool = False)
 |      Parameters
 |      ----------
 |      futag_llvm_package: str
 |          path to the futag llvm package (with binaries, scripts, etc)
 |      fuzz_driver_path: str
 |          location of fuzz-drivers, default "futag-fuzz-drivers"
 |      debug: bool = False
 |          print debug infomation while fuzzing, default False
 |      gdb: bool = False
 |          debug crashes with GDB, default False
 |      svres: bool = False
 |          generate svres file for Svace (if you have Svace), default False
 |      fork: int = 1
 |          fork mode of libFuzzer (https://llvm.org/docs/LibFuzzer.html#fork-mode), default 1 - no fork mode
 |      totaltime: int = 300
 |          total time of fuzzing one fuzz-driver, default 300 seconds
 |      timeout: int = 10
 |          if an fuzz-drive takes longer than this timeout, the process is treated as a failure case, default 10 seconds
 |      memlimit: int = 2048
 |          option for rss_limit_mb of libFuzzer - Memory usage limit in Mb, default 2048 Mb, Use 0 to disable the limit.
 |      coverage: bool = False
 |          option for showing coverage of fuzzing, default False.
 |      leak: bool = False
 |          detecting memory leak, default False
 |      introspect: bool = False
 |          option for integrate with fuzz-introspector (to be add soon).
 |  
 |  fuzz(self)
 |  
 |  ----------------------------------------------------------------------
```