{"id":13645794,"url":"https://github.com/mc-imperial/jfs","last_synced_at":"2025-04-21T17:31:27.110Z","repository":{"id":55462960,"uuid":"111597978","full_name":"mc-imperial/jfs","owner":"mc-imperial","description":"Constraint solver based on coverage-guided fuzzing","archived":false,"fork":false,"pushed_at":"2023-11-28T20:07:14.000Z","size":1719,"stargazers_count":239,"open_issues_count":34,"forks_count":20,"subscribers_count":17,"default_branch":"master","last_synced_at":"2024-11-09T19:39:35.000Z","etag":null,"topics":["constraint-solver","coverage-guided-fuzzing","floating-point-arithmetic","fuzzing","jit","libfuzzer","llvm","smtlib","smtlibv2","z3"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mc-imperial.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2017-11-21T20:29:53.000Z","updated_at":"2024-10-08T08:47:47.000Z","dependencies_parsed_at":"2024-01-14T10:08:32.961Z","dependency_job_id":null,"html_url":"https://github.com/mc-imperial/jfs","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mc-imperial%2Fjfs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mc-imperial%2Fjfs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mc-imperial%2Fjfs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mc-imperial%2Fjfs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mc-imperial","download_url":"https://codeload.github.com/mc-imperial/jfs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250100415,"owners_count":21374934,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["constraint-solver","coverage-guided-fuzzing","floating-point-arithmetic","fuzzing","jit","libfuzzer","llvm","smtlib","smtlibv2","z3"],"created_at":"2024-08-02T01:02:41.984Z","updated_at":"2025-04-21T17:31:26.537Z","avatar_url":"https://github.com/mc-imperial.png","language":"C++","funding_links":[],"categories":["C++"],"sub_categories":[],"readme":"# JFS\n\nJFS (Just Fuzz it Solver) (originally JIT Fuzzing Solver) is an experimental\nconstraint solver designed to investigate using __coverage guided fuzzing__ as\nan incomplete strategy for solving boolean, BitVector, and floating-point\nconstraints.\n\nJFS supports constraints in the [SMT-LIBv2][1] constraint langauge in the\n`QF_BV`, `QF_BVFP`, and `QF_FP` logics. JFS's primary purpose however is\nsolve floating-point constraints.\n\nJFS is built on top of the following projects\n\n* [LLVM](https://llvm.org/)\n* [Clang](http://clang.llvm.org/)\n* [Z3](https://github.com/Z3Prover/z3)\n* [LibFuzzer](https://llvm.org/docs/LibFuzzer.html)\n\n[1]: http://smtlib.cs.uiowa.edu/\n\n## FSE 2019 paper\n\n[A paper on JFS](https://srg.doc.ic.ac.uk/files/papers/jfs-esecfse-19.pdf) was presented and published at ESEC/FSE 2019.\n\nAdditional resources:\n\n* [artifact](https://github.com/mc-imperial/jfs-fse-2019-artifact)\n* [slides](https://docs.google.com/presentation/d/1wPxNJ3rXVqLRCm9jRMZTsL5sEW5aW9WZ583TPpb2Ffo/edit?usp=sharing)\n\nThe [Docker image](https://cloud.docker.com/u/delcypher/repository/docker/delcypher/jfs_build) with the tag `fse_2019`\n\n## Using JFS Docker image\n\nIf you want to get started with JFS with minimal effort the easiest thing to do\nis download the latest Docker image for JFS. Note this image may not be up-to-date\nso you might not the latest changes.\n\nTo obtain the image run (replace `fse_2019` with the tag you wish to use).\n\n```\ndocker pull delcypher/jfs_build:fse_2019\n```\n\nThe simplest invocation is something like this which will show JFS's help output.\n\n```\ndocker run --user 1000 --rm -t delcypher/jfs_build:fse_2019 /home/user/jfs/build/bin/jfs --help\n```\n\nTo run JFS on a SMT-LIBv2 file that exists outside the container (`/path/to/simple.smt2` in this example) run this command below.\n\n```\ndocker run --rm -t -v /path/to/simple.smt2:/tmp/simple.smt2 delcypher/jfs_build:fse_2019 /home/user/jfs/build/bin/jfs /tmp/simple.smt2\n```\n\nNote that the `docker run` command creates a new container and destroys it\nafterwards which has notable overhead. For better performance consider running\nJFS outside of a docker container or creating a single container and spawning a\nshell inside it and then launch JFS from there.\n\n## Building JFS\n\nJFS has been tested on Linux and macOS.\nWindows support would likely require a lot more work and is dependent on getting\nLibFuzzer to work on Windows.\n\n### Using Docker (the easy way)\n\nThe easiest way is just to use our Dockerfile. To do this simply run\n\n```\nscripts/Dockerfiles/build.sh\n```\n\nonce the script completes you will have a Docker image on your system\nnamed `jfs_build:ubuntu1604`. In this image you will find the JFS binaries\nin the `/home/user/jfs/build/bin` directory.\n\n## From source (the hard way)\n\nJFS has the following build dependencies:\n\n* LLVM/Clang/compiler-rt 6.0\n* Z3 4.6.0\n* CMake\n* Ninja\n\n\nHere are the steps to build JFS.\n\n1. Build Z3 4.6.0. Note you must build this using Z3's CMake build system\nand not its legacy build system because JFS's build system depends on files\nemitted by Z3's CMake build system.\n\nA convenience script is provided for this\n\n```bash\nexport Z3_SRC_DIR=/home/user/z3/src\nexport Z3_BUILD_DIR=/home/user/z3/build\nexport Z3_BUILD_TYPE=Release\nscripts/dist/build_z3.sh\n```\n\nSet the `Z3_SRC_DIR`, `Z3_BUILD_DIR` to paths to empty or non-existant\ndirectories. The `Z3_BUILD_TYPE` can be set to `Release`, `RelWithDebInfo`,\nor `Debug`.\n\n2. Build or install LLVM, Clang, and compiler-rt 6.0\n\n\nA convenience script is provided to build LLVM.\n\n```bash\nexport LLVM_SRC_DIR=/home/user/llvm/src\nexport LLVM_BUILD_DIR=/home/user/llvm/src\nexport LLVM_BUILD_TYPE=Release\nscripts/dist/build_llvm.sh\n```\n\nSet the `LLVM_SRC_DIR`, `LLVM_BUILD_DIR` to paths to empty or non-existant\ndirectories. The `LLVM_BUILD_TYPE` can be set to `Release`, `RelWithDebInfo`,\nor `Debug`.\n\n3. Build JFS\n\nA convenience script is provided to build JFS.\n\n```bash\nexport JFS_SRC_DIR=/home/user/jfs/src\nexport JFS_BUILD_DIR=/home/user/jfs/build\nexport JFS_BUILD_TYPE=Release\nscripts/dist/build_jfs.sh\n```\n\n`JFS_SRC_DIR` should be the absolute path to an already cloned copy of the JFS\nrepo. `JFS_BUILD_DIR` should be a path to an empty or non-existant directory.\nThe `JFS_BUILD_TYPE` can be set to `Release`, `RelWithDebInfo`, or `Debug`.\n\nNote that `Z3_BUILD_DIR` and `LLVM_BUILD_DIR` must also be set.\n\n4. Test JFS\n\n```\ncd ${JFS_BUILD_DIR}\nninja check\n```\n\n\n## FAQs\n\n### Aren't there already a bunch of search based floating-point constraint solvers?\n\nYes. However as far as we're aware, JFS is the first to try to use an\n\"off the shelf\" coverage guided fuzzer as a search strategy.\n\nHere's a non-exhaustive list:\n\n* [coral][2] is a constraint solver that\n  supports various search strategies over floating point constraints.  It uses\n  its own constraint language which is only partially overlaps with `QF_FP`\n  constraints in the SMT-LIBv2 language. The [smt2coral][3] tool provides a way\n  to run coral on SMT-LIBv2 constraints.\n\n* [XSat][4] transform constraints into a mathematical global optimization\n problem. Unfortunately this tool is not open source.\n\n* [goSAT][5] takes the ideas behind XSat but\n  uses different optimization libraries and uses LLVM's JIT to generate code.\n\nWe are currently in the process of performing an evaluation of JFS against\nthese solvers and we will report these results in the not to distant future.\n\n[2]: http://pan.cin.ufpe.br/coral/index.html\n[3]: https://github.com/delcypher/smt2coral\n[4]: https://www.researchgate.net/publication/305252908_XSat_A_Fast_Floating-Point_Satisfiability_Solver\n[5]: https://github.com/abenkhadra/gosat\n\n### How does JFS work?\n\nTo see how JFS works let's walk through a small example.\n\n1. Parse SMT-LIB constraints using Z3.\n\n```\n(declare-fun a () (_ FloatingPoint 11 53))\n(declare-fun b () (_ FloatingPoint 11 53))\n(define-fun a_b_rne () (_ FloatingPoint 11 53) (fp.div RNE a b))\n(define-fun a_b_rtp () (_ FloatingPoint 11 53) (fp.div RTP a b))\n(assert (not (fp.isNaN a)))\n(assert (not (fp.isNaN b)))\n(assert (not (fp.eq a_b_rne a_b_rtp)))\n(assert (not (fp.isNaN a_b_rne)))\n(assert (not (fp.isNaN a_b_rtp)))\n(check-sat)\n```\n\n2. Perform some simplifications on the constraints (e.g. constant folding).\n\n**NOTE: You can use the jfs-opt tool to experiment with these simplifications.**\n\n3. Generate a C++ program where the reachability of an `abort()` statement is\nequivalent to finding a satisfying assignment to the constraints.\n\n**NOTE: You can use the `jfs-smt2cxx` tool to convert SMT-LIBv2 constraints\ninto a program.**\n\n```c++\nextern \"C\" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {\n  if (size \u003c 16) {\n    return 0;\n  }\n  BufferRef\u003cconst uint8_t\u003e jfs_buffer_ref =\n      BufferRef\u003cconst uint8_t\u003e(data, size);\n  const Float\u003c11, 53\u003e a = makeFloatFrom\u003c11, 53\u003e(jfs_buffer_ref, 0, 63);\n  const Float\u003c11, 53\u003e b = makeFloatFrom\u003c11, 53\u003e(jfs_buffer_ref, 64, 127);\n  const bool jfs_ssa_0 = a.isNaN();\n  const bool jfs_ssa_1 = !(jfs_ssa_0);\n  if (jfs_ssa_1) {\n  } else {\n    return 0;\n  }\n  const bool jfs_ssa_2 = b.isNaN();\n  const bool jfs_ssa_3 = !(jfs_ssa_2);\n  if (jfs_ssa_3) {\n  } else {\n    return 0;\n  }\n  const Float\u003c11, 53\u003e jfs_ssa_4 = a.div(JFS_RM_RNE, b);\n  const Float\u003c11, 53\u003e jfs_ssa_5 = a.div(JFS_RM_RTP, b);\n  const bool jfs_ssa_6 = jfs_ssa_4.ieeeEquals(jfs_ssa_5);\n  const bool jfs_ssa_7 = !(jfs_ssa_6);\n  if (jfs_ssa_7) {\n  } else {\n    return 0;\n  }\n  const bool jfs_ssa_8 = jfs_ssa_4.isNaN();\n  const bool jfs_ssa_9 = !(jfs_ssa_8);\n  if (jfs_ssa_9) {\n  } else {\n    return 0;\n  }\n  const bool jfs_ssa_10 = jfs_ssa_5.isNaN();\n  const bool jfs_ssa_11 = !(jfs_ssa_10);\n  if (jfs_ssa_11) {\n  } else {\n    return 0;\n  }\n  // Fuzzing target\n  abort();\n}\n```\n\n4. This program is then compiled by Clang with coverage instrumentation\n  and linked against LibFuzzer and a small runtime library. The runtime\n  library implements the `Float` and `BitVector` SMT-LIBv2 types.\n\n5. A set of seeds are generated for the fuzzer.\n\n6. The compiled binary is invoked with the given seeds.\n  If the fuzzer generates an input that reaches the `abort()` a satisfying\n  assignment has been found and JFS terminates reporting `sat`.\n\nNote this strategy will never find a satisfying assignment if one does not exist\n(i.e. the constraints are unsatisfiable). This is why we say JFS is \"incomplete\"\nbecause it cannot show that unsatisfiable constraints are unsatisfiable.\n\nThere is one exception to this. JFS can show unsatisfiable constraints to be\nunsatisfiable if its simplications show one or more constraints to be `false`\n(i.e. trivially unsatisfiable).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmc-imperial%2Fjfs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmc-imperial%2Fjfs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmc-imperial%2Fjfs/lists"}