├── .circleci └── config.yml ├── .clang-format ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── Makefile ├── README.md ├── build ├── bin │ └── .gitkeep ├── include │ └── .gitkeep └── lib │ └── .gitkeep ├── lib ├── CMakeLists.txt ├── dict.h ├── dynamic-array.h ├── gradient_descend.c ├── gradient_descend.h ├── md5.c ├── md5.h ├── set.h ├── testcase-list.c ├── testcase-list.h ├── timer.c ├── timer.h ├── wrapped_interval.c ├── wrapped_interval.h ├── z3-fuzzy-datastructures-gen.h ├── z3-fuzzy-debug-utils.h ├── z3-fuzzy.c └── z3-fuzzy.h ├── python ├── .gitignore ├── fuzzysat │ ├── __init__.py │ └── fuzzy.py ├── native │ ├── Makefile │ └── wrapperForPython.c ├── setup.py └── test.py ├── scripts ├── decompress_and_run.sh ├── detect_interesting_queries.py ├── extract_check_light_phases.py ├── extract_faster_fuzzy.py ├── extract_query_k.py ├── findall_sols.py ├── fix_query.sh ├── fix_query_and_compress.sh ├── how_many_sat_in_fuzzy_time.py ├── load_queries.py ├── merge_queries_from_folder.py ├── num_queries.py ├── parse_filps.py ├── parse_fuzzy_jfs.py ├── parse_fuzzy_sat_z3_unkown.py ├── parse_info_query.py ├── parse_info_query_splitted.py ├── parse_run_multiple_log.py ├── query-printer.py ├── run_batch_fuzzy_jfs.sh ├── run_batch_fuzzy_with_parsing.sh ├── run_batch_fuzzy_z3.sh ├── run_batch_fuzzy_z3_old.sh ├── run_experiment.py ├── run_on_multiple_queries.py ├── run_query_stats_exp.sh └── split_queries_in_files.py ├── tests ├── 001_its.smt2 ├── 002_arithm.smt2 ├── 003_arithm.smt2 ├── 004_arithm.smt2 ├── 005_arithm.smt2 ├── run.py └── zero_seed.bin └── tools ├── CMakeLists.txt ├── debug-eval.c ├── eval-driver.c ├── findall-driver.c ├── fuzzy-solver-notify.c ├── fuzzy-solver-vs-z3.c ├── fuzzy-solver.c ├── interval_test.c ├── maxmin-driver.c ├── pretty-print.c ├── pretty-print.h ├── stats-collection-fuzzy.c ├── stats-collection-z3.c └── test-easy.c /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Use the latest 2.1 version of CircleCI pipeline process engine. See: https://circleci.com/docs/2.0/configuration-reference 2 | version: 2.1 3 | # Use a package of configuration called an orb. 4 | jobs: 5 | build: 6 | docker: 7 | - image: ercoppa/fuzzolic-ci-runner 8 | steps: 9 | - checkout 10 | 11 | - run: 12 | name: Monitor memory usage 13 | command: | 14 | echo "Memory Usage" > /tmp/memusage 15 | echo "============" >> /tmp/memusage 16 | free -h -s 3 >> /tmp/memusage 17 | background: true 18 | 19 | - run: 20 | name: Fetching submodules 21 | command: | 22 | [[ -f fuzzy-sat/.git ]] || (git submodule sync && git submodule update --init --recursive) 23 | 24 | - run: 25 | name: Init cmake build 26 | command: | 27 | mkdir build_cmake || true 28 | cd build_cmake 29 | cmake .. -DCMAKE_BUILD_TYPE=Release 30 | 31 | - restore_cache: 32 | key: fuzzolic-z3-{{ checksum ".git/modules/fuzzolic-z3/refs/heads/fuzzolic" }} 33 | 34 | - run: 35 | name: Building z3 36 | command: | 37 | cd build_cmake/fuzzolic-z3 38 | [ ! -f z3 ] && make -j 5 || true 39 | 40 | - save_cache: 41 | paths: 42 | - build_cmake/fuzzolic-z3 43 | key: fuzzolic-z3-{{ checksum ".git/modules/fuzzolic-z3/refs/heads/fuzzolic" }} 44 | 45 | - run: 46 | name: Building fuzzy 47 | command: | 48 | cd build_cmake/lib 49 | make -j 5 50 | cd ../tools 51 | make -j 5 52 | 53 | - run: 54 | name: Tests 55 | command: | 56 | cd tests 57 | FUZZY_BIN="`pwd`/../build_cmake/tools/fuzzy-solver" python3 -m pytest run.py --junitxml=test-results/junit.xml 58 | 59 | - store_test_results: 60 | path: tests/test-results 61 | 62 | - store_artifacts: 63 | path: /tmp/memusage 64 | destination: memory-usage 65 | 66 | - run: 67 | name: Job memory usage 68 | command: cat /sys/fs/cgroup/memory/memory.max_usage_in_bytes 69 | when: always 70 | 71 | workflows: 72 | basic-workflow: 73 | jobs: 74 | - build: 75 | filters: 76 | branches: 77 | ignore: dev 78 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | IndentWidth: 4 3 | UseTab: Never 4 | TabWidth: 4 5 | BreakBeforeBraces: Linux 6 | AllowShortIfStatementsOnASingleLine: false 7 | ColumnLimit: 80 8 | SortIncludes: false 9 | AlignConsecutiveAssignments: true 10 | AlignConsecutiveDeclarations: true 11 | 12 | # this requires clang-formnat >= 9.0 13 | # AlignConsecutiveMacros: true 14 | 15 | AlignEscapedNewlines: Right 16 | AlignOperands: true 17 | AlignTrailingComments: true 18 | DerivePointerAlignment: false 19 | PointerAlignment: Left 20 | IndentCaseLabels: true 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | query_db/ 3 | exp_logs/ 4 | 5 | build/bin/* 6 | !build/bin/.gitkeep 7 | build/lib/* 8 | !build/lib/.gitkeep 9 | build/include/* 10 | !build/include/.gitkeep 11 | 12 | build-cmake/ 13 | 14 | *.o 15 | *.pyc 16 | *.z3-trace 17 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "fuzzolic-z3"] 2 | path = fuzzolic-z3 3 | url = https://github.com/season-lab/z3.git 4 | branch = fuzzolic 5 | [submodule "xxhash"] 6 | path = lib/xxhash 7 | url = https://github.com/Cyan4973/xxHash.git 8 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.7) 2 | 3 | set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) 4 | 5 | project(Z3Fuzzy) 6 | 7 | set(Z3_BUILD_PYTHON_BINDINGS true) 8 | add_subdirectory(fuzzolic-z3) 9 | add_subdirectory(lib) 10 | add_subdirectory(tools) 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc #clang 2 | CFLAGS=-Wall -s -O3 -fPIC #-O3 -g -fsanitize=address -fno-omit-frame-pointer -fPIC 3 | CLIBS=-lz3 4 | CLIB_PATHS=-L./fuzzolic-z3/build 5 | CINCLUDE=-I./fuzzolic-z3/src/api -I./lib 6 | 7 | SRC_LIB_DIR=./lib 8 | SRC_TOOLS_DIR=./tools 9 | BIN_DIR=./build/bin 10 | LIB_DIR=./build/lib 11 | INC_DIR=./build/include 12 | 13 | all: fuzzy-solver-notify fuzzy-solver-vs-z3 stats-collection-z3 stats-collection-fuzzy 14 | 15 | fuzzy-solver-notify: fuzzy-lib 16 | ${CC} ${CFLAGS} ${SRC_TOOLS_DIR}/fuzzy-solver-notify.c ${SRC_TOOLS_DIR}/pretty-print.c ${LIB_DIR}/libZ3Fuzzy.a -o ${BIN_DIR}/fuzzy-solver ${CINCLUDE} ${CLIB_PATHS} ${CLIBS} 17 | 18 | fuzzy-solver-vs-z3: fuzzy-lib 19 | ${CC} ${CFLAGS} ${SRC_TOOLS_DIR}/fuzzy-solver-vs-z3.c ${SRC_TOOLS_DIR}/pretty-print.c ${LIB_DIR}/libZ3Fuzzy.a -o ${BIN_DIR}/fuzzy-solver-vs-z3 ${CINCLUDE} ${CLIB_PATHS} ${CLIBS} 20 | 21 | stats-collection-z3: 22 | ${CC} ${CFLAGS} ${SRC_TOOLS_DIR}/stats-collection-z3.c ${SRC_TOOLS_DIR}/pretty-print.c -o ${BIN_DIR}/stats-collection-z3 ${CINCLUDE} ${CLIB_PATHS} ${CLIBS} 23 | 24 | stats-collection-fuzzy: fuzzy-lib 25 | ${CC} ${CFLAGS} ${SRC_TOOLS_DIR}/stats-collection-fuzzy.c ${SRC_TOOLS_DIR}/pretty-print.c ${LIB_DIR}/libZ3Fuzzy.a -o ${BIN_DIR}/stats-collection-fuzzy ${CINCLUDE} ${CLIB_PATHS} ${CLIBS} 26 | 27 | eval-driver: fuzzy-lib 28 | ${CC} ${CFLAGS} ${SRC_TOOLS_DIR}/eval-driver.c ${SRC_TOOLS_DIR}/pretty-print.c ${LIB_DIR}/libZ3Fuzzy.a -o ${BIN_DIR}/eval-driver ${CINCLUDE} ${CLIB_PATHS} ${CLIBS} 29 | 30 | maxmin-driver: fuzzy-lib 31 | ${CC} ${CFLAGS} ${SRC_TOOLS_DIR}/maxmin-driver.c ${SRC_TOOLS_DIR}/pretty-print.c ${LIB_DIR}/libZ3Fuzzy.a -o ${BIN_DIR}/maxmin-driver ${CINCLUDE} ${CLIB_PATHS} ${CLIBS} 32 | 33 | findall-driver: fuzzy-lib 34 | ${CC} ${CFLAGS} ${SRC_TOOLS_DIR}/findall-driver.c ${LIB_DIR}/libZ3Fuzzy.a -o ${BIN_DIR}/findall-driver ${CINCLUDE} ${CLIB_PATHS} ${CLIBS} 35 | 36 | debug-eval: fuzzy-lib 37 | ${CC} ${CFLAGS} ${SRC_TOOLS_DIR}/debug-eval.c ${SRC_TOOLS_DIR}/pretty-print.c ${LIB_DIR}/libZ3Fuzzy.a -o ${BIN_DIR}/debug-eval ${CINCLUDE} ${CLIB_PATHS} ${CLIBS} 38 | 39 | fuzzy-lib: 40 | ${CC} ${CFLAGS} -c ${SRC_LIB_DIR}/z3-fuzzy.c ${CINCLUDE} ${CLIB_PATHS} ${CLIBS} 41 | ${CC} ${CFLAGS} -c ${SRC_LIB_DIR}/md5.c ${CINCLUDE} ${CLIB_PATHS} ${CLIBS} 42 | ${CC} ${CFLAGS} -c ${SRC_LIB_DIR}/gradient_descend.c ${CINCLUDE} ${CLIB_PATHS} ${CLIBS} 43 | ${CC} ${CFLAGS} -c ${SRC_LIB_DIR}/wrapped_interval.c ${CINCLUDE} ${CLIB_PATHS} ${CLIBS} 44 | ${CC} ${CFLAGS} -c ${SRC_LIB_DIR}/timer.c ${CINCLUDE} ${CLIB_PATHS} ${CLIBS} 45 | ${CC} ${CFLAGS} -c ${SRC_LIB_DIR}/testcase-list.c ${CINCLUDE} ${CLIB_PATHS} ${CLIBS} 46 | ar rcs ${LIB_DIR}/libZ3Fuzzy.a z3-fuzzy.o testcase-list.o gradient_descend.o md5.o wrapped_interval.o timer.o 47 | cp ${SRC_LIB_DIR}/z3-fuzzy.h ${INC_DIR}/z3-fuzzy.h 48 | rm z3-fuzzy.o testcase-list.o gradient_descend.o md5.o wrapped_interval.o timer.o 49 | 50 | interval-test: 51 | ${CC} ${CFLAGS} interval_test.c ./lib/wrapped_interval.c -o interval_test 52 | 53 | clean: 54 | rm -f ${BIN_DIR}/fuzzy-solver ${BIN_DIR}/fuzzy-solver-vs-z3 ${LIB_DIR}/libZ3Fuzzy.a ${INC_DIR}/z3-fuzzy.h 55 | 56 | clean-tests: 57 | rm tests/* 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Fuzzy SAT 2 | 3 | [![CircleCI](https://circleci.com/gh/season-lab/fuzzy-sat.svg?style=shield&circle-token=426e6fc0f049c0a748ff3487716cb303ebe9a918)](https://app.circleci.com/pipelines/github/season-lab/fuzzy-sat) 4 | 5 | ### Build 6 | 7 | Clone the repository and all the submodules: 8 | ``` bash 9 | $ git clone https://github.com/season-lab/fuzzy-sat 10 | $ cd fuzzy-sat 11 | $ git submodule update --init --recursive 12 | ``` 13 | 14 | Build the library using `cmake`: 15 | ``` bash 16 | $ cd path/to/build/dir 17 | $ cmake -DCMAKE_BUILD_TYPE=Release path/to/fuzzy-sat/source 18 | $ make 19 | ``` 20 | 21 | It will build our fork of z3, the FuzzySAT library, and the command-line tools. 22 | 23 | ### How to use 24 | See https://season-lab.github.io/fuzzolic/usage.html#fuzzy-sat. 25 | -------------------------------------------------------------------------------- /build/bin/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/season-lab/fuzzy-sat/99094f664abcc7cb8ff7d04eb894616b89a15efc/build/bin/.gitkeep -------------------------------------------------------------------------------- /build/include/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/season-lab/fuzzy-sat/99094f664abcc7cb8ff7d04eb894616b89a15efc/build/include/.gitkeep -------------------------------------------------------------------------------- /build/lib/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/season-lab/fuzzy-sat/99094f664abcc7cb8ff7d04eb894616b89a15efc/build/lib/.gitkeep -------------------------------------------------------------------------------- /lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.7) 2 | 3 | # Strip the binary in release mode 4 | set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -s") 5 | 6 | set(z3fuzzy_src 7 | z3-fuzzy.c 8 | md5.c 9 | gradient_descend.c 10 | wrapped_interval.c 11 | timer.c 12 | testcase-list.c ) 13 | 14 | add_library(objZ3FuzzyLib OBJECT ${z3fuzzy_src}) 15 | 16 | set_property(TARGET objZ3FuzzyLib PROPERTY POSITION_INDEPENDENT_CODE 1) 17 | 18 | add_library(Z3Fuzzy_static STATIC $) 19 | add_library(Z3Fuzzy_shared SHARED $) 20 | 21 | target_include_directories (objZ3FuzzyLib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../fuzzolic-z3/src/api") 22 | target_link_libraries (Z3Fuzzy_shared LINK_PUBLIC libz3) 23 | 24 | set_target_properties(Z3Fuzzy_static PROPERTIES OUTPUT_NAME Z3Fuzzy) 25 | set_target_properties(Z3Fuzzy_shared PROPERTIES OUTPUT_NAME Z3Fuzzy) 26 | 27 | install(FILES z3-fuzzy.h DESTINATION include) 28 | -------------------------------------------------------------------------------- /lib/dict.h: -------------------------------------------------------------------------------- 1 | #ifndef DICT_H 2 | #define DICT_H 3 | 4 | #include 5 | #include 6 | 7 | #endif 8 | 9 | #ifndef DICT_N_BUCKETS 10 | #define DICT_N_BUCKETS 1024 11 | #endif 12 | 13 | #ifndef glue 14 | #define xglue(x, y) x##y 15 | #define glue(x, y) xglue(x, y) 16 | #endif 17 | 18 | #ifndef DICT_DATA_T 19 | #define DICT_DATA_T long 20 | #endif 21 | 22 | typedef struct glue(dict_el__, DICT_DATA_T) 23 | { 24 | unsigned long key; 25 | DICT_DATA_T el; 26 | } 27 | glue(dict_el_, DICT_DATA_T); 28 | 29 | #define DICT_EL glue(dict_el_, DICT_DATA_T) 30 | #define DA_DATA_T DICT_EL 31 | #define DA_INIT_SIZE 5 32 | #include "dynamic-array.h" 33 | 34 | typedef struct glue(dict__, DICT_DATA_T) 35 | { 36 | glue(da__, DICT_EL) * buckets; 37 | unsigned long size; 38 | unsigned long* filled_buckets; 39 | unsigned long filled_buckets_i; 40 | void (*free_el)(DICT_DATA_T*); 41 | } 42 | glue(dict__, DICT_DATA_T); 43 | 44 | static inline void glue(dict_init__, 45 | DICT_DATA_T)(glue(dict__, DICT_DATA_T) * dict, 46 | void (*free_el)(DICT_DATA_T*)) 47 | { 48 | dict->free_el = free_el; 49 | dict->filled_buckets_i = 0; 50 | dict->size = 0; 51 | dict->buckets = (glue(da__, DICT_EL)*)malloc(sizeof(glue(da__, DICT_EL)) * 52 | DICT_N_BUCKETS); 53 | assert(dict->buckets != 0 && "dict dict_init() - malloc failed"); 54 | dict->filled_buckets = 55 | (unsigned long*)malloc(sizeof(unsigned long) * DICT_N_BUCKETS); 56 | assert(dict->filled_buckets != 0 && "dict dict_init() - malloc failed"); 57 | 58 | // this memset is crucial 59 | memset(dict->buckets, 0, sizeof(glue(da__, DICT_EL)) * DICT_N_BUCKETS); 60 | } 61 | 62 | static inline void glue(dict_set__, 63 | DICT_DATA_T)(glue(dict__, DICT_DATA_T) * dict, 64 | unsigned long key, DICT_DATA_T el) 65 | { 66 | unsigned long bucket_id = key % DICT_N_BUCKETS; 67 | 68 | DICT_EL dict_el; 69 | glue(da__, DICT_EL)* bucket = &dict->buckets[bucket_id]; 70 | 71 | if (bucket->data == 0) { 72 | // uninitialized bucket 73 | dict->filled_buckets[dict->filled_buckets_i++] = bucket_id; 74 | glue(da_init__, DICT_EL)(bucket); 75 | 76 | dict_el.el = el; 77 | dict_el.key = key; 78 | dict->size++; 79 | glue(da_add_item__, DICT_EL)(bucket, dict_el); 80 | } else if (bucket->size == 0) { 81 | // initialized but empty (as a consequence of set_remove_all) 82 | dict->filled_buckets[dict->filled_buckets_i++] = bucket_id; 83 | 84 | dict_el.el = el; 85 | dict_el.key = key; 86 | dict->size++; 87 | glue(da_add_item__, DICT_EL)(bucket, dict_el); 88 | } else { 89 | // collision 90 | unsigned i, is_present = 0; 91 | for (i = 0; i < bucket->size; ++i) { 92 | DICT_EL* tmp = glue(da_get_ref_item__, DICT_EL)(bucket, i); 93 | if (tmp->key == key) { 94 | if (dict->free_el != 0) 95 | dict->free_el(&tmp->el); 96 | tmp->el = el; 97 | is_present = 1; 98 | break; 99 | } 100 | } 101 | if (!is_present) { 102 | dict_el.el = el; 103 | dict_el.key = key; 104 | dict->size++; 105 | glue(da_add_item__, DICT_EL)(bucket, dict_el); 106 | } 107 | } 108 | } 109 | 110 | static inline DICT_DATA_T* glue(dict_get_ref__, 111 | DICT_DATA_T)(glue(dict__, DICT_DATA_T) * dict, 112 | unsigned long key) 113 | { 114 | unsigned long bucket_id = key % DICT_N_BUCKETS; 115 | 116 | glue(da__, DICT_EL)* bucket = &dict->buckets[bucket_id]; 117 | 118 | if (bucket->data == 0) { 119 | return 0; 120 | } 121 | unsigned i; 122 | for (i = 0; i < bucket->size; ++i) { 123 | DICT_EL* tmp = glue(da_get_ref_item__, DICT_EL)(bucket, i); 124 | if (tmp->key == key) { 125 | return &tmp->el; 126 | } 127 | } 128 | return 0; 129 | } 130 | 131 | static inline void glue(dict_remove_all__, 132 | DICT_DATA_T)(glue(dict__, DICT_DATA_T) * dict) 133 | { 134 | unsigned long i; 135 | for (i = 0; i < dict->filled_buckets_i; ++i) { 136 | glue(da__, DICT_EL)* bucket = &dict->buckets[dict->filled_buckets[i]]; 137 | if (dict->free_el != 0) { 138 | unsigned long j; 139 | for (j = 0; j < bucket->size; ++j) 140 | dict->free_el(&bucket->data[j].el); 141 | } 142 | glue(da_remove_all__, DICT_EL)(bucket, NULL); 143 | } 144 | 145 | dict->size = 0; 146 | dict->filled_buckets_i = 0; 147 | } 148 | 149 | static inline void glue(dict_free__, 150 | DICT_DATA_T)(glue(dict__, DICT_DATA_T) * dict) 151 | { 152 | unsigned long i; 153 | for (i = 0; i < DICT_N_BUCKETS; ++i) { 154 | glue(da__, DICT_EL)* bucket = &dict->buckets[i]; 155 | if (bucket->data == 0) 156 | continue; 157 | if (dict->free_el != 0) { 158 | unsigned long j; 159 | for (j = 0; j < bucket->size; ++j) 160 | dict->free_el(&bucket->data[j].el); 161 | } 162 | glue(da_free__, DICT_EL)(bucket, 0); 163 | } 164 | free(dict->buckets); 165 | free(dict->filled_buckets); 166 | dict->buckets = 0; 167 | dict->filled_buckets = 0; 168 | dict->size = 0; 169 | } 170 | 171 | #undef DICT_DATA_T 172 | #undef DICT_N_BUCKETS 173 | -------------------------------------------------------------------------------- /lib/dynamic-array.h: -------------------------------------------------------------------------------- 1 | #ifndef DYNAMIC_ARRAY_H 2 | #define DYNAMIC_ARRAY_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #endif 9 | 10 | #ifndef glue 11 | #define xglue(x, y) x##y 12 | #define glue(x, y) xglue(x, y) 13 | #endif 14 | 15 | #ifndef DA_INIT_SIZE 16 | #define DA_INIT_SIZE 100 17 | #endif 18 | 19 | #ifndef DA_DATA_T 20 | #define DA_DATA_T long 21 | #endif 22 | 23 | typedef struct glue(da__, DA_DATA_T) 24 | { 25 | DA_DATA_T* data; 26 | unsigned long max_size; 27 | unsigned long size; 28 | } 29 | glue(da__, DA_DATA_T); 30 | 31 | static inline void glue(da_init__, DA_DATA_T)(glue(da__, DA_DATA_T) * da) 32 | { 33 | da->data = (DA_DATA_T*)malloc(DA_INIT_SIZE * sizeof(DA_DATA_T)); 34 | assert(da->data != 0 && "dynamic-array da_init() - malloc failed"); 35 | da->max_size = DA_INIT_SIZE; 36 | da->size = 0; 37 | } 38 | 39 | static inline void glue(da_free__, DA_DATA_T)(glue(da__, DA_DATA_T) * da, 40 | void (*el_free)(DA_DATA_T*)) 41 | { 42 | if (el_free != NULL) { 43 | unsigned long i; 44 | for (i = 0; i < da->size; ++i) 45 | el_free(&da->data[i]); 46 | } 47 | free(da->data); 48 | da->data = NULL; 49 | da->max_size = 0; 50 | da->size = 0; 51 | } 52 | 53 | static inline void glue(da_remove_all__, DA_DATA_T)(glue(da__, DA_DATA_T) * da, 54 | void (*el_free)(DA_DATA_T*)) 55 | { 56 | // memset((void*)da->data, 0, da->size * sizeof(DA_DATA_T)); 57 | if (el_free != NULL) { 58 | unsigned long i; 59 | for (i = 0; i < da->size; ++i) 60 | el_free(&da->data[i]); 61 | } 62 | da->data = 63 | da->max_size > DA_INIT_SIZE 64 | ? (DA_DATA_T*)realloc(da->data, DA_INIT_SIZE * sizeof(DA_DATA_T)) 65 | : da->data; 66 | assert(da->data != 0 && "dynamic-array da_remove_all() - realloc failed"); 67 | da->max_size = DA_INIT_SIZE; 68 | da->size = 0; 69 | } 70 | 71 | static inline void glue(da_add_item__, DA_DATA_T)(glue(da__, DA_DATA_T) * da, 72 | DA_DATA_T el) 73 | { 74 | if (da->size >= da->max_size) { 75 | da->max_size *= 2; 76 | da->data = (DA_DATA_T*)realloc((void*)da->data, 77 | da->max_size * sizeof(DA_DATA_T)); 78 | assert(da->data != 0 && "dynamic-array da_add_item() - realloc failed"); 79 | } 80 | da->data[da->size++] = el; 81 | } 82 | 83 | static inline DA_DATA_T glue(da_get_item__, 84 | DA_DATA_T)(glue(da__, DA_DATA_T) * da, 85 | unsigned long idx) 86 | { 87 | assert(idx < da->size && "dynamic-array get_item() - out of range"); 88 | return da->data[idx]; 89 | } 90 | 91 | static inline DA_DATA_T* glue(da_get_ref_item__, 92 | DA_DATA_T)(glue(da__, DA_DATA_T) * da, 93 | unsigned long idx) 94 | { 95 | assert(idx < da->size && "dynamic-array get_ref_item() - out of range"); 96 | return &da->data[idx]; 97 | } 98 | 99 | #undef DA_DATA_T 100 | #undef DA_INIT_SIZE 101 | -------------------------------------------------------------------------------- /lib/gradient_descend.h: -------------------------------------------------------------------------------- 1 | #ifndef GRADIENT_DESCEND_H 2 | #define GRADIENT_DESCEND_H 3 | 4 | #include 5 | 6 | void gd_init(); 7 | void gd_free(); 8 | 9 | int gd_minimize(uint64_t (*function)(uint64_t*, int*), uint64_t* x0, 10 | uint64_t* out_x_min, uint64_t* out_f_min, uint32_t n); 11 | 12 | int gd_descend_transf(uint64_t (*function)(uint64_t*, int*), uint64_t* x0, 13 | uint64_t* out_x, uint64_t* out_f, uint32_t n); 14 | int gd_max_gradient(uint64_t (*function)(uint64_t*, int*), uint64_t* x0, 15 | uint32_t n, uint64_t* v); 16 | 17 | #endif -------------------------------------------------------------------------------- /lib/md5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * rfc1321 requires that I include this. The code is new. The constants 3 | * all come from the rfc (hence the copyright). We trade a table for the 4 | * macros in rfc. The total size is a lot less. 5 | * presotto@plan9.bell-labs.com (with tweaks by ehg@netlib.bell-labs.com) 6 | * 7 | * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 8 | * rights reserved. 9 | * 10 | * License to copy and use this software is granted provided that it 11 | * is identified as the "RSA Data Security, Inc. MD5 Message-Digest 12 | * Algorithm" in all material mentioning or referencing this software 13 | * or this function. 14 | * 15 | * License is also granted to make and use derivative works provided 16 | * that such works are identified as "derived from the RSA Data 17 | * Security, Inc. MD5 Message-Digest Algorithm" in all material 18 | * mentioning or referencing the derived work. 19 | * 20 | * RSA Data Security, Inc. makes no representations concerning either 21 | * the merchantability of this software or the suitability of this 22 | * software forany particular purpose. It is provided "as is" 23 | * without express or implied warranty of any kind. 24 | * These notices must be retained in any copies of any part of this 25 | * documentation and/or software. 26 | */ 27 | 28 | #include 29 | #include 30 | typedef unsigned int uint; 31 | typedef unsigned char byte; 32 | 33 | /* 34 | * Rotate amounts used in the algorithm 35 | */ 36 | enum 37 | { 38 | S11= 7, 39 | S12= 12, 40 | S13= 17, 41 | S14= 22, 42 | 43 | S21= 5, 44 | S22= 9, 45 | S23= 14, 46 | S24= 20, 47 | 48 | S31= 4, 49 | S32= 11, 50 | S33= 16, 51 | S34= 23, 52 | 53 | S41= 6, 54 | S42= 10, 55 | S43= 15, 56 | S44= 21 57 | }; 58 | 59 | 60 | typedef struct Table 61 | { 62 | uint sin; /* integer part of 4294967296 times abs(sin(i)) */ 63 | byte x; /* index into data block */ 64 | byte rot; /* amount to rotate left by */ 65 | }Table; 66 | 67 | Table tab[] = 68 | { 69 | /* round 1 */ 70 | { 0xd76aa478, 0, S11}, 71 | { 0xe8c7b756, 1, S12}, 72 | { 0x242070db, 2, S13}, 73 | { 0xc1bdceee, 3, S14}, 74 | { 0xf57c0faf, 4, S11}, 75 | { 0x4787c62a, 5, S12}, 76 | { 0xa8304613, 6, S13}, 77 | { 0xfd469501, 7, S14}, 78 | { 0x698098d8, 8, S11}, 79 | { 0x8b44f7af, 9, S12}, 80 | { 0xffff5bb1, 10, S13}, 81 | { 0x895cd7be, 11, S14}, 82 | { 0x6b901122, 12, S11}, 83 | { 0xfd987193, 13, S12}, 84 | { 0xa679438e, 14, S13}, 85 | { 0x49b40821, 15, S14}, 86 | 87 | /* round 2 */ 88 | { 0xf61e2562, 1, S21}, 89 | { 0xc040b340, 6, S22}, 90 | { 0x265e5a51, 11, S23}, 91 | { 0xe9b6c7aa, 0, S24}, 92 | { 0xd62f105d, 5, S21}, 93 | { 0x2441453, 10, S22}, 94 | { 0xd8a1e681, 15, S23}, 95 | { 0xe7d3fbc8, 4, S24}, 96 | { 0x21e1cde6, 9, S21}, 97 | { 0xc33707d6, 14, S22}, 98 | { 0xf4d50d87, 3, S23}, 99 | { 0x455a14ed, 8, S24}, 100 | { 0xa9e3e905, 13, S21}, 101 | { 0xfcefa3f8, 2, S22}, 102 | { 0x676f02d9, 7, S23}, 103 | { 0x8d2a4c8a, 12, S24}, 104 | 105 | /* round 3 */ 106 | { 0xfffa3942, 5, S31}, 107 | { 0x8771f681, 8, S32}, 108 | { 0x6d9d6122, 11, S33}, 109 | { 0xfde5380c, 14, S34}, 110 | { 0xa4beea44, 1, S31}, 111 | { 0x4bdecfa9, 4, S32}, 112 | { 0xf6bb4b60, 7, S33}, 113 | { 0xbebfbc70, 10, S34}, 114 | { 0x289b7ec6, 13, S31}, 115 | { 0xeaa127fa, 0, S32}, 116 | { 0xd4ef3085, 3, S33}, 117 | { 0x4881d05, 6, S34}, 118 | { 0xd9d4d039, 9, S31}, 119 | { 0xe6db99e5, 12, S32}, 120 | { 0x1fa27cf8, 15, S33}, 121 | { 0xc4ac5665, 2, S34}, 122 | 123 | /* round 4 */ 124 | { 0xf4292244, 0, S41}, 125 | { 0x432aff97, 7, S42}, 126 | { 0xab9423a7, 14, S43}, 127 | { 0xfc93a039, 5, S44}, 128 | { 0x655b59c3, 12, S41}, 129 | { 0x8f0ccc92, 3, S42}, 130 | { 0xffeff47d, 10, S43}, 131 | { 0x85845dd1, 1, S44}, 132 | { 0x6fa87e4f, 8, S41}, 133 | { 0xfe2ce6e0, 15, S42}, 134 | { 0xa3014314, 6, S43}, 135 | { 0x4e0811a1, 13, S44}, 136 | { 0xf7537e82, 4, S41}, 137 | { 0xbd3af235, 11, S42}, 138 | { 0x2ad7d2bb, 2, S43}, 139 | { 0xeb86d391, 9, S44}, 140 | }; 141 | 142 | typedef struct MD5state 143 | { 144 | uint len; 145 | uint state[4]; 146 | }MD5state; 147 | 148 | struct MD5state md5_state = {0}; 149 | 150 | /* 151 | * encodes input (uint) into output (byte). Assumes len is 152 | * a multiple of 4. 153 | */ 154 | static void 155 | encode(byte *output, uint *input, uint len) 156 | { 157 | uint x; 158 | byte *e; 159 | 160 | for(e = output + len; output < e;) { 161 | x = *input++; 162 | *output++ = x; 163 | *output++ = x >> 8; 164 | *output++ = x >> 16; 165 | *output++ = x >> 24; 166 | } 167 | } 168 | 169 | /* 170 | * decodes input (byte) into output (uint). Assumes len is 171 | * a multiple of 4. 172 | */ 173 | static void 174 | decode(uint *output, byte *input, uint len) 175 | { 176 | byte *e; 177 | 178 | for(e = input+len; input < e; input += 4) 179 | *output++ = input[0] | (input[1] << 8) | 180 | (input[2] << 16) | (input[3] << 24); 181 | } 182 | 183 | static MD5state* 184 | _md5(byte *p, uint len, byte *digest, MD5state *s) 185 | { 186 | uint a, b, c, d, tmp; 187 | uint i, done; 188 | Table *t; 189 | byte *end; 190 | uint x[16]; 191 | 192 | s->len += len; 193 | 194 | i = len & 0x3f; 195 | if(i || len == 0){ 196 | done = 1; 197 | 198 | /* pad the input, assume there's room */ 199 | if(i < 56) 200 | i = 56 - i; 201 | else 202 | i = 120 - i; 203 | if(i > 0){ 204 | memset(p + len, 0, i); 205 | p[len] = 0x80; 206 | } 207 | len += i; 208 | 209 | /* append the count */ 210 | x[0] = s->len<<3; 211 | x[1] = s->len>>29; 212 | encode(p+len, x, 8); 213 | } else 214 | done = 0; 215 | 216 | for(end = p+len; p < end; p += 64){ 217 | a = s->state[0]; 218 | b = s->state[1]; 219 | c = s->state[2]; 220 | d = s->state[3]; 221 | 222 | decode(x, p, 64); 223 | 224 | for(i = 0; i < 64; i++){ 225 | t = tab + i; 226 | switch(i>>4){ 227 | case 0: 228 | a += (b & c) | (~b & d); 229 | break; 230 | case 1: 231 | a += (b & d) | (c & ~d); 232 | break; 233 | case 2: 234 | a += b ^ c ^ d; 235 | break; 236 | case 3: 237 | a += c ^ (b | ~d); 238 | break; 239 | } 240 | a += x[t->x] + t->sin; 241 | a = (a << t->rot) | (a >> (32 - t->rot)); 242 | a += b; 243 | 244 | /* rotate variables */ 245 | tmp = d; 246 | d = c; 247 | c = b; 248 | b = a; 249 | a = tmp; 250 | } 251 | 252 | s->state[0] += a; 253 | s->state[1] += b; 254 | s->state[2] += c; 255 | s->state[3] += d; 256 | } 257 | 258 | /* return result */ 259 | if(done){ 260 | encode(digest, s->state, 16); 261 | return NULL; 262 | } 263 | return s; 264 | } 265 | 266 | void 267 | md5(unsigned char *p, unsigned len, unsigned char *digest) { 268 | md5_state.state[0] = 0x67452301; 269 | md5_state.state[1] = 0xefcdab89; 270 | md5_state.state[2] = 0x98badcfe; 271 | md5_state.state[3] = 0x10325476; 272 | md5_state.len = 0; 273 | 274 | byte copy_p[len + 64]; 275 | memcpy(copy_p, p, len); 276 | 277 | _md5((byte*)copy_p, len, (byte*)digest, &md5_state); 278 | } 279 | -------------------------------------------------------------------------------- /lib/md5.h: -------------------------------------------------------------------------------- 1 | #ifndef MD5_H 2 | #define MD5_H 3 | 4 | void md5(unsigned char *p, unsigned len, unsigned char *digest); 5 | 6 | #endif -------------------------------------------------------------------------------- /lib/set.h: -------------------------------------------------------------------------------- 1 | #ifndef SET_H 2 | #define SET_H 3 | 4 | #include 5 | 6 | typedef struct set_iter_t { 7 | // unsigned free; // TODO I should implement this 8 | unsigned long iter_buck_id; 9 | unsigned long iter_el_in_buck_id; 10 | } set_iter_t; 11 | 12 | #define NUM_ITERATORS 2 13 | 14 | #endif 15 | 16 | #ifndef SET_N_BUCKETS 17 | #define SET_N_BUCKETS 1024 18 | #endif 19 | 20 | #ifndef glue 21 | #define xglue(x, y) x##y 22 | #define glue(x, y) xglue(x, y) 23 | #endif 24 | 25 | #ifndef SET_DATA_T 26 | #define SET_DATA_T long 27 | #endif 28 | 29 | #define DA_DATA_T SET_DATA_T 30 | #define DA_INIT_SIZE 5 31 | #include "dynamic-array.h" 32 | 33 | typedef struct glue(set__, SET_DATA_T) 34 | { 35 | unsigned long (*hash)(SET_DATA_T*); 36 | unsigned int (*equals)(SET_DATA_T*, SET_DATA_T*); 37 | glue(da__, SET_DATA_T) * buckets; 38 | unsigned long* filled_buckets; 39 | unsigned long filled_buckets_i; 40 | unsigned long size; 41 | set_iter_t iterators[NUM_ITERATORS]; 42 | } 43 | glue(set__, SET_DATA_T); 44 | 45 | static inline void glue(set_init__, SET_DATA_T)( 46 | glue(set__, SET_DATA_T) * set, unsigned long (*hash_function)(SET_DATA_T*), 47 | unsigned int (*equals)(SET_DATA_T*, SET_DATA_T*)) 48 | { 49 | set->hash = hash_function; 50 | set->equals = equals; 51 | set->filled_buckets_i = 0; 52 | set->size = 0; 53 | memset(set->iterators, 0, sizeof(set_iter_t) * NUM_ITERATORS); 54 | set->buckets = (glue(da__, SET_DATA_T)*)malloc( 55 | sizeof(glue(da__, SET_DATA_T)) * SET_N_BUCKETS); 56 | assert(set->buckets != 0 && "set set_init() - malloc failed"); 57 | set->filled_buckets = 58 | (unsigned long*)malloc(sizeof(unsigned long) * SET_N_BUCKETS); 59 | assert(set->filled_buckets != 0 && "set set_init() - malloc failed"); 60 | 61 | // this memset is crucial 62 | memset(set->buckets, 0, sizeof(glue(da__, SET_DATA_T)) * SET_N_BUCKETS); 63 | } 64 | 65 | static inline void glue(set_add__, SET_DATA_T)(glue(set__, SET_DATA_T) * set, 66 | SET_DATA_T el) 67 | { 68 | unsigned long el_hash = set->hash((SET_DATA_T*)&el); 69 | unsigned long bucket_id = el_hash % SET_N_BUCKETS; 70 | 71 | // printf("se_add() hash=%lu, buck_id=%lu\n", el_hash, bucket_id); 72 | 73 | glue(da__, SET_DATA_T)* bucket = &set->buckets[bucket_id]; 74 | 75 | if (bucket->data == NULL) { 76 | // uninitialized bucket 77 | set->filled_buckets[set->filled_buckets_i++] = bucket_id; 78 | glue(da_init__, SET_DATA_T)(bucket); 79 | glue(da_add_item__, SET_DATA_T)(bucket, el); 80 | set->size++; 81 | } else if (bucket->size == 0) { 82 | // initialized but empty (as a consequence of set_remove_all) 83 | set->filled_buckets[set->filled_buckets_i++] = bucket_id; 84 | glue(da_add_item__, SET_DATA_T)(bucket, el); 85 | set->size++; 86 | } else { 87 | // collision 88 | unsigned i, is_present = 0; 89 | for (i = 0; i < bucket->size; ++i) { 90 | SET_DATA_T* tmp = glue(da_get_ref_item__, SET_DATA_T)(bucket, i); 91 | if (set->hash((SET_DATA_T*)tmp) == el_hash && 92 | set->equals((SET_DATA_T*)tmp, (SET_DATA_T*)&el)) { 93 | is_present = 1; 94 | break; 95 | } 96 | } 97 | if (!is_present) { 98 | glue(da_add_item__, SET_DATA_T)(bucket, el); 99 | set->size++; 100 | } 101 | } 102 | } 103 | 104 | static inline int glue(set_check__, SET_DATA_T)(glue(set__, SET_DATA_T) * set, 105 | SET_DATA_T el) 106 | { 107 | unsigned long el_hash = set->hash((SET_DATA_T*)&el); 108 | unsigned long bucket_id = el_hash % SET_N_BUCKETS; 109 | 110 | glue(da__, SET_DATA_T)* bucket = &set->buckets[bucket_id]; 111 | 112 | if (bucket->data == 0) { 113 | return 0; 114 | } 115 | unsigned i, is_present = 0; 116 | for (i = 0; i < bucket->size; ++i) { 117 | SET_DATA_T* tmp = glue(da_get_ref_item__, SET_DATA_T)(bucket, i); 118 | if (set->equals((SET_DATA_T*)tmp, (SET_DATA_T*)&el)) { 119 | is_present = 1; 120 | break; 121 | } 122 | } 123 | return (int)is_present; 124 | } 125 | 126 | static inline void glue(set_reset_iter__, 127 | SET_DATA_T)(glue(set__, SET_DATA_T) * set, 128 | unsigned iterator_id) 129 | { 130 | assert(iterator_id < NUM_ITERATORS && 131 | "set_reset_iter() iterator_id overflow"); 132 | set->iterators[iterator_id].iter_buck_id = 0; 133 | set->iterators[iterator_id].iter_el_in_buck_id = 0; 134 | } 135 | 136 | static inline int glue(set_iter_next__, 137 | SET_DATA_T)(glue(set__, SET_DATA_T) * set, 138 | unsigned iterator_id, SET_DATA_T** res) 139 | { 140 | assert(iterator_id < NUM_ITERATORS && 141 | "set_iter_next() iterator_id overflow"); 142 | if (set->iterators[iterator_id].iter_buck_id >= set->filled_buckets_i) 143 | return 0; 144 | glue(da__, SET_DATA_T)* bucket = 145 | &set->buckets 146 | [set->filled_buckets[set->iterators[iterator_id].iter_buck_id]]; 147 | if (set->iterators[iterator_id].iter_el_in_buck_id >= bucket->size) { 148 | set->iterators[iterator_id].iter_buck_id++; 149 | set->iterators[iterator_id].iter_el_in_buck_id = 0; 150 | return glue(set_iter_next__, SET_DATA_T)(set, iterator_id, res); 151 | } 152 | 153 | *res = glue(da_get_ref_item__, SET_DATA_T)( 154 | bucket, set->iterators[iterator_id].iter_el_in_buck_id); 155 | set->iterators[iterator_id].iter_el_in_buck_id++; 156 | return 1; 157 | } 158 | 159 | static inline SET_DATA_T* glue(set_find_el__, 160 | SET_DATA_T)(glue(set__, SET_DATA_T) * set, 161 | SET_DATA_T* el) 162 | { 163 | unsigned long el_hash = set->hash(el); 164 | unsigned long bucket_id = el_hash % SET_N_BUCKETS; 165 | 166 | glue(da__, SET_DATA_T)* bucket = &set->buckets[bucket_id]; 167 | 168 | if (bucket->data == 0) { 169 | return 0; 170 | } 171 | unsigned i; 172 | for (i = 0; i < bucket->size; ++i) { 173 | SET_DATA_T* tmp = glue(da_get_ref_item__, SET_DATA_T)(bucket, i); 174 | if (set->hash((SET_DATA_T*)tmp) == el_hash && 175 | set->equals((SET_DATA_T*)tmp, (SET_DATA_T*)el)) 176 | return tmp; 177 | } 178 | return 0; 179 | } 180 | 181 | // TODO I should implement a _get_free_iter_ and _release_iter_ 182 | 183 | static inline void glue(set_remove_all__, 184 | SET_DATA_T)(glue(set__, SET_DATA_T) * set, 185 | void (*el_free)(SET_DATA_T*)) 186 | { 187 | unsigned long i; 188 | for (i = 0; i < set->filled_buckets_i; ++i) 189 | glue(da_remove_all__, SET_DATA_T)(&set->buckets[set->filled_buckets[i]], 190 | el_free); 191 | 192 | set->filled_buckets_i = 0; 193 | set->size = 0; 194 | } 195 | 196 | static inline void glue(set_free__, SET_DATA_T)(glue(set__, SET_DATA_T) * set, 197 | void (*el_free)(SET_DATA_T*)) 198 | { 199 | unsigned long i; 200 | for (i = 0; i < SET_N_BUCKETS; ++i) 201 | if (set->buckets[i].data != 0) 202 | glue(da_free__, SET_DATA_T)(&set->buckets[i], el_free); 203 | free(set->buckets); 204 | free(set->filled_buckets); 205 | set->buckets = NULL; 206 | set->filled_buckets = NULL; 207 | set->size = 0; 208 | } 209 | 210 | #undef SET_DATA_T 211 | #undef SET_N_BUCKETS 212 | -------------------------------------------------------------------------------- /lib/testcase-list.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "testcase-list.h" 5 | 6 | #ifndef likely 7 | #define likely(x) __builtin_expect(!!(x), 1) 8 | #endif 9 | #ifndef unlikely 10 | #define unlikely(x) __builtin_expect(!!(x), 0) 11 | #endif 12 | 13 | #define ASSERT_OR_ABORT(x, mex) \ 14 | if (unlikely(!(x))) { \ 15 | fprintf(stderr, "[testcase-lib ABORT] " mex "\n"); \ 16 | abort(); \ 17 | } 18 | #define TESTCASE_LIB_LOG(x...) fprintf(stderr, "[testcase-lib] " x) 19 | 20 | void init_testcase_list(testcase_list_t* t) { da_init__testcase_t(t); } 21 | 22 | void free_testcase_list(Z3_context ctx, testcase_list_t* t) 23 | { 24 | unsigned int i, j; 25 | for (i = 0; i < t->size; ++i) { 26 | free(t->data[i].values); 27 | t->data[i].values = NULL; 28 | for (j = 0; j < t->data[i].values_len; ++j) 29 | if (t->data[i].z3_values[j] != NULL) 30 | Z3_dec_ref(ctx, t->data[i].z3_values[j]); 31 | free(t->data[i].z3_values); 32 | t->data[i].z3_values = NULL; 33 | free(t->data[i].value_sizes); 34 | t->data[i].value_sizes = NULL; 35 | } 36 | t->size = 0; 37 | da_free__testcase_t(t, NULL); 38 | } 39 | 40 | void load_testcase(testcase_list_t* t, char const* filename, Z3_context ctx) 41 | { 42 | ASSERT_OR_ABORT(t->size < t->max_size, "testcase_list is full"); 43 | 44 | // TESTCASE_LIB_LOG("Loading testcase \"%s\" \n", filename); 45 | 46 | testcase_t tc = {0}; 47 | FILE* fp = fopen(filename, "r"); 48 | int res, i = 0; 49 | unsigned char c; 50 | 51 | ASSERT_OR_ABORT(fp != NULL, "fopen() failed"); 52 | 53 | fseek(fp, 0L, SEEK_END); 54 | tc.testcase_len = ftell(fp); 55 | tc.values_len = tc.testcase_len; 56 | fseek(fp, 0L, SEEK_SET); 57 | 58 | tc.values = (unsigned long*)malloc(sizeof(unsigned long) * tc.values_len); 59 | tc.z3_values = (Z3_ast*)malloc(sizeof(Z3_ast) * tc.values_len); 60 | tc.value_sizes = 61 | (unsigned char*)malloc(sizeof(unsigned char) * tc.values_len); 62 | 63 | Z3_sort bv_sort = Z3_mk_bv_sort(ctx, 8); 64 | while (1) { 65 | res = fread(&c, sizeof(char), 1, fp); 66 | if (res != 1) 67 | break; 68 | tc.values[i] = (unsigned long)c; 69 | tc.value_sizes[i] = 8; 70 | tc.z3_values[i] = Z3_mk_unsigned_int(ctx, c, bv_sort); 71 | Z3_inc_ref(ctx, tc.z3_values[i]); 72 | i++; 73 | } 74 | da_add_item__testcase_t(t, tc); 75 | fclose(fp); 76 | } 77 | 78 | void load_testcase_folder(testcase_list_t* t, char* testcase_dir, 79 | Z3_context ctx) 80 | { 81 | FTS* ftsp; 82 | FTSENT * p, *chp; 83 | int fts_options = FTS_LOGICAL | FTS_NOCHDIR; 84 | char* const file_list[] = {testcase_dir, NULL}; 85 | 86 | TESTCASE_LIB_LOG("Loading testcases from folder \"%s\" \n", testcase_dir); 87 | 88 | ftsp = fts_open(file_list, fts_options, NULL); 89 | ASSERT_OR_ABORT(ftsp != NULL, "error in fts_open"); 90 | 91 | chp = fts_children(ftsp, 0); 92 | ASSERT_OR_ABORT(chp != NULL, "error in fts_children"); 93 | 94 | while ((p = fts_read(ftsp)) != NULL) { 95 | switch (p->fts_info) { 96 | case FTS_D: 97 | TESTCASE_LIB_LOG("found directory\t %s skipping\n", 98 | p->fts_path); 99 | break; 100 | case FTS_F: 101 | load_testcase(t, p->fts_path, ctx); 102 | break; 103 | default: 104 | break; 105 | } 106 | } 107 | fts_close(ftsp); 108 | } 109 | -------------------------------------------------------------------------------- /lib/testcase-list.h: -------------------------------------------------------------------------------- 1 | #ifndef TESTCASE_LIST_H 2 | #define TESTCASE_LIST_H 3 | 4 | #include 5 | 6 | typedef struct testcase_t { 7 | unsigned long* values; 8 | Z3_ast* z3_values; 9 | unsigned char* value_sizes; 10 | unsigned values_len; 11 | unsigned testcase_len; 12 | } testcase_t; 13 | 14 | #define DA_DATA_T testcase_t 15 | #include "dynamic-array.h" 16 | 17 | typedef da__testcase_t testcase_list_t; 18 | 19 | void init_testcase_list(testcase_list_t* t); 20 | void free_testcase_list(Z3_context ctx, testcase_list_t* t); 21 | void load_testcase_folder(testcase_list_t* t, char* testcase_dir, 22 | Z3_context ctx); 23 | void load_testcase(testcase_list_t* t, char const* filename, Z3_context ctx); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /lib/timer.c: -------------------------------------------------------------------------------- 1 | #include "timer.h" 2 | 3 | #ifndef likely 4 | #define likely(x) __builtin_expect(!!(x), 1) 5 | #endif 6 | #ifndef unlikely 7 | #define unlikely(x) __builtin_expect(!!(x), 0) 8 | #endif 9 | 10 | static struct timeval stop; 11 | 12 | static inline unsigned long compute_time_msec(struct timeval* start, 13 | struct timeval* end) 14 | { 15 | return ((end->tv_sec - start->tv_sec) * 1000000 + end->tv_usec - 16 | start->tv_usec) / 17 | 1000; 18 | } 19 | 20 | static inline unsigned long compute_time_usec(struct timeval* start, 21 | struct timeval* end) 22 | { 23 | return ((end->tv_sec - start->tv_sec) * 1000000 + end->tv_usec - 24 | start->tv_usec); 25 | } 26 | 27 | void init_timer(simple_timer_t* t, uint64_t time_max_msec) 28 | { 29 | t->time_max_msec = time_max_msec; 30 | } 31 | 32 | void start_timer(simple_timer_t* t) { gettimeofday(&t->start, 0); } 33 | 34 | int check_timer(simple_timer_t* t) 35 | { 36 | gettimeofday(&stop, 0); 37 | unsigned long delta_time = compute_time_msec(&t->start, &stop); 38 | if (delta_time > t->time_max_msec) 39 | return 1; 40 | return 0; 41 | } 42 | 43 | unsigned long get_elapsed_time(simple_timer_t* t) 44 | { 45 | gettimeofday(&stop, 0); 46 | unsigned long delta_time = compute_time_usec(&t->start, &stop); 47 | return delta_time; 48 | } -------------------------------------------------------------------------------- /lib/timer.h: -------------------------------------------------------------------------------- 1 | #ifndef TIMER_H 2 | #define TIMER_H 3 | 4 | #include 5 | #include 6 | 7 | typedef struct simple_timer_t { 8 | struct timeval start; 9 | uint64_t time_max_msec; 10 | } simple_timer_t; 11 | 12 | void init_timer(simple_timer_t* t, uint64_t time_max_msec); 13 | void start_timer(simple_timer_t* t); 14 | int check_timer(simple_timer_t* t); 15 | unsigned long get_elapsed_time(simple_timer_t* t); 16 | 17 | #endif -------------------------------------------------------------------------------- /lib/wrapped_interval.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "wrapped_interval.h" 4 | 5 | #define DEBUG 0 6 | 7 | #ifndef likely 8 | #define likely(x) __builtin_expect(!!(x), 1) 9 | #endif 10 | #ifndef unlikely 11 | #define unlikely(x) __builtin_expect(!!(x), 0) 12 | #endif 13 | 14 | #define ASSERT_OR_ABORT(x, mex) \ 15 | if (unlikely(!(x))) { \ 16 | fprintf(stderr, "[interval ABORT] " mex "\n"); \ 17 | abort(); \ 18 | } 19 | #define _min(a, b) ((a) < (b) ? (a) : (b)) 20 | #define _max(a, b) ((a) > (b) ? (a) : (b)) 21 | 22 | static inline int is_signed_op(optype op) 23 | { 24 | return !(op == OP_ULT || op == OP_ULE || op == OP_UGT || op == OP_UGE); 25 | } 26 | 27 | static inline uint64_t sext(uint64_t c, uint32_t size) 28 | { 29 | uint64_t mask = 1UL << (size - 1UL); 30 | if (c & mask) { 31 | c |= ((2UL << (64UL - size - 1UL)) - 1UL) << size; 32 | return c; 33 | } 34 | return c; 35 | } 36 | 37 | static inline uint64_t get_size_mask(uint32_t size) 38 | { 39 | uint64_t res = 0; 40 | res |= (2UL << (size - 1UL)) - 1UL; 41 | return res; 42 | } 43 | 44 | static inline uint64_t get_signed_min(uint32_t size) 45 | { 46 | if (size < 2) 47 | return 0; 48 | uint64_t res = 1UL << (size - 1UL); 49 | return res; 50 | } 51 | 52 | static inline uint64_t get_signed_max(uint32_t size) 53 | { 54 | if (size < 2) 55 | return 0; 56 | return get_signed_min(size) - 1; 57 | } 58 | 59 | static inline int is_wrapping(const wrapped_interval_t* interval) 60 | { 61 | return interval->min > interval->max; 62 | } 63 | 64 | static inline int is_right_of(uint64_t v1, uint64_t v2, uint32_t size) 65 | { 66 | return ((v1 - v2) & get_size_mask(size)) <= 67 | ((v2 - v1) & get_size_mask(size)); 68 | } 69 | 70 | static inline int is_left_of(uint64_t v1, uint64_t v2, uint32_t size) 71 | { 72 | return !is_right_of(v1, v2, size); 73 | } 74 | 75 | static inline int wi_check_intersect(const wrapped_interval_t* int1, 76 | const wrapped_interval_t* int2) 77 | { 78 | if (is_wrapping(int1) && is_wrapping(int2)) 79 | return 1; 80 | if (!is_wrapping(int1) && is_wrapping(int2)) 81 | return int1->min <= int2->max || int1->max >= int2->min; 82 | if (is_wrapping(int1) && !is_wrapping(int2)) 83 | return int2->min <= int1->max || int2->max >= int1->min; 84 | return _max(int1->min, int2->min) <= _min(int2->max, int2->max); 85 | } 86 | 87 | int wi_intersect(wrapped_interval_t* int1, const wrapped_interval_t* int2) 88 | { 89 | // Overapproximation 90 | // -> side-effect on int1 91 | #if DEBUG 92 | printf("intersection:\n 1) "); 93 | wi_print(int1); 94 | printf(" 2) "); 95 | wi_print(int2); 96 | #endif 97 | if (!wi_check_intersect(int1, int2)) 98 | return 0; 99 | 100 | if (!is_wrapping(int1) && !is_wrapping(int2)) { 101 | int1->min = _max(int1->min, int2->min); 102 | int1->max = _min(int1->max, int2->max); 103 | } else { 104 | if (wi_contains_element(int2, int1->max) && 105 | !wi_contains_element(int2, int1->min)) { 106 | /* 107 | * +--------+ 108 | * +------|-+ | 109 | * | I1 | | I2 | 110 | * +------|-+ | 111 | * +--------+ 112 | */ 113 | int1->min = int2->min; 114 | // int1->max = int1->max; 115 | } else if (wi_contains_element(int2, int1->min) && 116 | !wi_contains_element(int2, int1->max)) { 117 | /* 118 | * +--------+ 119 | * +------|-+ | 120 | * | I2 | | I1 | 121 | * +------|-+ | 122 | * +--------+ 123 | */ 124 | // int1->min = int1->min; 125 | int1->max = int2->max; 126 | } else { 127 | /* 128 | * ------+ +------ 129 | * +-|----|-+ 130 | * I1 | | I2 | | I1 (overapprox, take min (I1, I2)) 131 | * +-|----|-+ 132 | * ------+ +------ 133 | * 134 | * ------+ +------ 135 | * +-|----|-+ 136 | * I2 | | I1 | | I2 (overapprox, take min (I1, I2)) 137 | * +-|----|-+ 138 | * ------+ +------ 139 | * 140 | * +-----------------+ 141 | * | +--------+ | 142 | * | | I1 | I2 | (no approximation) 143 | * | +--------+ | 144 | * +-----------------+ 145 | * 146 | * +-----------------+ 147 | * | +--------+ | 148 | * | | I2 | I1 | (no approximation) 149 | * | +--------+ | 150 | * +-----------------+ 151 | 152 | */ 153 | // double intersection -> possibly overapproximation 154 | if (wi_get_range(int2) < wi_get_range(int1)) { 155 | int1->min = int2->min; 156 | int1->max = int2->max; 157 | } 158 | } 159 | } 160 | #if DEBUG 161 | printf(" -> "); 162 | wi_print(int1); 163 | #endif 164 | return 1; 165 | } 166 | 167 | wrapped_interval_t wi_init(unsigned size) 168 | { 169 | ASSERT_OR_ABORT(size <= 64, "INTERVAL_H init_interval() - invalid size"); 170 | 171 | wrapped_interval_t res = { 172 | .min = 0, .max = get_size_mask(size), .size = size}; 173 | return res; 174 | } 175 | 176 | int wi_update_cmp(wrapped_interval_t* src, uint64_t c, optype op) 177 | { 178 | int res = 1; 179 | wrapped_interval_t cint = {.size = src->size}; 180 | c &= get_size_mask(src->size); 181 | switch (op) { 182 | case OP_ULT: 183 | c--; 184 | case OP_ULE: { 185 | cint.min = 0; 186 | cint.max = c; 187 | res = wi_intersect(src, &cint); 188 | break; 189 | } 190 | case OP_SLT: 191 | c--; 192 | case OP_SLE: { 193 | cint.min = _max(get_signed_min(src->size), src->min); 194 | cint.max = c; 195 | res = wi_intersect(src, &cint); 196 | break; 197 | } 198 | case OP_UGT: 199 | c++; 200 | case OP_UGE: { 201 | cint.min = c; 202 | cint.max = _min(get_size_mask(src->size), src->max); 203 | res = wi_intersect(src, &cint); 204 | break; 205 | } 206 | case OP_SGT: 207 | c++; 208 | case OP_SGE: { 209 | cint.min = c; 210 | cint.max = _min(get_signed_max(src->size), src->max); 211 | res = wi_intersect(src, &cint); 212 | break; 213 | } 214 | case OP_EQ: { 215 | if (!wi_contains_element(src, c)) { 216 | res = 0; 217 | break; 218 | } 219 | src->min = c; 220 | src->max = c; 221 | break; 222 | } 223 | 224 | default: 225 | ASSERT_OR_ABORT(0, "INTERVAL_H interval_update_cmp() - invalid op"); 226 | break; 227 | } 228 | return res; 229 | } 230 | 231 | void wi_update_add(wrapped_interval_t* src, uint64_t c) 232 | { 233 | src->min = (src->min + c) & get_size_mask(src->size); 234 | src->max = (src->max + c) & get_size_mask(src->size); 235 | } 236 | 237 | void wi_update_sub(wrapped_interval_t* src, uint64_t c) 238 | { 239 | src->min = (src->min - c) & get_size_mask(src->size); 240 | src->max = (src->max - c) & get_size_mask(src->size); 241 | } 242 | 243 | void wi_update_invert(wrapped_interval_t* src) 244 | { 245 | src->min = (- src->min) & get_size_mask(src->size); 246 | src->max = (- src->max) & get_size_mask(src->size); 247 | if (src->max < src->min) { 248 | src->min ^= src->max; 249 | src->max ^= src->min; 250 | src->min ^= src->max; 251 | } 252 | } 253 | 254 | void wi_modify_size(wrapped_interval_t* src, uint32_t new_size) 255 | { 256 | if (new_size < src->size) { 257 | wrapped_interval_t tmp = { 258 | .min = 0, .max = get_size_mask(new_size), .size = src->size}; 259 | wi_intersect(src, &tmp); 260 | } 261 | src->size = new_size; 262 | } 263 | 264 | int wi_contains_element(const wrapped_interval_t* interval, uint64_t value) 265 | { 266 | if (is_wrapping(interval)) 267 | return (interval->min <= value && 268 | value <= get_size_mask(interval->size)) || 269 | (0 <= value && value <= interval->max); 270 | return interval->min <= value && value <= interval->max; 271 | } 272 | 273 | uint64_t wi_get_range(const wrapped_interval_t* interval) 274 | { 275 | uint64_t mask = get_size_mask(interval->size); 276 | uint64_t range = (interval->max & mask) - (interval->min & mask); 277 | return (uint64_t)(range & mask); 278 | } 279 | 280 | wrapped_interval_iter_t wi_init_iter_values(wrapped_interval_t* interval) 281 | { 282 | wrapped_interval_iter_t it; 283 | it.min_v = interval->min; 284 | it.curr_i = 0; 285 | it.max_i = wi_get_range(interval); 286 | it.mask = get_size_mask(interval->size); 287 | return it; 288 | } 289 | 290 | int wi_iter_get_next(wrapped_interval_iter_t* it, uint64_t* el) 291 | { 292 | if (it->curr_i > it->max_i) 293 | return 0; 294 | 295 | *el = (uint64_t)((it->min_v + it->curr_i++) & it->mask); 296 | return 1; 297 | } 298 | 299 | const char* op_to_string(optype op) 300 | { 301 | switch (op) { 302 | case OP_UGT: 303 | return "OP_UGT"; 304 | case OP_UGE: 305 | return "OP_UGE"; 306 | case OP_SGT: 307 | return "OP_SGT"; 308 | case OP_SGE: 309 | return "OP_SGE"; 310 | case OP_ULT: 311 | return "OP_ULT"; 312 | case OP_ULE: 313 | return "OP_ULE"; 314 | case OP_SLT: 315 | return "OP_SLT"; 316 | case OP_SLE: 317 | return "OP_SLE"; 318 | 319 | default: 320 | ASSERT_OR_ABORT(0, "op_to_string() - unexpected optype"); 321 | } 322 | } 323 | 324 | void wi_print(wrapped_interval_t* interval) 325 | { 326 | if (!is_wrapping(interval)) 327 | fprintf(stderr, "[ 0x%lx, 0x%lx ] (%u)\n", interval->min, interval->max, 328 | interval->size); 329 | else 330 | fprintf(stderr, "[ 0x%lx, 0x%lx ] U [ 0x%lx, 0x%lx ] (%u)\n", interval->min, 331 | get_size_mask(interval->size), 0UL, interval->max, 332 | interval->size); 333 | } 334 | -------------------------------------------------------------------------------- /lib/wrapped_interval.h: -------------------------------------------------------------------------------- 1 | #ifndef WRAPPED_INTERVAL_H 2 | #define WRAPPED_INTERVAL_H 3 | 4 | #include 5 | 6 | #define OP_ULT 0 7 | #define OP_SLT 1 8 | #define OP_ULE 2 9 | #define OP_SLE 3 10 | #define OP_UGT 4 11 | #define OP_SGT 5 12 | #define OP_UGE 6 13 | #define OP_SGE 7 14 | #define OP_EQ 8 15 | 16 | typedef int optype; 17 | 18 | typedef struct wrapped_interval_t { 19 | uint64_t min; 20 | uint64_t max; 21 | uint32_t size; 22 | } wrapped_interval_t; 23 | 24 | typedef struct wrapped_interval_iter_t { 25 | uint64_t curr_i; 26 | uint64_t max_i; 27 | uint64_t min_v; 28 | uint64_t mask; 29 | } wrapped_interval_iter_t; 30 | 31 | wrapped_interval_t wi_init(unsigned size); 32 | int wi_update_cmp(wrapped_interval_t* src, uint64_t c, optype op); 33 | void wi_update_add(wrapped_interval_t* src, uint64_t c); 34 | void wi_update_sub(wrapped_interval_t* src, uint64_t c); 35 | void wi_update_invert(wrapped_interval_t* src); 36 | void wi_modify_size(wrapped_interval_t* src, uint32_t new_size); 37 | int wi_intersect(wrapped_interval_t* int1, const wrapped_interval_t* int2); 38 | int wi_contains_element(const wrapped_interval_t* interval, uint64_t value); 39 | uint64_t wi_get_range(const wrapped_interval_t* interval); 40 | void wi_print(wrapped_interval_t* interval); 41 | 42 | wrapped_interval_iter_t wi_init_iter_values(wrapped_interval_t* interval); 43 | int wi_iter_get_next(wrapped_interval_iter_t* it, uint64_t* el); 44 | 45 | const char* op_to_string(optype op); 46 | 47 | #endif -------------------------------------------------------------------------------- /lib/z3-fuzzy-datastructures-gen.h: -------------------------------------------------------------------------------- 1 | // *********** index group set *********** 2 | #define MAX_GROUP_SIZE 8 3 | 4 | typedef struct index_group_t { 5 | unsigned char n; // number of valid indexes 6 | unsigned long indexes[MAX_GROUP_SIZE]; // indexes 7 | } index_group_t; 8 | 9 | #define SET_N_BUCKETS 8 10 | #define SET_DATA_T index_group_t 11 | #include "set.h" 12 | typedef set__index_group_t index_groups_t; 13 | 14 | unsigned long index_group_hash(index_group_t* el) 15 | { 16 | unsigned long a = el->n; 17 | unsigned long b = a > 0 ? el->indexes[0] : 0; 18 | return (a + b) * (a + b + 1) / 2; 19 | } 20 | 21 | unsigned int index_group_equals(index_group_t* el1, index_group_t* el2) 22 | { 23 | if (el1->n != el2->n) 24 | return 0; 25 | 26 | unsigned char i; 27 | for (i = 0; i < el1->n; ++i) 28 | if (el1->indexes[i] != el2->indexes[i]) 29 | return 0; 30 | return 1; 31 | } 32 | static inline int da_check_el__index_group_t(da__index_group_t* da, 33 | index_group_t* el) 34 | { 35 | unsigned i; 36 | for (i = 0; i < da->size; ++i) 37 | if (index_group_equals(&da->data[i], el)) 38 | return 1; 39 | return 0; 40 | } 41 | // ********* end index group set ********* 42 | 43 | // ************* indexes set ************* 44 | typedef unsigned long ulong; 45 | #define SET_N_BUCKETS 512 46 | #define SET_DATA_T ulong 47 | #include "set.h" 48 | unsigned long index_hash(unsigned long* el) { return *el; } 49 | unsigned int index_equals(unsigned long* el1, unsigned long* el2) 50 | { 51 | return *el1 == *el2; 52 | } 53 | typedef set__ulong indexes_t; 54 | 55 | static inline int da_check_el__ulong(da__ulong* da, ulong el) 56 | { 57 | unsigned i; 58 | for (i = 0; i < da->size; ++i) 59 | if (da->data[i] == el) 60 | return 1; 61 | return 0; 62 | } 63 | // *********** end indexes set *********** 64 | 65 | // ************* values array ************ 66 | typedef da__ulong values_t; 67 | // *********** end values array ********** 68 | 69 | // *********** evaluate set ************** 70 | typedef struct digest_t { 71 | unsigned char digest[16]; 72 | } digest_t; 73 | 74 | unsigned long digest_64bit_hash(digest_t* el) 75 | { 76 | unsigned long* __attribute__((__may_alias__)) digest_p = 77 | ((unsigned long*)&el->digest); 78 | return *digest_p; 79 | } 80 | 81 | unsigned int digest_equals(digest_t* el1, digest_t* el2) 82 | { 83 | unsigned i; 84 | for (i = 0; i < 16; ++i) 85 | if (el1->digest[i] != el2->digest[i]) 86 | return 0; 87 | return 1; 88 | } 89 | 90 | #define SET_DATA_T digest_t 91 | #include "set.h" 92 | 93 | typedef set__digest_t processed_set_t; 94 | // ********* end evaluate set ************ 95 | // ********* conflicting dict ************ 96 | typedef struct ast_ptr { 97 | Z3_context ctx; 98 | Z3_ast ast; 99 | } ast_ptr; 100 | #define SET_N_BUCKETS 256 101 | #define SET_DATA_T ast_ptr 102 | #include "set.h" 103 | 104 | typedef set__ast_ptr* conflicting_ptr; 105 | #define DICT_DATA_T conflicting_ptr 106 | #include "dict.h" 107 | 108 | static void ast_ptr_free(ast_ptr* el) { Z3_dec_ref(el->ctx, el->ast); } 109 | static unsigned long ast_ptr_hash(ast_ptr* el) 110 | { 111 | return Z3_get_ast_id(el->ctx, el->ast); 112 | } 113 | static unsigned int ast_ptr_equals(ast_ptr* el1, ast_ptr* el2) 114 | { 115 | return Z3_get_ast_id(el1->ctx, el1->ast) == 116 | Z3_get_ast_id(el2->ctx, el2->ast); 117 | } 118 | 119 | static inline void conflicting_init(conflicting_ptr ptr) 120 | { 121 | set_init__ast_ptr(ptr, &ast_ptr_hash, &ast_ptr_equals); 122 | } 123 | 124 | static inline void conflicting_ptr_free(conflicting_ptr* ptr) 125 | { 126 | set_free__ast_ptr(*ptr, ast_ptr_free); 127 | free(*ptr); 128 | } 129 | 130 | static inline void add_item_to_conflicting(dict__conflicting_ptr* dict, 131 | Z3_ast expr, unsigned long idx, 132 | Z3_context ctx) 133 | { 134 | conflicting_ptr el; 135 | conflicting_ptr* match = dict_get_ref__conflicting_ptr(dict, idx); 136 | if (match == NULL) { 137 | el = (conflicting_ptr)malloc(sizeof(set__ast_ptr)); 138 | conflicting_init(el); 139 | dict_set__conflicting_ptr(dict, idx, el); 140 | } else 141 | el = *match; 142 | 143 | Z3_inc_ref(ctx, expr); 144 | ast_ptr v = {.ctx = ctx, .ast = expr}; 145 | set_add__ast_ptr(el, v); 146 | } 147 | // ******** end conflicting dict ********* 148 | // ********** interval group ************* 149 | typedef struct interval_group_t { 150 | wrapped_interval_t interval; 151 | index_group_t group; 152 | } interval_group_t; 153 | 154 | typedef interval_group_t* interval_group_ptr; 155 | #define SET_DATA_T interval_group_ptr 156 | #include "set.h" 157 | 158 | #define DICT_DATA_T da__interval_group_ptr 159 | #include "dict.h" 160 | 161 | static unsigned long interval_group_ptr_hash(interval_group_ptr* el) 162 | { 163 | return index_group_hash(&(*el)->group); 164 | } 165 | 166 | static unsigned int interval_group_ptr_equals(interval_group_ptr* el1, 167 | interval_group_ptr* el2) 168 | { 169 | return index_group_equals(&(*el1)->group, &(*el2)->group); 170 | } 171 | 172 | static void interval_group_set_el_free(interval_group_ptr* el) { free(*el); } 173 | 174 | static void index_to_group_intervals_el_free(da__interval_group_ptr* el) 175 | { 176 | da_free__interval_group_ptr(el, NULL); 177 | } 178 | // ******* end interval group ************* 179 | // ******* da Z3_ast ********************** 180 | #define DA_DATA_T Z3_ast 181 | #include "dynamic-array.h" 182 | // **************************************** 183 | // ********* ItS ite ********************** 184 | typedef struct ite_its_t { 185 | index_group_t ig; 186 | unsigned long val; 187 | } ite_its_t; 188 | #define DA_DATA_T ite_its_t 189 | #include "dynamic-array.h" 190 | 191 | int da_check_el__ite_its_t(da__ite_its_t* d, ite_its_t* el) 192 | { 193 | unsigned i; 194 | for (i = 0; i < d->size; ++i) { 195 | if (d->data[i].val == el->val && 196 | index_group_equals(&d->data[i].ig, &el->ig)) 197 | return 1; 198 | } 199 | return 0; 200 | } 201 | // **************************************** 202 | -------------------------------------------------------------------------------- /lib/z3-fuzzy-debug-utils.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static inline void print_index_queue(ast_info_ptr data) 4 | { 5 | index_group_t* group; 6 | fprintf(stderr, "----- QUEUE -----\n"); 7 | unsigned int i, j; 8 | i = 0; 9 | set_reset_iter__index_group_t(&data->index_groups, 1); 10 | while (set_iter_next__index_group_t(&data->index_groups, 1, &group)) { 11 | for (j = 0; j < group->n; ++j) 12 | fprintf(stderr, "group: %d. index: 0x%lx\n", i, group->indexes[j]); 13 | i++; 14 | } 15 | 16 | fprintf(stderr, "\n\n"); 17 | 18 | ulong* p; 19 | set_reset_iter__ulong(&data->indexes, 1); 20 | while (set_iter_next__ulong(&data->indexes, 1, &p)) 21 | fprintf(stderr, "index: 0x%lx\n", *p); 22 | 23 | fprintf(stderr, "-----------------\n"); 24 | } 25 | 26 | static inline void print_index_group(index_group_t* ig) 27 | { 28 | fprintf(stderr, 29 | "IG {\n" 30 | " n: %u\n" 31 | " indexes: ", 32 | ig->n); 33 | unsigned i; 34 | for (i = 0; i < ig->n; ++i) 35 | fprintf(stderr, "%03ld ", ig->indexes[i]); 36 | fprintf(stderr, "\n}\n"); 37 | } 38 | 39 | static inline void print_interval_groups(fuzzy_ctx_t* ctx) 40 | { 41 | fprintf(stderr, "----- INTERVAL GROUPS -----\n"); 42 | set__interval_group_ptr* group_intervals = 43 | (set__interval_group_ptr*)ctx->group_intervals; 44 | 45 | interval_group_ptr* el; 46 | set_reset_iter__interval_group_ptr(group_intervals, 0); 47 | while (set_iter_next__interval_group_ptr(group_intervals, 0, &el)) { 48 | fprintf(stderr, "***************************\n"); 49 | print_index_group(&(*el)->group); 50 | wi_print(&(*el)->interval); 51 | fprintf(stderr, "***************************\n"); 52 | } 53 | fprintf(stderr, "------------------------------\n"); 54 | } 55 | 56 | static inline void print_univocally_defined(fuzzy_ctx_t* ctx) 57 | { 58 | fprintf(stderr, "----- UNIVOCALLY DEFINED -----\n"); 59 | set__ulong* univocally_defined_inputs = 60 | (set__ulong*)ctx->univocally_defined_inputs; 61 | 62 | ulong* p; 63 | set_reset_iter__ulong(univocally_defined_inputs, 0); 64 | while (set_iter_next__ulong(univocally_defined_inputs, 0, &p)) { 65 | fprintf(stderr, "> 0x%lx\n", *p); 66 | } 67 | 68 | fprintf(stderr, "------------------------------\n"); 69 | } -------------------------------------------------------------------------------- /lib/z3-fuzzy.h: -------------------------------------------------------------------------------- 1 | #ifndef Z3_FUZZY_H 2 | #define Z3_FUZZY_H 3 | 4 | #ifdef FUZZY_SOURCE 5 | #include "testcase-list.h" 6 | #endif 7 | 8 | #include 9 | 10 | typedef enum fuzzy_findall_res_t { 11 | Z3FUZZ_GIVE_NEXT, 12 | Z3FUZZ_STOP, 13 | Z3FUZZ_JUST_LAST 14 | } fuzzy_findall_res_t; 15 | 16 | typedef struct fuzzy_stats_t { 17 | unsigned long num_evaluate; 18 | unsigned long aggressive_opt_evaluate; 19 | unsigned long num_sat; 20 | unsigned long opt_sat; 21 | unsigned long reuse; 22 | unsigned long input_to_state; 23 | unsigned long simple_math; 24 | unsigned long input_to_state_ext; 25 | unsigned long brute_force; 26 | unsigned long range_brute_force; 27 | unsigned long range_brute_force_opt; 28 | unsigned long gradient_descend; 29 | unsigned long flip1; 30 | unsigned long flip2; 31 | unsigned long flip4; 32 | unsigned long flip8; 33 | unsigned long arith8_sum; 34 | unsigned long arith8_sub; 35 | unsigned long int8; 36 | unsigned long flip16; 37 | unsigned long arith16_sum_LE; 38 | unsigned long arith16_sum_BE; 39 | unsigned long arith16_sub_LE; 40 | unsigned long arith16_sub_BE; 41 | unsigned long int16; 42 | unsigned long flip32; 43 | unsigned long arith32_sum_LE; 44 | unsigned long arith32_sum_BE; 45 | unsigned long arith32_sub_LE; 46 | unsigned long arith32_sub_BE; 47 | unsigned long int32; 48 | unsigned long flip64; 49 | unsigned long arith64_sum_LE; 50 | unsigned long arith64_sum_BE; 51 | unsigned long arith64_sub_LE; 52 | unsigned long arith64_sub_BE; 53 | unsigned long int64; 54 | unsigned long havoc; 55 | unsigned long multigoal; 56 | unsigned long sat_in_seed; 57 | unsigned long num_univocally_defined; 58 | unsigned long num_range_constraints; 59 | unsigned long num_conflicting; 60 | unsigned long conflicting_fallbacks; 61 | unsigned long conflicting_fallbacks_same_inputs; 62 | unsigned long conflicting_fallbacks_no_true; 63 | unsigned long ast_info_cache_hits; 64 | unsigned long num_timeouts; 65 | double avg_time_for_eval; 66 | } fuzzy_stats_t; 67 | 68 | typedef struct fuzzy_ctx_t { 69 | Z3_context z3_ctx; 70 | char* testcase_path; 71 | Z3_ast* symbols; 72 | unsigned long n_symbols; 73 | fuzzy_stats_t stats; 74 | Z3_ast* assignments; 75 | unsigned size_assignments; 76 | uint64_t (*model_eval)(Z3_context, Z3_ast, uint64_t*, uint8_t*, size_t, 77 | uint32_t*); 78 | #ifdef FUZZY_SOURCE 79 | testcase_list_t testcases; 80 | #else 81 | void* testcases_a; 82 | void* testcases_b; 83 | void* testcases_c; 84 | #endif 85 | 86 | // opaque fields 87 | void* univocally_defined_inputs; 88 | void* ast_info_cache; 89 | void* processed_constraints; 90 | void* conflicting_asts; 91 | void* group_intervals; 92 | void* index_to_group_intervals; 93 | void* timer; 94 | } fuzzy_ctx_t; 95 | 96 | typedef struct memory_impact_stats_t { 97 | unsigned long univocally_defined_size; 98 | unsigned long ast_info_cache_size; 99 | unsigned long conflicting_ast_size; 100 | unsigned long group_intervals_size; 101 | unsigned long index_to_group_intervals_size; 102 | unsigned long n_assignments; 103 | } memory_impact_stats_t; 104 | 105 | fuzzy_ctx_t* z3fuzz_create(Z3_context ctx, char* seed_filename, 106 | unsigned timeout); 107 | void z3fuzz_init(fuzzy_ctx_t* fctx, Z3_context ctx, char* seed_filename, 108 | char* testcase_path, 109 | uint64_t (*model_eval)(Z3_context, Z3_ast, uint64_t*, uint8_t*, 110 | size_t, uint32_t*), 111 | unsigned timeout); 112 | void z3fuzz_free(fuzzy_ctx_t* ctx); 113 | void z3fuzz_print_expr(fuzzy_ctx_t* ctx, Z3_ast e); 114 | 115 | unsigned long z3fuzz_evaluate_expression(fuzzy_ctx_t* ctx, Z3_ast value, 116 | unsigned char* values); 117 | unsigned long z3fuzz_evaluate_expression_z3(fuzzy_ctx_t* ctx, Z3_ast query, 118 | Z3_ast* values); 119 | int z3fuzz_query_check_light(fuzzy_ctx_t* ctx, Z3_ast query, 120 | Z3_ast branch_condition, 121 | unsigned char const** proof, 122 | unsigned long* proof_size); 123 | int z3fuzz_get_optimistic_sol(fuzzy_ctx_t* ctx, unsigned char const** proof, 124 | unsigned long* proof_size); 125 | unsigned long z3fuzz_maximize(fuzzy_ctx_t* ctx, Z3_ast pi, Z3_ast to_maximize, 126 | unsigned char const** out_values, 127 | unsigned long* out_len); 128 | unsigned long z3fuzz_minimize(fuzzy_ctx_t* ctx, Z3_ast pi, Z3_ast to_minimize, 129 | unsigned char const** out_values, 130 | unsigned long* out_len); 131 | void z3fuzz_find_all_values( 132 | fuzzy_ctx_t* ctx, Z3_ast expr, Z3_ast pi, 133 | fuzzy_findall_res_t (*callback)(unsigned char const* out_bytes, 134 | unsigned long out_bytes_len, 135 | unsigned long val)); 136 | void z3fuzz_find_all_values_gd( 137 | fuzzy_ctx_t* ctx, Z3_ast expr, Z3_ast pi, int to_min, 138 | fuzzy_findall_res_t (*callback)(unsigned char const* out_bytes, 139 | unsigned long out_bytes_len, 140 | unsigned long val)); 141 | void z3fuzz_add_assignment(fuzzy_ctx_t* ctx, int idx, Z3_ast assignment_value); 142 | 143 | void z3fuzz_notify_constraint(fuzzy_ctx_t* ctx, Z3_ast constraint); 144 | void z3fuzz_dump_proof(fuzzy_ctx_t* ctx, const char* filename, 145 | unsigned char const* proof, unsigned long proof_size); 146 | 147 | void z3fuzz_get_mem_stats(fuzzy_ctx_t* ctx, memory_impact_stats_t* stats); 148 | #endif 149 | -------------------------------------------------------------------------------- /python/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | fuzzysat.egg-info/ 3 | fuzzysat/z3/ 4 | native/libZ3Fuzzy.a 5 | native/libfuzzy_python.so 6 | fuzzysat/libfuzzy_python.so 7 | -------------------------------------------------------------------------------- /python/fuzzysat/__init__.py: -------------------------------------------------------------------------------- 1 | from .fuzzy import FuzzySolver 2 | -------------------------------------------------------------------------------- /python/fuzzysat/fuzzy.py: -------------------------------------------------------------------------------- 1 | import tempfile 2 | import ctypes 3 | import os 4 | 5 | from .z3 import main_ctx as _z3_ctx 6 | from .z3 import BitVec, BitVecRef, BoolVal, BoolRef, And 7 | 8 | class evalElement(ctypes.Structure): 9 | _fields_ = [('val', ctypes.c_uint64), 10 | ('proof', ctypes.c_uint64), 11 | ('proof_size', ctypes.c_uint64)] 12 | 13 | SCRIPTDIR = os.path.realpath(os.path.dirname(__file__)) 14 | 15 | libref = ctypes.cdll.LoadLibrary( 16 | os.path.join(SCRIPTDIR, "libfuzzy_python.so")) 17 | 18 | libref.createFuzzyCtx.restype = ctypes.c_void_p 19 | libref.createEvalElementArray.restype = ctypes.POINTER(evalElement) 20 | libref.z3fuzz_evaluate_expression.restype = ctypes.c_uint64 21 | libref.z3fuzz_maximize.restype = ctypes.c_uint64 22 | libref.z3fuzz_minimize.restype = ctypes.c_uint64 23 | 24 | class FuzzyCtx(object): 25 | def __init__(self, seed:str, timeout:int=0): 26 | native_z3_ctx = ctypes.c_void_p(_z3_ctx().ctx.value) 27 | native_seed = ctypes.c_char_p(bytes(seed, "ascii")) 28 | native_timeout = ctypes.c_void_p(timeout) 29 | 30 | self.handle = libref.createFuzzyCtx(native_z3_ctx, native_seed, native_timeout) 31 | 32 | def print_expr(self, expr:BitVecRef): 33 | libref.z3fuzz_print_expr(self.handle_ref(), expr.as_ast()) 34 | 35 | def handle_ref(self): 36 | return ctypes.c_void_p(self.handle) 37 | 38 | def __del__(self): 39 | libref.destroyFuzzyCtx(self.handle_ref()) 40 | 41 | class FuzzySolver(object): 42 | def __init__(self, seed:bytes, timeout:int=1000): 43 | with tempfile.NamedTemporaryFile() as f: 44 | f.write(seed) 45 | f.flush() 46 | self.ctx = FuzzyCtx(f.name, timeout) 47 | 48 | self.seed = seed 49 | self.constraints = list() 50 | self.inputs = [BitVec(i, 8) for i in range(len(seed))] 51 | 52 | def __del__(self): 53 | pass 54 | 55 | def get_input(self, off:int): 56 | if off >= len(self.inputs) or off < 0: 57 | raise ValueError(f"{off} is not a valid offset") 58 | return self.inputs[off] 59 | 60 | def add(self, constraint:BoolRef): 61 | if not self.eval_in_seed(constraint) > 0: 62 | raise ValueError( 63 | "the constraint is not true when evaluated in the seed") 64 | self.constraints.append(constraint) 65 | 66 | libref.z3fuzz_notify_constraint( 67 | self.ctx.handle_ref(), constraint.as_ast()) 68 | 69 | def pi(self): 70 | pi = BoolVal(True) 71 | if self.constraints: 72 | pi = And(*self.constraints) 73 | return pi 74 | 75 | def check_sat(self, branch_condition:BitVecRef): 76 | proof_size = ctypes.c_uint64() 77 | proof = ctypes.c_uint64() 78 | 79 | res = libref.z3fuzz_query_check_light( 80 | self.ctx.handle_ref(), 81 | self.pi().as_ast(), 82 | branch_condition.as_ast(), 83 | ctypes.byref(proof), 84 | ctypes.byref(proof_size)) 85 | 86 | if res == 0: 87 | optsol = libref.z3fuzz_get_optimistic_sol( 88 | self.ctx.handle_ref(), 89 | ctypes.byref(proof), 90 | ctypes.byref(proof_size)) 91 | if optsol == 0: 92 | return False, False, None 93 | return False, True, (ctypes.c_char*proof_size.value).from_address(proof.value).raw 94 | return True, True, (ctypes.c_char*proof_size.value).from_address(proof.value).raw 95 | 96 | def eval_in_seed(self, expr:BitVecRef): 97 | seed_arr = (ctypes.c_uint8 * len(self.seed))(*list(self.seed)) 98 | return libref.z3fuzz_evaluate_expression( 99 | self.ctx.handle_ref(), 100 | expr.as_ast(), 101 | seed_arr 102 | ) 103 | 104 | def eval(self, expr:BitVecRef, data:bytes): 105 | assert len(data) == len(self.seed) 106 | 107 | data_arr = (ctypes.c_uint8 * len(data))(*list(data)) 108 | return libref.z3fuzz_evaluate_expression( 109 | self.ctx.handle_ref(), 110 | expr.as_ast(), 111 | data_arr 112 | ) 113 | 114 | def eval_upto_inner(self, expr:BitVecRef, n:int, mode="greedy"): 115 | if mode not in {"greedy", "gd_min", "gd_max"}: 116 | raise ValueError("unrecognised mode") 117 | 118 | out_arr = libref.createEvalElementArray( 119 | ctypes.c_uint64(n), 120 | ctypes.c_uint64(len(self.seed)) 121 | ) 122 | 123 | if mode == "greedy": 124 | gd_mode = 0 125 | elif mode == "gd_min": 126 | gd_mode = 1 127 | else: 128 | gd_mode = 2 129 | 130 | n_vals = libref.evalUpto( 131 | self.ctx.handle_ref(), 132 | expr.as_ast(), 133 | self.pi().as_ast(), 134 | out_arr, 135 | ctypes.c_uint32(n), 136 | ctypes.c_uint8(gd_mode)) 137 | 138 | inserted_vals = set() 139 | res = list() 140 | for i in range(n_vals): 141 | if out_arr[i].val in inserted_vals: 142 | continue 143 | 144 | inserted_vals.add(out_arr[i].val) 145 | res.append( 146 | (out_arr[i].val, (ctypes.c_char*out_arr[i].proof_size).from_address(out_arr[i].proof).raw) 147 | ) 148 | 149 | libref.destroyEvalElementArray( 150 | out_arr, 151 | ctypes.c_uint64(n)) 152 | return res 153 | 154 | def eval_upto(self, expr:BitVecRef, n:int): 155 | added_elements = set() 156 | res = list() 157 | 158 | for el in \ 159 | self.eval_upto_inner(expr, n, "greedy") + \ 160 | self.eval_upto_inner(expr, n, "gd_min") + \ 161 | self.eval_upto_inner(expr, n, "gd_max"): 162 | 163 | if el[0] in added_elements: 164 | continue 165 | added_elements.add(el[0]) 166 | res.append(el) 167 | return res[:n] 168 | 169 | def minimize(self, expr:BitVecRef): 170 | proof_size = ctypes.c_uint64() 171 | proof = ctypes.c_uint64() 172 | 173 | minval = libref.z3fuzz_minimize( 174 | self.ctx.handle_ref(), 175 | self.pi().as_ast(), 176 | expr.as_ast(), 177 | ctypes.byref(proof), 178 | ctypes.byref(proof_size)) 179 | 180 | return minval, (ctypes.c_char*proof_size.value).from_address(proof.value).raw 181 | 182 | def maximize(self, expr:BitVecRef): 183 | proof_size = ctypes.c_uint64() 184 | proof = ctypes.c_uint64() 185 | 186 | maxval = libref.z3fuzz_maximize( 187 | self.ctx.handle_ref(), 188 | self.pi().as_ast(), 189 | expr.as_ast(), 190 | ctypes.byref(proof), 191 | ctypes.byref(proof_size)) 192 | 193 | return maxval, (ctypes.c_char*proof_size.value).from_address(proof.value).raw 194 | -------------------------------------------------------------------------------- /python/native/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc -fPIC -shared wrapperForPython.c -o libfuzzy_python.so -L. -lZ3Fuzzy -L../fuzzysat/z3 -lz3 3 | 4 | clean: 5 | rm libfuzzy_python.so 6 | -------------------------------------------------------------------------------- /python/native/wrapperForPython.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "../../lib/z3-fuzzy.h" 6 | 7 | typedef struct { 8 | uint64_t val; 9 | uint8_t* proof; 10 | uint64_t proof_size; 11 | } evalElement; 12 | 13 | fuzzy_ctx_t* createFuzzyCtx(Z3_context ctx, char* seed_filename, 14 | unsigned timeout) 15 | { 16 | fuzzy_ctx_t* fctx = (fuzzy_ctx_t*)malloc(sizeof(fuzzy_ctx_t)); 17 | z3fuzz_init(fctx, ctx, seed_filename, NULL, NULL, timeout); 18 | return fctx; 19 | } 20 | 21 | void destroyFuzzyCtx(fuzzy_ctx_t* fctx) 22 | { 23 | z3fuzz_free(fctx); 24 | free(fctx); 25 | } 26 | 27 | evalElement* createEvalElementArray(size_t n_els, size_t proof_size) 28 | { 29 | evalElement* res = (evalElement*)malloc(sizeof(evalElement) * n_els); 30 | size_t i; 31 | for (i = 0; i < n_els; ++i) { 32 | res[i].val = 0; 33 | res[i].proof = (uint8_t*)malloc(proof_size); 34 | res[i].proof_size = proof_size; 35 | } 36 | 37 | return res; 38 | } 39 | 40 | void destroyEvalElementArray(evalElement* arr, size_t n_els) 41 | { 42 | size_t i; 43 | for (i = 0; i < n_els; ++i) 44 | free(arr[i].proof); 45 | free(arr); 46 | } 47 | 48 | static evalElement* uptoOutBuffer = NULL; 49 | static uint32_t uptoCounter = 0; 50 | static uint32_t uptoMaxCounter = 0; 51 | 52 | static fuzzy_findall_res_t evalUptoCallback(unsigned char const* out_bytes, 53 | unsigned long out_bytes_len, 54 | unsigned long val) 55 | { 56 | assert(uptoOutBuffer); 57 | assert(uptoOutBuffer[uptoCounter].proof_size == out_bytes_len); 58 | 59 | uptoOutBuffer[uptoCounter].val = val; 60 | memcpy(uptoOutBuffer[uptoCounter].proof, out_bytes, out_bytes_len); 61 | 62 | uptoCounter++; 63 | if (uptoCounter >= uptoMaxCounter) 64 | return Z3FUZZ_STOP; 65 | return Z3FUZZ_GIVE_NEXT; 66 | } 67 | 68 | #define GD_MODE_NO_GD 0 69 | #define GD_MODE_TOMIN 1 70 | #define GD_MODE_TOMAX 2 71 | 72 | uint32_t evalUpto(fuzzy_ctx_t* fctx, Z3_ast expr, Z3_ast pi, evalElement* out, 73 | uint32_t out_len, uint8_t gd_mode) 74 | { 75 | uptoOutBuffer = out; 76 | uptoCounter = 0; 77 | uptoMaxCounter = out_len; 78 | 79 | switch (gd_mode) { 80 | case GD_MODE_NO_GD: 81 | z3fuzz_find_all_values(fctx, expr, pi, evalUptoCallback); 82 | break; 83 | case GD_MODE_TOMIN: 84 | z3fuzz_find_all_values_gd(fctx, expr, pi, 1, evalUptoCallback); 85 | break; 86 | case GD_MODE_TOMAX: 87 | z3fuzz_find_all_values_gd(fctx, expr, pi, 0, evalUptoCallback); 88 | break; 89 | default: 90 | fprintf(stderr, "Unexpected gd_mode: %u\n", gd_mode); 91 | assert(0); 92 | } 93 | return uptoCounter; 94 | } 95 | -------------------------------------------------------------------------------- /python/setup.py: -------------------------------------------------------------------------------- 1 | import multiprocessing 2 | import subprocess 3 | import shutil 4 | import sys 5 | import os 6 | 7 | from setuptools import setup, find_packages 8 | from distutils.command.build import build as _build 9 | from distutils.command.clean import clean as _clean 10 | 11 | SCRIPTDIR = os.path.realpath(os.path.dirname(__file__)) 12 | 13 | DEBUG=False 14 | 15 | if SCRIPTDIR.startswith("/tmp"): 16 | sys.stderr.write("!Err: update PIP") 17 | exit(1) 18 | 19 | def _patch_z3(): 20 | os.system( 21 | "sed -i '13 {s/^/#/}' %s" % "fuzzysat/z3/z3core.py" 22 | ) 23 | os.system( 24 | "sed -i '8 {s/^/import sys, io; import fuzzysat.z3 as z3 #/}' %s" % "fuzzysat/z3/z3printer.py" 25 | ) 26 | 27 | def _build_native(): 28 | build_dir = os.path.realpath(os.path.join(SCRIPTDIR, "../build-cmake")) 29 | if not os.path.exists(build_dir): 30 | os.mkdir(build_dir) 31 | 32 | cmd = [ 33 | "cmake", 34 | "-DCMAKE_BUILD_TYPE=" + ("Release" if not DEBUG else "Debug"), 35 | ".."] 36 | subprocess.check_call(cmd, cwd=build_dir) 37 | 38 | cmd = ["make", "-j", str(multiprocessing.cpu_count())] 39 | subprocess.check_call(cmd, cwd=build_dir) 40 | 41 | shutil.rmtree('fuzzysat/z3', ignore_errors=True) 42 | shutil.copytree( 43 | os.path.join(build_dir, "fuzzolic-z3", "python", "z3"), 44 | "fuzzysat/z3" 45 | ) 46 | shutil.copy( 47 | os.path.join(build_dir, "fuzzolic-z3", "python", "libz3.so"), 48 | "fuzzysat/z3/libz3.so" 49 | ) 50 | 51 | shutil.rmtree('native/libZ3Fuzzy.a', ignore_errors=True) 52 | shutil.copy( 53 | os.path.join(build_dir, "lib", "libZ3Fuzzy.a"), 54 | "native/libZ3Fuzzy.a" 55 | ) 56 | 57 | cmd = ["make"] 58 | subprocess.check_call(cmd, cwd=os.path.join(SCRIPTDIR, "native")) 59 | shutil.copy( 60 | os.path.join("native", "libfuzzy_python.so"), 61 | "fuzzysat/libfuzzy_python.so" 62 | ) 63 | 64 | _patch_z3() 65 | 66 | def _clean_native(): 67 | shutil.rmtree('fuzzysat/z3', ignore_errors=True) 68 | shutil.rmtree('native/libZ3Fuzzy.a', ignore_errors=True) 69 | shutil.rmtree('native/libfuzzy_python.so', ignore_errors=True) 70 | shutil.rmtree('fuzzysat/libfuzzy_python.so', ignore_errors=True) 71 | 72 | class build(_build): 73 | def run(self, *args): 74 | self.execute(_build_native, (), msg='Building fuzzysat') 75 | _build.run(self, *args) 76 | 77 | class clean(_clean): 78 | def run(self, *args): 79 | self.execute(_clean_native, (), msg='Cleaning fuzzysat') 80 | _clean.run(self, *args) 81 | 82 | cmdclass = { 83 | 'build': build, 84 | 'clean': clean, 85 | } 86 | 87 | setup ( 88 | name='fuzzysat', 89 | version='0.1', 90 | python_requires='>=3.6', 91 | description='An approximate SMT solver', 92 | url='https://github.com/season-lab/fuzzy-sat', 93 | packages=find_packages(), 94 | install_requires=[], 95 | setup_requires=[], 96 | extras_require={}, 97 | cmdclass=cmdclass, 98 | include_package_data=True, 99 | package_data={ 100 | 'fuzzysat': [ 101 | 'z3/*', 102 | 'libfuzzy_python.so' 103 | ] 104 | } 105 | ) 106 | -------------------------------------------------------------------------------- /python/test.py: -------------------------------------------------------------------------------- 1 | import fuzzysat 2 | import fuzzysat.z3 as z3 3 | 4 | def print_sat_info(r): 5 | is_sat, is_opt_sat, proof = r 6 | if is_sat: 7 | print("SAT: %s" % proof) 8 | elif is_opt_sat: 9 | print("OPTSAT: %s" % proof) 10 | else: 11 | print("UNKNOWN") 12 | 13 | s = fuzzysat.FuzzySolver( 14 | seed=b"\x00\x00\x00\x01") 15 | 16 | inp = z3.Concat( 17 | s.get_input(0), 18 | s.get_input(1), 19 | s.get_input(2), 20 | s.get_input(3)) 21 | 22 | s.add(inp < 16) 23 | s.add(inp > 0) 24 | 25 | print("checking %s" % (inp > 10)) 26 | r = s.check_sat(inp > 10) 27 | print_sat_info(r) 28 | 29 | print("checking %s" % (inp > 20)) 30 | r = s.check_sat(inp > 20) 31 | print_sat_info(r) 32 | 33 | print() 34 | 35 | print("eval_upto (all): ") 36 | for val, proof in s.eval_upto(inp, 20): 37 | print(" ", val, proof) 38 | print() 39 | print("eval_upto (greedy): ") 40 | for val, proof in s.eval_upto_inner(inp, 20, mode="greedy"): 41 | print(" ", val, proof) 42 | print() 43 | print("eval_upto (gd to min):") 44 | for val, proof in s.eval_upto_inner(inp, 20, mode="gd_min"): 45 | print(" ", val, proof) 46 | print() 47 | print("eval_upto (gd to max):") 48 | for val, proof in s.eval_upto_inner(inp, 20, mode="gd_max"): 49 | print(" ", val, proof) 50 | 51 | print() 52 | 53 | minval, minproof = s.minimize(inp) 54 | maxval, maxproof = s.maximize(inp) 55 | 56 | print("minval:", minval, "(", str(minproof), ")") 57 | print("maxval:", maxval, "(", str(maxproof), ")") 58 | -------------------------------------------------------------------------------- /scripts/decompress_and_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | solver=$1 4 | query_compressed_file=$2 5 | seed_file=$3 6 | 7 | tar -xzf $query_compressed_file -C /tmp 8 | 9 | $solver /tmp/query.smt2 $seed_file 10 | 11 | rm /tmp/query.smt2 12 | -------------------------------------------------------------------------------- /scripts/detect_interesting_queries.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import subprocess 4 | import sys 5 | import os 6 | 7 | dir_path = os.path.dirname(os.path.realpath(__file__)) 8 | 9 | fuzzy_solver_path = dir_path + "/../fuzzy-solver" 10 | z3_solver_path = dir_path + "/../solver" 11 | 12 | if len(sys.argv) < 3: 13 | print("USAGE: %s queries_dir seed_path" % sys.argv[0]) 14 | exit(1) 15 | 16 | directory = sys.argv[1] 17 | seed = sys.argv[2] 18 | 19 | devnull = open(os.devnull, 'w') 20 | 21 | for filename in os.listdir(directory): 22 | if filename.endswith(".smt2"): 23 | filepath = directory + "/" + filename 24 | fuzzy_out = subprocess.check_output([fuzzy_solver_path, filepath, seed], stderr=devnull) 25 | solver_out = subprocess.check_output([z3_solver_path, filepath], stderr=devnull) 26 | 27 | fuzzy_sat = int(list(filter(lambda x: b"fast sat" in x, fuzzy_out.split(b"\n")))[0].split(b"\t")[1]) 28 | solver_sat = int(list(filter(lambda x: b"sat queries" in x, solver_out.split(b"\n")))[0].split(b"\t")[1]) 29 | solver_unk = int(list(filter(lambda x: b"unkn queries" in x, solver_out.split(b"\n")))[0].split(b"\t")[1]) 30 | 31 | if fuzzy_sat == 1 and solver_unk == 1: 32 | print(filename, "is interesting! (fuzzy ok, solver unknown)") 33 | if fuzzy_sat == 0 and solver_sat == 1: 34 | print(filename, "is interesting! (fuzzy fail, solver ok)") 35 | 36 | devnull.close() 37 | -------------------------------------------------------------------------------- /scripts/extract_check_light_phases.py: -------------------------------------------------------------------------------- 1 | import tabulate 2 | import sys 3 | import re 4 | 5 | if len(sys.argv) < 2: 6 | print("error: not enough arguments") 7 | sys.exit(1) 8 | 9 | print_csv = False 10 | if len(sys.argv) > 2: 11 | print_csv = True 12 | 13 | filename = sys.argv[1] 14 | fin = open(filename, "r") 15 | 16 | hist = {} 17 | def add_or_inc(hist, v): 18 | if v in hist: 19 | hist[v] += 1 20 | else: 21 | hist[v] = 1 22 | 23 | for line in fin: 24 | match = re.findall(r"\[check light .*\]", line) 25 | if len(match) == 0: 26 | continue 27 | assert len(match) == 1 28 | m = match[0] 29 | add_or_inc(hist, m.replace("[check light ", "").replace("]", "")) 30 | 31 | sorted_keys = sorted(hist, key=lambda x: hist[x], reverse=True) 32 | 33 | table = [] 34 | for key in sorted_keys: 35 | table.append([key, hist[key]]) 36 | 37 | if not print_csv: 38 | print(tabulate.tabulate(table, headers=["transformation", "num"])) 39 | else: 40 | for line in table: 41 | print(';'.join(map(str, line))) 42 | 43 | fin.close() 44 | -------------------------------------------------------------------------------- /scripts/extract_faster_fuzzy.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import z3 4 | import os 5 | import re 6 | import sys 7 | 8 | def get_queries(filename): 9 | queries = z3.parse_smt2_file(filename) 10 | return queries 11 | 12 | def get_faster_fuzzy(csv_filename): 13 | with open(csv_filename, "r") as fin: 14 | lines = fin.readlines() 15 | 16 | lines = lines[1:] 17 | ids = set() 18 | i = 0 19 | for line in lines: 20 | line = line.strip() 21 | split = line.split(",") 22 | if split[1] == "sat" and split[3] == "unknown": 23 | ids.add(i) 24 | i += 1 25 | 26 | return ids 27 | 28 | def get_times(csv_filename, ids): 29 | with open(csv_filename, "r") as fin: 30 | lines = fin.readlines() 31 | 32 | times = [] 33 | lines = lines[1:] 34 | for idx in ids: 35 | line = lines[idx].strip() 36 | split = line.split(",") 37 | times.append( 38 | (split[0], split[2]) 39 | ) 40 | return times 41 | 42 | def find_inputs(query): 43 | inputs = re.findall(r"k![0-9]+", query.sexpr().replace("\n", "")) 44 | return set(inputs) 45 | 46 | def usage(): 47 | print("%s " % sys.argv[0]) 48 | exit(1) 49 | 50 | if len(sys.argv) < 4: 51 | usage() 52 | 53 | csv_filename = sys.argv[1] 54 | smt2_file = sys.argv[2] 55 | out_dir = sys.argv[3] 56 | 57 | if not os.path.exists(out_dir): 58 | os.mkdir(out_dir) 59 | 60 | queries = get_queries(smt2_file) 61 | ids = get_faster_fuzzy(csv_filename) 62 | 63 | i = 0 64 | for idx in ids: 65 | query = queries[idx] 66 | filename = "query_%03d.smt2" % i 67 | fout = open(out_dir + "/" + filename, "w") 68 | for inp in find_inputs(query): 69 | fout.write("(declare-const %s (_ BitVec 8))\n" % inp) 70 | fout.write("(assert \n" + query.sexpr() + "\n)\n(check-sat)") 71 | fout.close() 72 | i += 1 73 | 74 | i = 0 75 | times = get_times(csv_filename, ids) 76 | fout = open(out_dir + "/times.txt", "w") 77 | fout.write("#q\tfuzzy\tz3\n") 78 | for time_fuzzy, time_z3 in times: 79 | fout.write("%d\t%s\t%s\n" % (i, time_fuzzy, time_z3)) 80 | i += 1 81 | -------------------------------------------------------------------------------- /scripts/extract_query_k.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import z3 4 | import sys 5 | 6 | ctx = z3.Context() 7 | s = z3.Solver(ctx=ctx) 8 | queries = z3.parse_smt2_file(sys.argv[1]) 9 | k = int(sys.argv[2]) 10 | outfile = sys.argv[3] 11 | 12 | query = queries[k] 13 | 14 | with open(outfile, "w") as fout: 15 | fout.write("(assert\n" + query.sexpr() + "\n)\n") 16 | -------------------------------------------------------------------------------- /scripts/findall_sols.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import z3 5 | 6 | def usage(): 7 | print("%s [ ... ]" % sys.argv[0]) 8 | exit(1) 9 | 10 | if len(sys.argv) < 3: 11 | usage() 12 | 13 | query_f = sys.argv[1] 14 | ids = list(map(int, sys.argv[2:])) 15 | 16 | query = z3.parse_smt2_file(query_f) 17 | 18 | bvs = [z3.BitVec("k!%d" % i, 8) for i in ids] 19 | bv = bvs[0] 20 | for i in range(1, len(bvs)): 21 | bv = z3.Concat(bvs[i], bv) 22 | 23 | s = z3.Solver() 24 | s.add(query) 25 | 26 | # import IPython; IPython.embed() 27 | 28 | j = 1 29 | while s.check().r == 1: 30 | m = s.model() 31 | v = m.eval(bv, model_completion=True) 32 | v = v.as_long() 33 | 34 | print("SOL %d" % j) 35 | for i in range(len(ids)): 36 | k_v = (v >> i*8) & 0xff 37 | print(" k!%03d: 0x%02x" % (ids[i], k_v)) 38 | 39 | s.add(bv != v) 40 | print() 41 | 42 | j += 1 -------------------------------------------------------------------------------- /scripts/fix_query.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" 4 | 5 | query_file=$1 6 | query_name=`basename $query_file` 7 | 8 | max_inp=`grep -o "k\![0-9]*" $query_file | cut -d'!' -f2 | sort -n | tail -n 1` 9 | max_inp=`echo "$max_inp" | sed 's/\ *//g'` 10 | 11 | echo -n "" > /tmp/query.smt2 12 | for i in `seq 0 $max_inp`; do 13 | echo "(declare-const k!$i (_ BitVec 8))" >> /tmp/query.smt2 14 | done 15 | cat $query_file >> /tmp/query.smt2 16 | mv /tmp/query.smt2 $query_file.FIXED.smt2 17 | -------------------------------------------------------------------------------- /scripts/fix_query_and_compress.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" 4 | 5 | query_file=$1 6 | query_name=`basename $query_file` 7 | 8 | max_inp=`grep -o "k\![0-9]*" $query_file | cut -d'!' -f2 | sort -n | tail -n 1` 9 | max_inp=`echo "$max_inp" | sed 's/\ *//g'` 10 | 11 | echo -n "" > /tmp/query.smt2 12 | for i in `seq 0 $max_inp`; do 13 | echo "(declare-const k!$i (_ BitVec 8))" >> /tmp/query.smt2 14 | done 15 | cat $query_file >> /tmp/query.smt2 16 | 17 | pushd /tmp > /dev/null 18 | tar -czf $SCRIPTPATH/../query_db/$query_name.tar.gz query.smt2 19 | popd > /dev/null 20 | 21 | rm /tmp/query.smt2 22 | -------------------------------------------------------------------------------- /scripts/how_many_sat_in_fuzzy_time.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from functools import reduce 4 | import random 5 | import sys 6 | import os 7 | 8 | def usage(): 9 | print("%s " % sys.argv[0]) 10 | exit(1) 11 | 12 | def iterate_files(path): 13 | for subdir, _, files in os.walk(path): 14 | for file in files: 15 | yield os.path.join(subdir, file) 16 | break 17 | 18 | def get_queries(filename): 19 | res = [] 20 | 21 | f = open(filename, "r") 22 | f.readline() 23 | for line in f: 24 | line = line.strip() 25 | t_fuzzy, sat_fuzzy, t_z3, sat_z3 = line.split(",") 26 | t_fuzzy = float(t_fuzzy) 27 | t_z3 = float(t_z3) 28 | res.append( 29 | (t_fuzzy, sat_fuzzy, t_z3, sat_z3) 30 | ) 31 | f.close() 32 | 33 | return res 34 | 35 | def get_time_fuzzy(queries): 36 | tot = 0.0 37 | 38 | for q in queries: 39 | t, _, _, _ = q 40 | tot += t 41 | 42 | return tot 43 | 44 | def get_n_sat_fuzzy(queries): 45 | tot = 0 46 | 47 | for q in queries: 48 | _, sat, _, _ = q 49 | if sat == "sat": 50 | tot += 1 51 | 52 | return tot 53 | 54 | def get_sat_z3_up_to_time(queries, time_max): 55 | tot_time = 0.0 56 | tot_sat = 0 57 | 58 | for q in queries: 59 | _, _, t, sat = q 60 | t = float(t) 61 | tot_time += t 62 | if tot_time > time_max: 63 | break 64 | if sat == "sat": 65 | tot_sat += 1 66 | 67 | return tot_sat 68 | 69 | if len(sys.argv) < 2: 70 | usage() 71 | 72 | dirname = sys.argv[1] 73 | 74 | print("progname,time fuzzy,sat fuzzy,sat z3 [min],sat z3 [max],sat z3 [avg]") 75 | for file in sorted(list(iterate_files(dirname))): 76 | if "queries" not in os.path.basename(file): 77 | continue 78 | 79 | progname = os.path.basename(file).split("-")[0] 80 | print(progname, end=",") 81 | queries = get_queries(file) 82 | time_fuzzy = get_time_fuzzy(queries) 83 | n_sat_fuzzy = get_n_sat_fuzzy(queries) 84 | 85 | avg_sat_z3 = 0.0 86 | min_sat_z3 = 9999999 87 | max_sat_z3 = 0 88 | i = 10000 89 | while i > 0: 90 | random.shuffle(queries) 91 | n_sat_z3 = get_sat_z3_up_to_time(queries, time_fuzzy) 92 | if n_sat_z3 > max_sat_z3: 93 | max_sat_z3 = n_sat_z3 94 | if n_sat_z3 < min_sat_z3: 95 | min_sat_z3 = n_sat_z3 96 | avg_sat_z3 += n_sat_z3 97 | i -= 1 98 | 99 | avg_sat_z3 /= 10000 100 | 101 | print("%.03f s,%d,%d,%d,%.03f" % (time_fuzzy / 1000, n_sat_fuzzy, min_sat_z3, max_sat_z3, avg_sat_z3)) 102 | -------------------------------------------------------------------------------- /scripts/load_queries.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import z3 4 | import sys 5 | 6 | ctx = z3.Context() 7 | s = z3.Solver(ctx=ctx) 8 | queries_1 = z3.parse_smt2_file(sys.argv[1]) 9 | queries_2 = z3.parse_smt2_file(sys.argv[2]) 10 | 11 | queries_1 = set(queries_1) 12 | queries_2 = set(queries_2) 13 | 14 | diff = queries_1 - queries_2 15 | import IPython; IPython.embed() 16 | for query in diff: 17 | print("(assert\n" + query.sexpr() + "\n)") 18 | -------------------------------------------------------------------------------- /scripts/merge_queries_from_folder.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import z3 4 | import re 5 | import os 6 | import sys 7 | 8 | def find_inputs(query): 9 | inputs = re.findall(r"k![0-9]+", query.sexpr().replace("\n", "")) 10 | return set(inputs) 11 | 12 | if len(sys.argv) < 3: 13 | print("USAGE: %s directory smt_file" % sys.argv[0]) 14 | exit(1) 15 | 16 | directory = sys.argv[1] 17 | smt_file = sys.argv[2] 18 | 19 | if not os.path.exists(directory): 20 | print("ERROR: %s does not exist" % directory) 21 | exit(1) 22 | 23 | inputs = set() 24 | res = "" 25 | for filename in os.listdir(directory): 26 | filename = directory + "/" + filename 27 | if filename.endswith(".smt2"): 28 | print(filename) 29 | queries = z3.parse_smt2_file(filename) 30 | for query in queries: 31 | res += "(assert \n" + query.sexpr() + "\n)\n" 32 | inputs |= find_inputs(query) 33 | 34 | fout = open(smt_file, "w") 35 | for inp in inputs: 36 | fout.write("(declare-const %s (_ BitVec 8))\n" % inp) 37 | fout.write(res) 38 | fout.close() 39 | -------------------------------------------------------------------------------- /scripts/num_queries.py: -------------------------------------------------------------------------------- 1 | 2 | import z3 3 | import sys 4 | 5 | ctx = z3.Context() 6 | s = z3.Solver(ctx=ctx) 7 | queries = z3.parse_smt2_file(sys.argv[1]) 8 | 9 | print("num queries:", len(queries)) 10 | -------------------------------------------------------------------------------- /scripts/parse_filps.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from functools import reduce 4 | import sys 5 | import os 6 | 7 | def usage(): 8 | print("%s " % sys.argv[0]) 9 | exit(1) 10 | 11 | def iterate_files(path): 12 | for subdir, _, files in os.walk(path): 13 | for file in files: 14 | yield os.path.join(subdir, file) 15 | break 16 | 17 | if len(sys.argv) < 2: 18 | usage() 19 | 20 | dirname = sys.argv[1] 21 | 22 | print("progname,its,its ext,ia,gd,flips,arithms,int,havoc,multigoal,sis,tot") 23 | for file in sorted(list(iterate_files(dirname))): 24 | if "flips" not in os.path.basename(file): 25 | continue 26 | 27 | progname = os.path.basename(file).split("-")[0] 28 | print(progname, end=",") 29 | with open(file, "r") as fin: 30 | vals = fin.readline().split(",") 31 | print(",".join(vals), end=",") 32 | print(reduce(lambda x, y: x+y, map(int, vals))) 33 | -------------------------------------------------------------------------------- /scripts/parse_fuzzy_jfs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import os 5 | 6 | def usage(): 7 | print("%s " % sys.argv[0]) 8 | exit(1) 9 | 10 | def iterate_files(path): 11 | for subdir, _, files in os.walk(path): 12 | for file in files: 13 | yield os.path.join(subdir, file) 14 | break 15 | 16 | def get_queries(dirname): 17 | queries = {} 18 | tmp_expname = "" 19 | tmp_list = [] 20 | for filename in sorted(list(iterate_files(dirname))): 21 | progname = os.path.basename(filename).split("-")[0] 22 | if "-fuzzy" in os.path.basename(filename): 23 | assert tmp_expname == "" 24 | with open(filename, "r") as fin: 25 | fin.readline() 26 | for line in fin: 27 | sat, t = line.strip().split(",") 28 | tmp_list.append( 29 | [float(t), int(sat)] 30 | ) 31 | tmp_expname = progname 32 | 33 | if "-jfs" in os.path.basename(filename): 34 | assert tmp_expname != "" 35 | with open(filename, "r") as fin: 36 | fin.readline() 37 | i = 0 38 | for line in fin: 39 | sat, t = line.strip().split(",") 40 | tmp_list[i].extend( 41 | [float(t), int(sat)] 42 | ) 43 | i += 1 44 | assert tmp_expname not in queries 45 | queries[tmp_expname] = tmp_list 46 | tmp_expname = "" 47 | tmp_list = [] 48 | return queries 49 | 50 | def parse_queries(queries): 51 | t_sat_fuzzy = 0 52 | t_sat_jfs = 0 53 | t_time_fuzzy = 0.0 54 | t_time_jfs = 0.0 55 | 56 | n_jfs_sat_fuzzy_unkn = 0 57 | tot_queries = 0 58 | 59 | for q in queries: 60 | time_fuzzy, res_fuzzy, time_jfs, res_jfs = q 61 | 62 | tot_queries += 1 63 | t_sat_fuzzy += res_fuzzy 64 | t_sat_jfs += res_jfs 65 | 66 | t_time_fuzzy += float(time_fuzzy) 67 | t_time_jfs += float(time_jfs) 68 | 69 | if res_fuzzy == 0 and res_jfs == 1: 70 | n_jfs_sat_fuzzy_unkn += 1 71 | 72 | return tot_queries, t_time_fuzzy, t_time_jfs, t_sat_fuzzy, t_sat_jfs, n_jfs_sat_fuzzy_unkn 73 | 74 | if len(sys.argv) < 2: 75 | usage() 76 | 77 | dirname = sys.argv[1] 78 | queries = get_queries(dirname) 79 | 80 | for progname in sorted(list(queries.keys())): 81 | q = queries[progname] 82 | tot_queries, t_time_fuzzy, t_time_jfs, t_sat_fuzzy, t_sat_jfs, n_jfs_sat_fuzzy_unkn = parse_queries(q) 83 | print("%s;%d;%d;%d;%.02f;%d;%d;%d" % 84 | ( 85 | progname, tot_queries, t_time_fuzzy, t_time_jfs, t_time_jfs / t_time_fuzzy, t_sat_fuzzy, 86 | t_sat_jfs, n_jfs_sat_fuzzy_unkn 87 | ) 88 | ) 89 | -------------------------------------------------------------------------------- /scripts/parse_fuzzy_sat_z3_unkown.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import shutil 4 | import sys 5 | import os 6 | 7 | def usage(): 8 | print("%s " % sys.argv[0]) 9 | exit(1) 10 | 11 | def iterate_files(path): 12 | for subdir, _, files in os.walk(path): 13 | for file in files: 14 | yield os.path.join(subdir, file) 15 | break 16 | 17 | def unzip_queries(queries_dir, progname): 18 | zip_name = os.path.join(queries_dir, progname + "_queries.tar.gz") 19 | os.system("tar xzf %s -C /tmp/" % zip_name) 20 | 21 | def prepare_output_for_progname(progname): 22 | os.system("mkdir /dev/shm/%s" % progname) 23 | 24 | def copy_query(progname, query_n, time_z3, time_fuzzy): 25 | match = None 26 | for q in iterate_files("/tmp/%s_queries/" % progname): 27 | if "_%03d_" % query_n in q: 28 | match = q 29 | break 30 | 31 | assert match is not None 32 | shutil.copy2( 33 | match, 34 | os.path.join("/dev/shm/%s" % progname, "query_%08d_%08d.smt2" % (int(time_z3 * 1000), int(time_fuzzy * 1000)))) 35 | 36 | def clean_tmp(progname): 37 | os.system("rm -rf /tmp/%s_queries" % progname) 38 | 39 | def get_queries(dirname): 40 | queries = {} 41 | tmp_expname = "" 42 | tmp_list = [] 43 | for filename in sorted(list(iterate_files(dirname))): 44 | if "queries" not in os.path.basename(filename): 45 | continue 46 | 47 | progname = os.path.basename(filename).split("-")[0] 48 | if "-fuzzy-" in os.path.basename(filename): 49 | assert tmp_expname == "" 50 | with open(filename, "r") as fin: 51 | fin.readline() 52 | for line in fin: 53 | t, sat = line.strip().split(",") 54 | tmp_list.append( 55 | [float(t), sat] 56 | ) 57 | tmp_expname = progname 58 | 59 | if "-z3-" in os.path.basename(filename): 60 | assert tmp_expname != "" 61 | with open(filename, "r") as fin: 62 | fin.readline() 63 | i = 0 64 | for line in fin: 65 | t, sat = line.strip().split(",") 66 | tmp_list[i].extend( 67 | [float(t), sat] 68 | ) 69 | i += 1 70 | assert tmp_expname not in queries 71 | queries[tmp_expname] = tmp_list 72 | tmp_expname = "" 73 | tmp_list = [] 74 | return queries 75 | 76 | 77 | def parse_queries(queries, progname): 78 | t_sat_fuzzy = 0 79 | t_sat_z3 = 0 80 | t_time_fuzzy = 0.0 81 | t_time_z3 = 0.0 82 | 83 | n_fuzzy_sat_z3_unknown = 0 84 | n_fuzzy_faster = 0 85 | tot_queries = 0 86 | 87 | i = 0 88 | for q in queries: 89 | time_fuzzy, res_fuzzy, time_z3, res_z3 = q 90 | 91 | tot_queries += 1 92 | if res_fuzzy == "sat": 93 | t_sat_fuzzy += 1 94 | if res_z3 == "sat": 95 | t_sat_z3 += 1 96 | 97 | t_time_fuzzy += float(time_fuzzy) 98 | t_time_z3 += float(time_z3) 99 | 100 | if float(time_fuzzy) < float(time_z3): 101 | n_fuzzy_faster += 1 102 | if res_z3 == "unknown" and res_fuzzy == "sat": 103 | copy_query(progname, i, 0, time_fuzzy) 104 | elif float(time_z3) > 1000 and res_z3 == "sat" and res_fuzzy == "sat": 105 | copy_query(progname, i, time_z3, time_fuzzy) 106 | 107 | i += 1 108 | 109 | if len(sys.argv) < 3: 110 | usage() 111 | 112 | dirname = sys.argv[1] 113 | queries_dir = sys.argv[2] 114 | 115 | queries = get_queries(dirname) 116 | 117 | for progname in sorted(list(queries.keys())): 118 | unzip_queries(queries_dir, progname) 119 | prepare_output_for_progname(progname) 120 | 121 | q = queries[progname] 122 | parse_queries(q, progname) 123 | 124 | clean_tmp(progname) 125 | -------------------------------------------------------------------------------- /scripts/parse_info_query.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import os 5 | 6 | def usage(): 7 | print("%s " % sys.argv[0]) 8 | exit(1) 9 | 10 | def iterate_files(path): 11 | for subdir, _, files in os.walk(path): 12 | for file in files: 13 | yield os.path.join(subdir, file) 14 | break 15 | 16 | def parse_file(filename): 17 | f = open(filename, "r") 18 | 19 | t_sat_fuzzy = 0 20 | t_sat_z3 = 0 21 | t_time_fuzzy = 0.0 22 | t_time_z3 = 0.0 23 | 24 | n_fuzzy_sat_z3_unknown = 0 25 | n_fuzzy_faster = 0 26 | tot_queries = 0 27 | 28 | f.readline() 29 | for line in f: 30 | line = line.strip() 31 | time_fuzzy, res_fuzzy, time_z3, res_z3 = line.split(",") 32 | 33 | tot_queries += 1 34 | if res_fuzzy == "sat": 35 | t_sat_fuzzy += 1 36 | if res_z3 == "sat": 37 | t_sat_z3 += 1 38 | 39 | t_time_fuzzy += float(time_fuzzy) 40 | t_time_z3 += float(time_z3) 41 | 42 | if float(time_fuzzy) < float(time_z3): 43 | n_fuzzy_faster += 1 44 | if res_z3 == "unknown" and res_fuzzy == "sat": 45 | n_fuzzy_sat_z3_unknown += 1 46 | 47 | f.close() 48 | return tot_queries, n_fuzzy_faster, t_time_fuzzy, t_time_z3, t_sat_fuzzy, t_sat_z3, n_fuzzy_sat_z3_unknown 49 | 50 | if len(sys.argv) < 2: 51 | usage() 52 | 53 | dirname = sys.argv[1] 54 | 55 | for filename in sorted(list(iterate_files(dirname))): 56 | if "queries" not in os.path.basename(filename): 57 | continue 58 | 59 | progname = os.path.basename(filename).split("-")[0] 60 | tot_queries, n_fuzzy_faster, t_time_fuzzy, t_time_z3, t_sat_fuzzy, t_sat_z3, n_fuzzy_sat_z3_unknown = parse_file(filename) 61 | print("%s;%d;%d;%.02f;%.03f;%.03f;%.02f;%d;%d;%.02f;%d" % 62 | ( 63 | progname, tot_queries, n_fuzzy_faster, n_fuzzy_faster / tot_queries * 100, 64 | t_time_fuzzy, t_time_z3, t_time_z3 / t_time_fuzzy, t_sat_fuzzy, t_sat_z3, 65 | (t_sat_fuzzy - n_fuzzy_sat_z3_unknown) / t_sat_z3 * 100, n_fuzzy_sat_z3_unknown 66 | ) 67 | ) 68 | -------------------------------------------------------------------------------- /scripts/parse_info_query_splitted.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import os 5 | 6 | def usage(): 7 | print("%s " % sys.argv[0]) 8 | exit(1) 9 | 10 | def iterate_files(path): 11 | for subdir, _, files in os.walk(path): 12 | for file in files: 13 | yield os.path.join(subdir, file) 14 | break 15 | 16 | def get_queries(dirname): 17 | queries = {} 18 | tmp_expname = "" 19 | tmp_list = [] 20 | for filename in sorted(list(iterate_files(dirname))): 21 | if "queries" not in os.path.basename(filename): 22 | continue 23 | 24 | progname = os.path.basename(filename).split("-")[0] 25 | if "-fuzzy-" in os.path.basename(filename): 26 | assert tmp_expname == "" 27 | with open(filename, "r") as fin: 28 | fin.readline() 29 | for line in fin: 30 | t, sat = line.strip().split(",") 31 | tmp_list.append( 32 | [float(t), sat] 33 | ) 34 | tmp_expname = progname 35 | 36 | if "-z3-" in os.path.basename(filename): 37 | assert tmp_expname != "" 38 | with open(filename, "r") as fin: 39 | fin.readline() 40 | i = 0 41 | for line in fin: 42 | t, sat = line.strip().split(",") 43 | tmp_list[i].extend( 44 | [float(t), sat] 45 | ) 46 | i += 1 47 | assert tmp_expname not in queries 48 | queries[tmp_expname] = tmp_list 49 | tmp_expname = "" 50 | tmp_list = [] 51 | return queries 52 | 53 | 54 | def parse_queries(queries): 55 | t_sat_fuzzy = 0 56 | t_sat_z3 = 0 57 | t_time_fuzzy = 0.0 58 | t_time_z3 = 0.0 59 | 60 | n_fuzzy_sat_z3_unknown = 0 61 | n_fuzzy_faster = 0 62 | tot_queries = 0 63 | 64 | for q in queries: 65 | time_fuzzy, res_fuzzy, time_z3, res_z3 = q 66 | 67 | tot_queries += 1 68 | if res_fuzzy == "sat": 69 | t_sat_fuzzy += 1 70 | if res_z3 == "sat": 71 | t_sat_z3 += 1 72 | 73 | t_time_fuzzy += float(time_fuzzy) 74 | t_time_z3 += float(time_z3) 75 | 76 | if float(time_fuzzy) < float(time_z3): 77 | n_fuzzy_faster += 1 78 | if res_z3 == "unknown" and res_fuzzy == "sat": 79 | n_fuzzy_sat_z3_unknown += 1 80 | 81 | return tot_queries, n_fuzzy_faster, t_time_fuzzy, t_time_z3, t_sat_fuzzy, t_sat_z3, n_fuzzy_sat_z3_unknown 82 | 83 | if len(sys.argv) < 2: 84 | usage() 85 | 86 | dirname = sys.argv[1] 87 | 88 | queries = get_queries(dirname) 89 | 90 | for progname in sorted(list(queries.keys())): 91 | q = queries[progname] 92 | tot_queries, n_fuzzy_faster, t_time_fuzzy, t_time_z3, t_sat_fuzzy, t_sat_z3, n_fuzzy_sat_z3_unknown = parse_queries(q) 93 | print("%s;%d;%d;%.02f;%.03f;%.03f;%.02f;%d;%d;%.02f;%d" % 94 | ( 95 | progname, tot_queries, n_fuzzy_faster, n_fuzzy_faster / tot_queries * 100, 96 | t_time_fuzzy, t_time_z3, t_time_z3 / t_time_fuzzy, t_sat_fuzzy, t_sat_z3, 97 | (t_sat_fuzzy - n_fuzzy_sat_z3_unknown) / t_sat_z3 * 100, n_fuzzy_sat_z3_unknown 98 | ) 99 | ) 100 | -------------------------------------------------------------------------------- /scripts/parse_run_multiple_log.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def usage(): 6 | print("%s " % sys.argv[0]) 7 | exit(1) 8 | 9 | if len(sys.argv) < 3: 10 | usage() 11 | 12 | log_fuzzy = sys.argv[1] 13 | log_jsf = sys.argv[2] 14 | 15 | f_fuzzy = open(log_fuzzy, "r") 16 | f_jsf = open(log_jsf, "r") 17 | 18 | tot_t_fuzzy = 0.0 19 | n_sat_fuzzy = 0 20 | fuzzy_sat_dict = {} 21 | 22 | i = 0 23 | for line in f_fuzzy: 24 | sat_fuzzy, t_fuzzy = line.split(",") 25 | t_fuzzy = float(t_fuzzy) 26 | 27 | if sat_fuzzy == "1": 28 | n_sat_fuzzy += 1 29 | fuzzy_sat_dict[i] = True 30 | else: 31 | fuzzy_sat_dict[i] = False 32 | tot_t_fuzzy += t_fuzzy 33 | i += 1 34 | 35 | tot_t_jsf = 0.0 36 | n_sat_jsf = 0 37 | jfs_sat_but_no_fuzzy = 0 38 | 39 | i = 0 40 | for line in f_jsf: 41 | sat_jsf, t_jsf = line.split(",") 42 | t_jsf = float(t_jsf) 43 | 44 | if sat_jsf == "1": 45 | n_sat_jsf += 1 46 | if not fuzzy_sat_dict[i]: 47 | print("query %d jsf but not fuzzy" % i) 48 | jfs_sat_but_no_fuzzy += 1 49 | tot_t_jsf += t_jsf 50 | i += 1 51 | 52 | f_fuzzy.close() 53 | f_jsf.close() 54 | 55 | print("tot time fuzzy:", tot_t_fuzzy) 56 | print("tot time jsf: ", tot_t_jsf) 57 | print("num sat fuzzy: ", n_sat_fuzzy) 58 | print("num sat jsf: ", n_sat_jsf) 59 | print("jsf sat but no fuzzy: ", jfs_sat_but_no_fuzzy) -------------------------------------------------------------------------------- /scripts/run_batch_fuzzy_jfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" 4 | QUERIES_PATH=$SCRIPTPATH/../query_db/single_queries 5 | SEED_PATH=$SCRIPTPATH/../query_db/seeds 6 | 7 | export LD_LIBRARY_PATH=$SCRIPTPATH/../fuzzolic-z3/build 8 | 9 | function execute_bench { 10 | queries_dir=$1 11 | seed_path=$2 12 | exp_name=$3 13 | out_dir=$4 14 | 15 | echo "running exp $exp_name on fuzzy..." 16 | $SCRIPTPATH/run_on_multiple_queries.py \ 17 | $queries_dir $seed_path $out_dir/$exp_name-fuzzy.csv fuzzy 18 | 19 | echo "running exp $exp_name on jfs..." 20 | docker run --rm \ 21 | -v $out_dir:/home/user/out \ 22 | -v $queries_dir:/home/user/queries:ro \ 23 | -v $SCRIPTPATH/run_on_multiple_queries.py:/home/user/run_on_multiple_queries.py:ro \ 24 | delcypher/jfs_build:fse_2019 \ 25 | /home/user/run_on_multiple_queries.py \ 26 | /home/user/queries 0 /home/user/out/$exp_name-jfs.csv jfs 27 | 28 | echo "DONE" 29 | } 30 | 31 | function execute_run { 32 | out_dir=$1 33 | run_n=$2 34 | 35 | out_dir=$out_dir/run-$run_n 36 | 37 | [ -d $out_dir ] && echo "Directory $out_dir exists." && exit 1 38 | 39 | mkdir $out_dir 40 | 41 | tar xzf $QUERIES_PATH/advmng_queries.tar.gz -C /tmp 42 | execute_bench /tmp/advmng_queries $SEED_PATH/mappy.mng advmng $out_dir 43 | rm -rf /tmp/advmng_queries 44 | 45 | tar xzf $QUERIES_PATH/advzip_queries.tar.gz -C /tmp 46 | execute_bench /tmp/advzip_queries $SEED_PATH/small_archive.zip advzip $out_dir 47 | rm -rf /tmp/advzip_queries 48 | 49 | tar xzf $QUERIES_PATH/bloaty_queries.tar.gz -C /tmp 50 | execute_bench /tmp/bloaty_queries $SEED_PATH/small_exec.elf bloaty $out_dir 51 | rm -rf /tmp/bloaty_queries 52 | 53 | tar xzf $QUERIES_PATH/bsdtar_queries.tar.gz -C /tmp 54 | execute_bench /tmp/bsdtar_queries $SEED_PATH/tar.tar bsdtar $out_dir 55 | rm -rf /tmp/bsdtar_queries 56 | 57 | tar xzf $QUERIES_PATH/djpeg_queries.tar.gz -C /tmp 58 | execute_bench /tmp/djpeg_queries $SEED_PATH/not_kitty.jpg djpeg $out_dir 59 | rm -rf /tmp/djpeg_queries 60 | 61 | tar xzf $QUERIES_PATH/jhead_queries.tar.gz -C /tmp 62 | execute_bench /tmp/jhead_queries $SEED_PATH/not_kitty.jpg jhead $out_dir 63 | rm -rf /tmp/jhead_queries 64 | 65 | tar xzf $QUERIES_PATH/libpng_queries.tar.gz -C /tmp 66 | execute_bench /tmp/libpng_queries $SEED_PATH/not_kitty.png libpng $out_dir 67 | rm -rf /tmp/libpng_queries 68 | 69 | tar xzf $QUERIES_PATH/lodepng_queries.tar.gz -C /tmp 70 | execute_bench /tmp/lodepng_queries $SEED_PATH/not_kitty.png lodepng $out_dir 71 | rm -rf /tmp/lodepng_queries 72 | 73 | tar xzf $QUERIES_PATH/optipng_queries.tar.gz -C /tmp 74 | execute_bench /tmp/optipng_queries $SEED_PATH/not_kitty.png optipng $out_dir 75 | rm -rf /tmp/optipng_queries 76 | 77 | tar xzf $QUERIES_PATH/readelf_queries.tar.gz -C /tmp 78 | execute_bench /tmp/readelf_queries $SEED_PATH/small_exec.elf readelf $out_dir 79 | rm -rf /tmp/readelf_queries 80 | 81 | tar xzf $QUERIES_PATH/tcpdump_queries.tar.gz -C /tmp 82 | execute_bench /tmp/tcpdump_queries $SEED_PATH/small_capture.pcap tcpdump $out_dir 83 | rm -rf /tmp/tcpdump_queries 84 | 85 | tar xzf $QUERIES_PATH/tiff2pdf_queries.tar.gz -C /tmp 86 | execute_bench /tmp/tiff2pdf_queries $SEED_PATH/not_kitty.tiff tiff2pdf $out_dir 87 | rm -rf /tmp/tiff2pdf_queries 88 | 89 | tar xzf $QUERIES_PATH/objdump_queries.tar.gz -C /tmp 90 | execute_bench /tmp/objdump_queries $SEED_PATH/small_exec.elf objdump $out_dir 91 | rm -rf /tmp/objdump_queries 92 | } 93 | 94 | OUT_DIR=$SCRIPTPATH/../exp_logs/exp-nuovi/fuzzy-jsf 95 | 96 | execute_run $OUT_DIR 1 97 | execute_run $OUT_DIR 2 98 | execute_run $OUT_DIR 3 99 | -------------------------------------------------------------------------------- /scripts/run_batch_fuzzy_with_parsing.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #!/bin/bash 4 | 5 | SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" 6 | BIN_FUZZY=$SCRIPTPATH/../fuzzy-solver-notify 7 | QUERIES_PATH=$SCRIPTPATH/../query_db/without_models 8 | SEED_PATH=$SCRIPTPATH/../query_db/seeds 9 | 10 | export LD_LIBRARY_PATH=$SCRIPTPATH/../fuzzolic-z3/build 11 | 12 | function execute_bench { 13 | query_path=$1 14 | seed_path=$2 15 | exp_name=$3 16 | out_file=$4 17 | 18 | echo "running exp $exp_name on fuzzy..." 19 | output=$($BIN_FUZZY $query_path $seed_path) 20 | tot_time=$(echo "$output" | grep "elaps time + par" | cut -d':' -f2 | sed 's/s//g' | sed 's/ //g') 21 | time_par=$(echo "$output" | grep "elaps par" | cut -d':' -f2 | sed 's/s//g' | sed 's/ //g') 22 | 23 | echo "$exp_name,$time_par,$tot_time" >> $out_file 24 | echo "DONE" 25 | } 26 | 27 | function execute_run { 28 | out_dir=$1 29 | run_n=$2 30 | 31 | out_file=$out_dir/fuzzy-times-with-parsing-$run_n.csv 32 | 33 | execute_bench $QUERIES_PATH/advmng.smt2 $SEED_PATH/mappy.mng advmng $out_file 34 | execute_bench $QUERIES_PATH/advzip.smt2 $SEED_PATH/small_archive.zip advzip $out_file 35 | execute_bench $QUERIES_PATH/bloaty.smt2 $SEED_PATH/small_exec.elf bloaty $out_file 36 | execute_bench $QUERIES_PATH/bsdtar.smt2 $SEED_PATH/tar.tar bsdtar $out_file 37 | execute_bench $QUERIES_PATH/djpeg.smt2 $SEED_PATH/not_kitty.jpg djpeg $out_file 38 | execute_bench $QUERIES_PATH/jhead.smt2 $SEED_PATH/not_kitty.jpg jhead $out_file 39 | execute_bench $QUERIES_PATH/libpng.smt2 $SEED_PATH/not_kitty.png libpng $out_file 40 | execute_bench $QUERIES_PATH/lodepng_decode_nock.smt2 $SEED_PATH/not_kitty.png lodepng $out_file 41 | execute_bench $QUERIES_PATH/optipng.smt2 $SEED_PATH/not_kitty.png optipng $out_file 42 | execute_bench $QUERIES_PATH/readelf.smt2 $SEED_PATH/small_exec.elf readelf $out_file 43 | execute_bench $QUERIES_PATH/tcpdump.smt2 $SEED_PATH/small_capture.pcap tcpdump $out_file 44 | execute_bench $QUERIES_PATH/tiff2pdf.smt2 $SEED_PATH/not_kitty.tiff tiff2pdf $out_file 45 | execute_bench $QUERIES_PATH/objdump.smt2 $SEED_PATH/small_exec.elf objdump $out_file 46 | } 47 | 48 | OUT_DIR=$SCRIPTPATH/../exp_logs/exp-nuovi/fuzzy-times-with-parsing 49 | 50 | execute_run $OUT_DIR 1 51 | execute_run $OUT_DIR 2 52 | execute_run $OUT_DIR 3 53 | -------------------------------------------------------------------------------- /scripts/run_batch_fuzzy_z3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" 4 | BIN_Z3=$SCRIPTPATH/../build/bin/stats-collection-z3 5 | BIN_FUZZY=$SCRIPTPATH/../build/bin/stats-collection-fuzzy 6 | # QUERIES_PATH=$SCRIPTPATH/../query_db/without_models 7 | QUERIES_PATH=/media/luca/HD2T/Home/Data/smt2_queries_dataset/queries_dataset 8 | # SEED_PATH=$SCRIPTPATH/../query_db/seeds 9 | SEED_PATH=/media/luca/HD2T/Home/Data/smt2_queries_dataset/seeds 10 | 11 | export LD_LIBRARY_PATH=$SCRIPTPATH/../fuzzolic-z3/build 12 | 13 | function execute_bench { 14 | query_path=$1 15 | seed_path=$2 16 | exp_name=$3 17 | out_dir=$4 18 | 19 | echo "running exp $exp_name on z3..." 20 | $BIN_Z3 $query_path 21 | 22 | mv ./z3_queries.csv $out_dir/$exp_name-z3-queries.csv 23 | 24 | echo "running exp $exp_name on fuzzy..." 25 | $BIN_FUZZY $query_path $seed_path 26 | 27 | mv ./fuzzy_queries.csv $out_dir/$exp_name-fuzzy-queries.csv 28 | mv ./fuzzy_flip_info.csv $out_dir/$exp_name-fuzzy-flips.csv 29 | 30 | echo "DONE" 31 | } 32 | 33 | function execute_run { 34 | out_dir=$1 35 | run_n=$2 36 | 37 | out_dir=$out_dir/run-$run_n 38 | 39 | [ -d $out_dir ] && echo "Directory $out_dir exists." && exit 1 40 | 41 | mkdir $out_dir 42 | 43 | execute_bench $QUERIES_PATH/advmng.smt2 $SEED_PATH/mappy.mng advmng $out_dir 44 | execute_bench $QUERIES_PATH/advzip.smt2 $SEED_PATH/small_archive.zip advzip $out_dir 45 | execute_bench $QUERIES_PATH/bloaty.smt2 $SEED_PATH/small_exec.elf bloaty $out_dir 46 | execute_bench $QUERIES_PATH/bsdtar.smt2 $SEED_PATH/tar.tar bsdtar $out_dir 47 | execute_bench $QUERIES_PATH/djpeg.smt2 $SEED_PATH/not_kitty.jpg djpeg $out_dir 48 | execute_bench $QUERIES_PATH/jhead.smt2 $SEED_PATH/not_kitty.jpg jhead $out_dir 49 | execute_bench $QUERIES_PATH/libpng.smt2 $SEED_PATH/not_kitty.png libpng $out_dir 50 | execute_bench $QUERIES_PATH/lodepng_decode_nock.smt2 $SEED_PATH/not_kitty.png lodepng $out_dir 51 | execute_bench $QUERIES_PATH/optipng.smt2 $SEED_PATH/not_kitty.png optipng $out_dir 52 | execute_bench $QUERIES_PATH/readelf.smt2 $SEED_PATH/small_exec.elf readelf $out_dir 53 | execute_bench $QUERIES_PATH/tcpdump.smt2 $SEED_PATH/small_capture.pcap tcpdump $out_dir 54 | execute_bench $QUERIES_PATH/tiff2pdf.smt2 $SEED_PATH/not_kitty.tiff tiff2pdf $out_dir 55 | execute_bench $QUERIES_PATH/objdump.smt2 $SEED_PATH/small_exec.elf objdump $out_dir 56 | } 57 | 58 | # OUT_DIR=$SCRIPTPATH/../exp_logs/exp-nuovi/fuzzy-z3-1sec 59 | OUT_DIR=/media/luca/HD2T/Home/Data/exp_logs_fuzzy_sat/fuzzy-z3-1sec 60 | 61 | execute_run $OUT_DIR 1 62 | # execute_run $OUT_DIR 2 63 | # execute_run $OUT_DIR 3 64 | -------------------------------------------------------------------------------- /scripts/run_batch_fuzzy_z3_old.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" 4 | BIN=$SCRIPTPATH/../fuzzy-solver-vs-z3 5 | QUERIES_PATH=$SCRIPTPATH/../query_db/without_models 6 | SEED_PATH=$SCRIPTPATH/../query_db/seeds 7 | 8 | export LD_LIBRARY_PATH=$SCRIPTPATH/../fuzzolic-z3/build 9 | 10 | function execute_bench { 11 | query_path=$1 12 | seed_path=$2 13 | exp_name=$3 14 | out_dir=$4 15 | 16 | echo "running exp $exp_name..." 17 | $BIN $query_path $seed_path 18 | 19 | mv ./fuzzy_z3.csv $out_dir/$exp_name-queries.csv 20 | mv ./fuzzy_flip_info.csv $out_dir/$exp_name-flips.csv 21 | echo "DONE" 22 | } 23 | 24 | OUT_DIR=$SCRIPTPATH/../exp_logs/fuzzy_z3_10sec 25 | 26 | # execute_bench $QUERIES_PATH/advmng.smt2 $SEED_PATH/mappy.mng advmng $OUT_DIR 27 | # execute_bench $QUERIES_PATH/advzip.smt2 $SEED_PATH/small_archive.zip advzip $OUT_DIR 28 | # execute_bench $QUERIES_PATH/bloaty.smt2 $SEED_PATH/small_exec.elf bloaty $OUT_DIR 29 | # execute_bench $QUERIES_PATH/djpeg.smt2 $SEED_PATH/not_kitty.jpg djpeg $OUT_DIR 30 | # execute_bench $QUERIES_PATH/jhead.smt2 $SEED_PATH/not_kitty.jpg jhead $OUT_DIR 31 | # execute_bench $QUERIES_PATH/libpng.smt2 $SEED_PATH/not_kitty.png libpng $OUT_DIR 32 | # execute_bench $QUERIES_PATH/lodepng_decode_nock.smt2 $SEED_PATH/not_kitty.png lodepng $OUT_DIR 33 | # execute_bench $QUERIES_PATH/optipng.smt2 $SEED_PATH/not_kitty.png optipng $OUT_DIR 34 | # execute_bench $QUERIES_PATH/readelf.smt2 $SEED_PATH/small_exec.elf readelf $OUT_DIR 35 | # execute_bench $QUERIES_PATH/tcpdump.smt2 $SEED_PATH/small_capture.pcap tcpdump $OUT_DIR 36 | # execute_bench $QUERIES_PATH/tiff2pdf.smt2 $SEED_PATH/not_kitty.tiff tiff2pdf $OUT_DIR 37 | execute_bench $QUERIES_PATH/objdump.smt2 $SEED_PATH/small_exec.elf objdump $OUT_DIR 38 | -------------------------------------------------------------------------------- /scripts/run_experiment.py: -------------------------------------------------------------------------------- 1 | import os 2 | from subprocess import check_call 3 | from shutil import copyfile 4 | 5 | CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) 6 | 7 | 8 | def run_experiment(path_to_queries, path_to_seed): 9 | # fuzzy_solver 10 | 11 | exp_dir = CURRENT_DIR + "/data/" + \ 12 | path_to_queries.split("/")[-1].replace(".smt2.tar.gz", "") 13 | try: 14 | # Create experiment directory 15 | os.mkdir(exp_dir) 16 | except FileExistsError: 17 | print("Dicrectory ", exp_dir, " already exists") 18 | return -1 19 | 20 | stdout_file_fuzzy_solver = open(exp_dir + "/stdout_fuzzy.txt", "w") 21 | stderr_file_fuzzy_solver = open(exp_dir + "/stderr_fuzzy.txt", "w") 22 | 23 | print("running fuzzy-solver on", path_to_queries) 24 | check_call([CURRENT_DIR + "/decompress_and_run.sh", CURRENT_DIR + "/../fuzzy-solver", 25 | path_to_queries, path_to_seed], stderr=stderr_file_fuzzy_solver) 26 | 27 | copyfile("/tmp/z3fuzzy-log.csv", exp_dir + "/fuzzy-solver.csv") 28 | copyfile("/tmp/sat-z3-only.smt2", exp_dir + "/sat-z3-only.smt2") 29 | stderr_file_fuzzy_solver.close() 30 | stdout_file_fuzzy_solver.close() 31 | 32 | stdout_file_solver = open(exp_dir + "/stdout_solver.txt", "w") 33 | stderr_file_solver = open(exp_dir + "/stderr_solver.txt", "w") 34 | 35 | print("running solver on", path_to_queries) 36 | check_call([CURRENT_DIR + "/decompress_and_run.sh", CURRENT_DIR + "/../solver", 37 | path_to_queries], stderr=stderr_file_solver) 38 | 39 | copyfile("/tmp/z3fuzzy-log.csv", exp_dir + "/solver.csv") 40 | stderr_file_solver.close() 41 | stdout_file_solver.close() 42 | 43 | return 0 44 | 45 | 46 | run_experiment("/mnt/data/symbolic/SymFuzz/fuzzy-solver/query_db/lodepng_queries.smt2.tar.gz", 47 | "/mnt/data/symbolic/SymFuzz/fuzzy-solver/query_db/png.seed") 48 | 49 | run_experiment("/mnt/data/symbolic/SymFuzz/fuzzy-solver/query_db/lodepng_nocks_queries.smt2.tar.gz", 50 | "/mnt/data/symbolic/SymFuzz/fuzzy-solver/query_db/png.seed") 51 | 52 | run_experiment("/mnt/data/symbolic/SymFuzz/fuzzy-solver/query_db/libpng_queries.smt2.tar.gz", 53 | "/mnt/data/symbolic/SymFuzz/fuzzy-solver/query_db/png.seed") 54 | 55 | run_experiment("/mnt/data/symbolic/SymFuzz/fuzzy-solver/query_db/djpeg_queries.smt2.tar.gz", 56 | "/mnt/data/symbolic/SymFuzz/fuzzy-solver/query_db/jpg.seed") 57 | 58 | run_experiment("/mnt/data/symbolic/SymFuzz/fuzzy-solver/query_db/gifhisto_queries.smt2.tar.gz", 59 | "/mnt/data/symbolic/SymFuzz/fuzzy-solver/query_db/gif.seed") 60 | -------------------------------------------------------------------------------- /scripts/run_on_multiple_queries.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import subprocess 4 | import time 5 | import sys 6 | import os 7 | 8 | SCRIPT_PATH = os.path.dirname(os.path.realpath(__file__)) 9 | 10 | def usage(): 11 | print("%s {fuzzy/jsf}" % sys.argv[0]) 12 | exit(1) 13 | 14 | def iterate_files(path): 15 | for subdir, _, files in os.walk(path): 16 | for file in files: 17 | yield os.path.join(subdir, file) 18 | break 19 | 20 | def docker_check_kill(docker_name): 21 | s = subprocess.check_output(["docker", "ps"]) 22 | if docker_name in s.decode("ascii", errors="ignore"): 23 | subprocess.check_call( 24 | ["docker", "kill", docker_name], 25 | stderr=subprocess.DEVNULL, 26 | stdout=subprocess.DEVNULL) 27 | 28 | def run_fuzzy(query, seed): 29 | start = time.time() 30 | try: 31 | output = subprocess.check_output( 32 | [os.path.join(SCRIPT_PATH, "../fuzzy-solver"), "--query", query, "--seed", seed, "--notui"], 33 | timeout=2, 34 | stderr=subprocess.DEVNULL, 35 | env={"LD_LIBRARY_PATH": os.path.join(SCRIPT_PATH, "../fuzzolic-z3/build")} 36 | ) 37 | except subprocess.TimeoutExpired: 38 | output = b"" 39 | end = time.time() 40 | elapsed = (end - start) * 1000.0 41 | 42 | if b"SAT" in output: 43 | return True, elapsed 44 | return False, elapsed 45 | 46 | def run_jfs_docker(query): 47 | start = time.time() 48 | try: 49 | output = subprocess.check_output( 50 | [ 51 | "docker", "run", "--user", "1000", "--rm", "-v", 52 | "%s:/tmp/q.smt2" % os.path.realpath(query), 53 | "--name", "jfs-runner", "-t", "delcypher/jfs_build:fse_2019", 54 | "/home/user/jfs/build/bin/jfs", "-max-time=1", "/tmp/q.smt2" 55 | ], 56 | timeout=2, 57 | stderr=subprocess.DEVNULL, 58 | ) 59 | except subprocess.TimeoutExpired: 60 | output = b"" 61 | end = time.time() 62 | elapsed = (end - start) * 1000.0 63 | 64 | docker_check_kill("jfs-runner") 65 | 66 | if b"sat" in output and b"unsat" not in output: 67 | return True, elapsed 68 | return False, elapsed 69 | 70 | def run_jfs(query): 71 | start = time.time() 72 | try: 73 | output = subprocess.check_output( 74 | [ 75 | "/home/user/jfs/build/bin/jfs", "-max-time=1", query 76 | ], 77 | timeout=2, 78 | stderr=subprocess.DEVNULL, 79 | ) 80 | except subprocess.TimeoutExpired: 81 | output = b"" 82 | except subprocess.CalledProcessError: 83 | print("WARNING: called process error on %s" % query) 84 | output = b"" 85 | end = time.time() 86 | elapsed = (end - start) * 1000.0 87 | 88 | if b"sat" in output and b"unsat" not in output: 89 | return True, elapsed 90 | return False, elapsed 91 | 92 | def exp_jfs(queries_dir, logfile): 93 | f = open(logfile, "w") 94 | for query in sorted(list(iterate_files(queries_dir))): 95 | sat_jfs, time_jfs = run_jfs(query) 96 | f.write("%d,%.03f\n" % (1 if sat_jfs else 0, time_jfs)) 97 | 98 | f.close() 99 | 100 | def exp_fuzzy(queries_dir, seed, logfile): 101 | f = open(logfile, "w") 102 | for query in sorted(list(iterate_files(queries_dir))): 103 | sat_fuzzy, time_fuzzy = run_fuzzy(query, seed) 104 | f.write("%d,%.03f\n" % (1 if sat_fuzzy else 0, time_fuzzy)) 105 | 106 | f.close() 107 | 108 | if len(sys.argv) < 5: 109 | usage() 110 | 111 | queries_dir = sys.argv[1] 112 | seed = sys.argv[2] 113 | logfile = sys.argv[3] 114 | program = sys.argv[4] 115 | 116 | assert program in ["jfs", "fuzzy"] 117 | 118 | if program == "jfs": 119 | exp_jfs(queries_dir, logfile) 120 | else: 121 | exp_fuzzy(queries_dir, seed, logfile) 122 | -------------------------------------------------------------------------------- /scripts/run_query_stats_exp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope > /dev/null 4 | export LD_LIBRARY_PATH=../fuzzolic-z3/build 5 | 6 | HOST_BENCH=/home/luca/Documents/git/exp-docker/host_bin/benchmarks 7 | GUEST_BENCH=/home/qsym/benchmarks 8 | 9 | function run_exp { 10 | seed_file=$1 11 | prog_name=$2 12 | args=$3 13 | 14 | rm -rf /dev/shm/* 15 | echo "" 16 | echo "> exp $prog_name <" 17 | echo "" 18 | echo "[+] running docker..." 19 | docker run --rm \ 20 | -v /dev/shm:/mnt/out \ 21 | -v $HOST_BENCH:$GUEST_BENCH \ 22 | qsym-fuzzy-exp \ 23 | /bin/bash -c \ 24 | "source ./fuzzers/qsym-fuzzy/venv/bin/activate && \ 25 | ./fuzzers/qsym-fuzzy/bin/run_qsym.py \ 26 | -i $GUEST_BENCH/$seed_file -o /mnt/out -- $GUEST_BENCH/$args" 27 | 28 | mv /dev/shm/qsym-out-0/querylog.log ../query_db/exp_out/$prog_name 29 | echo "[+] fixing query...." 30 | ./fix_query.sh ../query_db/exp_out/$prog_name 31 | mv ../query_db/exp_out/$prog_name.FIXED.smt2 ../query_db/exp_out/$prog_name.smt2 32 | rm ../query_db/exp_out/$prog_name 33 | echo "[+] running fuzzy-solver vs z3..." 34 | ../fuzzy-solver-vs-z3 ../query_db/exp_out/$prog_name.smt2 $HOST_BENCH/$seed_file 35 | mv ./fuzzy_z3.csv ../query_db/exp_out/$prog_name.csv 36 | echo "[+] done" 37 | rm -rf /dev/shm/* 38 | } 39 | 40 | # run_exp tcpdump/seeds/small_capture.pcap tcpdump "tcpdump/tcpdump_nopie -e -vv -nr @@" 41 | # run_exp bloaty/seeds/small_exec.elf bloaty "bloaty/bloaty @@" 42 | # run_exp djpeg/seeds/not_kitty.jpg djpeg "djpeg/djpeg @@" 43 | # run_exp readelf/seeds/small_exec.elf readelf "readelf/readelf_nopie -a @@" 44 | # run_exp jhead/seeds/not_kitty.jpg jhead "jhead/jhead @@" 45 | # run_exp tiff2pdf/seeds/not_kitty.tiff tiff2pdf "tiff2pdf/tiff2pdf_nopie @@" 46 | # run_exp advmng/seeds/mappy.mng advmng "advmng/advmng -l @@" 47 | # run_exp advzip/seeds/small_archive.zip advzip "advzip/advzip -l @@" 48 | # run_exp gocr/seeds/not_kitty.png gocr "gocr/gocr @@" 49 | # run_exp optipng/seeds/not_kitty.png optipng "optipng/optipng -out /dev/null @@" 50 | -------------------------------------------------------------------------------- /scripts/split_queries_in_files.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import z3 4 | import re 5 | import os 6 | import sys 7 | 8 | if len(sys.argv) < 3: 9 | print("USAGE: %s smt2_file directory", sys.argv[0]) 10 | exit(1) 11 | 12 | def deduplicate_query(query): 13 | if query.decl().kind() == z3.Z3_OP_AND: 14 | branch_condition = query.children()[0] # preserve branch condition 15 | # first position 16 | other_asserts = query.children()[1:] 17 | return z3.And(*([branch_condition] + list(set(other_asserts)))) 18 | return query 19 | 20 | def find_inputs(query): 21 | inputs = re.findall(r"k![0-9]+", query.sexpr().replace("\n", "")) 22 | return set(inputs) 23 | 24 | def find_addresses(filename): 25 | fin = open(filename, "r") 26 | addresses = [] 27 | for line in fin: 28 | if line.startswith("; ADDRESS "): 29 | address = int(line.strip().split(" ")[2], 16) 30 | addresses.append(address) 31 | fin.close() 32 | return addresses 33 | 34 | smt_file = sys.argv[1] 35 | directory = sys.argv[2] 36 | 37 | queries = z3.parse_smt2_file(smt_file) 38 | addresses = find_addresses(smt_file) 39 | has_address = len(addresses) > 0 40 | 41 | if not has_address: 42 | print("WARNING: no addresses") 43 | else: 44 | assert len(addresses) == len(queries) 45 | 46 | if not os.path.exists(directory): 47 | os.mkdir(directory) 48 | 49 | i = 0 50 | for query in queries: 51 | # query = deduplicate_query(query) 52 | filename = "query_%03d_@_0x%x.smt2" % (i, addresses[i] if has_address else 0) 53 | fout = open(directory + "/" + filename, "w") 54 | for inp in find_inputs(query): 55 | fout.write("(declare-const %s (_ BitVec 8))\n" % inp) 56 | fout.write("(assert \n" + query.sexpr() + "\n)\n(check-sat)") 57 | fout.close() 58 | i += 1 59 | -------------------------------------------------------------------------------- /tests/001_its.smt2: -------------------------------------------------------------------------------- 1 | (declare-const k!0 (_ BitVec 8)) 2 | (declare-const k!1 (_ BitVec 8)) 3 | (declare-const k!2 (_ BitVec 8)) 4 | (declare-const k!3 (_ BitVec 8)) 5 | 6 | (assert 7 | (= #xaabbccdd (concat k!0 k!1 k!2 k!3))) 8 | -------------------------------------------------------------------------------- /tests/002_arithm.smt2: -------------------------------------------------------------------------------- 1 | (declare-const k!0 (_ BitVec 8)) 2 | (declare-const k!1 (_ BitVec 8)) 3 | (declare-const k!2 (_ BitVec 8)) 4 | (declare-const k!3 (_ BitVec 8)) 5 | 6 | (assert 7 | (= 8 | #xdeadbeef 9 | (bvadd 10 | (concat k!0 k!1 k!2 k!3) 11 | #xabadcafe))) 12 | -------------------------------------------------------------------------------- /tests/003_arithm.smt2: -------------------------------------------------------------------------------- 1 | (declare-const k!0 (_ BitVec 8)) 2 | (declare-const k!1 (_ BitVec 8)) 3 | (declare-const k!2 (_ BitVec 8)) 4 | (declare-const k!3 (_ BitVec 8)) 5 | 6 | (assert 7 | (= 8 | #x00000000 9 | (bvadd 10 | (concat k!0 k!1 k!2 k!3) 11 | #xabadcafe))) 12 | -------------------------------------------------------------------------------- /tests/004_arithm.smt2: -------------------------------------------------------------------------------- 1 | (declare-const k!0 (_ BitVec 8)) 2 | (declare-const k!1 (_ BitVec 8)) 3 | (declare-const k!2 (_ BitVec 8)) 4 | (declare-const k!3 (_ BitVec 8)) 5 | 6 | (assert 7 | (and 8 | (bvult 9 | #x0000ffff 10 | (concat k!0 k!1 k!2 k!3)) 11 | (bvugt 12 | #x00010001 13 | (concat k!0 k!1 k!2 k!3)))) 14 | -------------------------------------------------------------------------------- /tests/005_arithm.smt2: -------------------------------------------------------------------------------- 1 | (declare-const k!0 (_ BitVec 8)) 2 | (declare-const k!1 (_ BitVec 8)) 3 | (declare-const k!2 (_ BitVec 8)) 4 | (declare-const k!3 (_ BitVec 8)) 5 | 6 | (assert 7 | (and 8 | (bvult 9 | #x0000ffff 10 | (bvadd 11 | (concat k!0 k!1 k!2 k!3) 12 | #xabadcafe)) 13 | (bvugt 14 | #x00010001 15 | (bvadd 16 | (concat k!0 k!1 k!2 k!3) 17 | #xabadcafe)))) 18 | -------------------------------------------------------------------------------- /tests/run.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import subprocess 4 | import pytest 5 | import os 6 | 7 | SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) 8 | FUZZY_BIN = os.path.join(SCRIPT_DIR, "../build/bin/fuzzy-solver") 9 | if "FUZZY_BIN" in os.environ: 10 | FUZZY_BIN = os.environ["FUZZY_BIN"] 11 | 12 | ZERO_SEED = os.path.join(SCRIPT_DIR, "zero_seed.bin") 13 | 14 | def get_path(query): 15 | return os.path.join(SCRIPT_DIR, query) 16 | 17 | def common(query, seed): 18 | cmd = [FUZZY_BIN, "--notui", "-q", query, "-s", seed] 19 | out = subprocess.check_output(cmd) 20 | return b"SAT" in out 21 | 22 | def test_its_000(): 23 | assert common(get_path("001_its.smt2"), ZERO_SEED) 24 | 25 | def test_arithm_000(): 26 | assert common(get_path("002_arithm.smt2"), ZERO_SEED) 27 | 28 | def test_arithm_001(): 29 | assert common(get_path("003_arithm.smt2"), ZERO_SEED) 30 | 31 | def test_arithm_002(): 32 | assert common(get_path("004_arithm.smt2"), ZERO_SEED) 33 | 34 | def test_arithm_003(): 35 | assert common(get_path("005_arithm.smt2"), ZERO_SEED) 36 | -------------------------------------------------------------------------------- /tests/zero_seed.bin: -------------------------------------------------------------------------------- 1 | 0000 -------------------------------------------------------------------------------- /tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.7) 2 | 3 | macro(LinkBin exe_name) 4 | target_link_libraries(${exe_name} LINK_PUBLIC libz3) 5 | target_link_libraries(${exe_name} LINK_PUBLIC Z3Fuzzy_static) 6 | target_include_directories(${exe_name} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../fuzzolic-z3/src/api") 7 | target_include_directories(${exe_name} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../lib") 8 | endmacro() 9 | 10 | add_executable(fuzzy-solver 11 | fuzzy-solver-notify.c 12 | pretty-print.c) 13 | LinkBin(fuzzy-solver) 14 | 15 | add_executable(fuzzy-solver-vs-z3 16 | fuzzy-solver-vs-z3.c 17 | pretty-print.c) 18 | LinkBin(fuzzy-solver-vs-z3) 19 | 20 | add_executable(stats-collection-fuzzy 21 | stats-collection-fuzzy.c 22 | pretty-print.c) 23 | LinkBin(stats-collection-fuzzy) 24 | 25 | add_executable(stats-collection-z3 26 | stats-collection-z3.c 27 | pretty-print.c) 28 | LinkBin(stats-collection-z3) 29 | -------------------------------------------------------------------------------- /tools/debug-eval.c: -------------------------------------------------------------------------------- 1 | #define FUZZY_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "pretty-print.h" 8 | #include "z3-fuzzy.h" 9 | 10 | #define TIMEOUT 1000 11 | 12 | #define USE_PP 13 | 14 | unsigned char* inputs = NULL; 15 | unsigned long num_inputs = 0; 16 | unsigned total = 0; 17 | unsigned current = 0; 18 | fuzzy_ctx_t fctx; 19 | 20 | void debug_eval(Z3_context ctx, Z3_ast expr) 21 | { 22 | switch (Z3_get_ast_kind(ctx, expr)) { 23 | case Z3_APP_AST: { 24 | Z3_app app = Z3_to_app(ctx, expr); 25 | unsigned num_args = Z3_get_app_num_args(ctx, app); 26 | 27 | unsigned i; 28 | for (i = 0; i < num_args; ++i) { 29 | Z3_ast child = Z3_get_app_arg(ctx, app, i); 30 | debug_eval(ctx, child); 31 | } 32 | 33 | Z3_sort expr_sort = Z3_get_sort(ctx, expr); 34 | if (Z3_get_sort_kind(ctx, expr_sort) == Z3_BV_SORT && 35 | Z3_get_bv_sort_size(ctx, expr_sort) > 64) 36 | break; 37 | 38 | // z3 39 | unsigned long res_z3 = z3fuzz_evaluate_expression_z3( 40 | &fctx, expr, fctx.testcases.data[0].z3_values); 41 | 42 | // fuzzy 43 | unsigned long res_fuzzy = z3fuzz_evaluate_expression( 44 | &fctx, expr, inputs); 45 | 46 | if (res_fuzzy != res_z3) { 47 | printf("different evaluate\n" 48 | "fuzzy: 0x%lx\n" 49 | "z3: 0x%lx\n\n" 50 | "%s\n", 51 | res_fuzzy, res_z3, Z3_ast_to_string(ctx, expr)); 52 | exit(1); 53 | } 54 | break; 55 | } 56 | case Z3_NUMERAL_AST: { 57 | break; 58 | } 59 | default: { 60 | assert(0 && "z3_jit_eval() unknown ast_kind"); 61 | } 62 | } 63 | current++; 64 | 65 | #ifdef USE_PP 66 | pp_printf(0, 1, "%u / %u", current, total); 67 | pp_set_line(3); 68 | #endif 69 | } 70 | 71 | unsigned count_apps(Z3_context ctx, Z3_ast expr) 72 | { 73 | unsigned counter = 0; 74 | switch (Z3_get_ast_kind(ctx, expr)) { 75 | case Z3_APP_AST: { 76 | Z3_app app = Z3_to_app(ctx, expr); 77 | unsigned num_args = Z3_get_app_num_args(ctx, app); 78 | 79 | counter = 1; 80 | unsigned i; 81 | for (i = 0; i < num_args; ++i) { 82 | Z3_ast child = Z3_get_app_arg(ctx, app, i); 83 | counter += count_apps(ctx, child); 84 | } 85 | break; 86 | } 87 | case Z3_NUMERAL_AST: { 88 | break; 89 | } 90 | default: { 91 | assert(0 && "z3_jit_eval() unknown ast_kind"); 92 | } 93 | } 94 | return counter; 95 | } 96 | 97 | static inline void usage(char* filename) 98 | { 99 | fprintf(stderr, "wrong argv. usage:\n%s query_filename seed\n", filename); 100 | exit(1); 101 | } 102 | 103 | static inline void init_input_data(char* filename) 104 | { 105 | FILE* fp = fopen(filename, "r"); 106 | int res, i = 0; 107 | unsigned char c; 108 | 109 | assert(fp != NULL && "fopen() failed"); 110 | 111 | fseek(fp, 0L, SEEK_END); 112 | num_inputs = ftell(fp); 113 | fseek(fp, 0L, SEEK_SET); 114 | inputs = (unsigned char*)malloc(sizeof(unsigned char) * num_inputs); 115 | while (1) { 116 | res = fread(&c, sizeof(char), 1, fp); 117 | if (res != 1) 118 | break; 119 | inputs[i] = c; 120 | i++; 121 | } 122 | fclose(fp); 123 | } 124 | 125 | int main(int argc, char** argv) 126 | { 127 | 128 | if (argc < 3) 129 | usage(argv[0]); 130 | 131 | char* query_filename = argv[1]; 132 | char* seed_filename = argv[2]; 133 | Z3_config cfg = Z3_mk_config(); 134 | Z3_context ctx = Z3_mk_context(cfg); 135 | char var_name[128]; 136 | 137 | init_input_data(seed_filename); 138 | 139 | Z3_ast* str_symbols = (Z3_ast*)malloc(sizeof(Z3_ast) * num_inputs); 140 | Z3_ast* int_symbols = (Z3_ast*)malloc(sizeof(Z3_ast) * num_inputs); 141 | Z3_sort bsort = Z3_mk_bv_sort(ctx, 8); 142 | unsigned i; 143 | for (i = 0; i < num_inputs; ++i) { 144 | int n = snprintf(var_name, sizeof(var_name), "k!%u", i); 145 | assert(n > 0 && n < sizeof(var_name) && "symbol name too long"); 146 | Z3_symbol s = Z3_mk_string_symbol(ctx, var_name); 147 | Z3_ast s_bv = Z3_mk_const(ctx, s, bsort); 148 | str_symbols[i] = s_bv; 149 | s = Z3_mk_int_symbol(ctx, i); 150 | s_bv = Z3_mk_const(ctx, s, bsort); 151 | int_symbols[i] = s_bv; 152 | } 153 | 154 | Z3_ast_vector queries = 155 | Z3_parse_smtlib2_file(ctx, query_filename, 0, 0, 0, 0, 0, 0); 156 | Z3_ast_vector_inc_ref(ctx, queries); 157 | unsigned num_queries = Z3_ast_vector_size(ctx, queries); 158 | assert(num_queries == 1 && "only one query is allowed"); 159 | 160 | Z3_ast bv_tmp = Z3_ast_vector_get(ctx, queries, 0); 161 | Z3_ast_vector_dec_ref(ctx, queries); 162 | 163 | Z3_ast bv = bv_tmp; 164 | bv = Z3_substitute(ctx, bv, num_inputs, str_symbols, int_symbols); 165 | puts("[+] BV loaded"); 166 | 167 | z3fuzz_init(&fctx, ctx, seed_filename, NULL, NULL, TIMEOUT); 168 | puts("[+] FCTX initialized"); 169 | 170 | pp_init(); 171 | total = count_apps(ctx, bv); 172 | puts("[+] PP initialized"); 173 | 174 | debug_eval(ctx, bv); 175 | 176 | z3fuzz_free(&fctx); 177 | return 0; 178 | } 179 | -------------------------------------------------------------------------------- /tools/eval-driver.c: -------------------------------------------------------------------------------- 1 | #define FUZZY_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include "z3-fuzzy.h" 7 | #include "pretty-print.h" 8 | 9 | #define NUM_ITERATIONS 1000 10 | #define TIMEOUT 1000 11 | 12 | static unsigned char* inputs; 13 | fuzzy_ctx_t fctx; 14 | 15 | void long_to_char_array(unsigned long* in, unsigned char* out, unsigned size) 16 | { 17 | unsigned i; 18 | for (i = 0; i < size; ++i) 19 | out[i] = (unsigned char)in[i]; 20 | } 21 | 22 | static inline unsigned long compute_time_usec(struct timeval* start, 23 | struct timeval* end) 24 | { 25 | return ((end->tv_sec - start->tv_sec) * 1000000 + end->tv_usec - 26 | start->tv_usec); 27 | } 28 | 29 | static inline void usage(char* filename) 30 | { 31 | fprintf(stderr, "wrong argv. usage:\n%s query_filename seed\n", filename); 32 | exit(1); 33 | } 34 | 35 | int main(int argc, char* argv[]) 36 | { 37 | if (argc < 2) 38 | usage(argv[0]); 39 | 40 | char* query_filename = argv[1]; 41 | char* seed_filename = argv[2]; 42 | Z3_config cfg = Z3_mk_config(); 43 | Z3_context ctx = Z3_mk_context(cfg); 44 | Z3_ast query; 45 | Z3_ast* str_symbols; 46 | char var_name[128]; 47 | Z3_sort bsort = Z3_mk_bv_sort(ctx, 8); 48 | struct timeval stop, start; 49 | unsigned long elapsed_time_z3 = 0, elapsed_time_fast = 0; 50 | unsigned long num_queries; 51 | unsigned long res1, res2; 52 | unsigned int i; 53 | int n; 54 | 55 | pp_init(); 56 | z3fuzz_init(&fctx, ctx, seed_filename, NULL, NULL, TIMEOUT); 57 | 58 | str_symbols = (Z3_ast*)malloc(sizeof(Z3_ast) * fctx.n_symbols); 59 | for (i = 0; i < fctx.n_symbols; ++i) { 60 | n = snprintf(var_name, sizeof(var_name), "k!%u", i); 61 | assert(n > 0 && n < sizeof(var_name) && "symbol name too long"); 62 | Z3_symbol s = Z3_mk_string_symbol(ctx, var_name); 63 | Z3_ast s_bv = Z3_mk_const(ctx, s, bsort); 64 | str_symbols[i] = s_bv; 65 | } 66 | 67 | Z3_ast_vector queries = 68 | Z3_parse_smtlib2_file(ctx, query_filename, 0, 0, 0, 0, 0, 0); 69 | Z3_ast_vector_inc_ref(ctx, queries); 70 | 71 | num_queries = Z3_ast_vector_size(ctx, queries); 72 | assert(num_queries == 1 && "only one query is allowed"); 73 | 74 | testcase_t* testcase = &fctx.testcases.data[0]; 75 | inputs = 76 | (unsigned char*)malloc(sizeof(unsigned char) * testcase->values_len); 77 | long_to_char_array(testcase->values, inputs, testcase->values_len); 78 | query = Z3_ast_vector_get(ctx, queries, 0); 79 | query = 80 | Z3_substitute(ctx, query, fctx.n_symbols, str_symbols, fctx.symbols); 81 | Z3_ast_vector_dec_ref(ctx, queries); 82 | 83 | for (i = 0; i < NUM_ITERATIONS; ++i) { 84 | pp_printf(0, 1, "iteration %d/%d", i, NUM_ITERATIONS); 85 | 86 | gettimeofday(&start, NULL); 87 | res1 = z3fuzz_evaluate_expression(&fctx, query, inputs); 88 | gettimeofday(&stop, NULL); 89 | elapsed_time_fast += compute_time_usec(&start, &stop); 90 | 91 | gettimeofday(&start, NULL); 92 | res2 = z3fuzz_evaluate_expression_z3(&fctx, query, testcase->z3_values); 93 | gettimeofday(&stop, NULL); 94 | elapsed_time_z3 += compute_time_usec(&start, &stop); 95 | 96 | assert(res1 == res2 && "bug in evaluate!"); 97 | } 98 | 99 | z3fuzz_free(&fctx); 100 | 101 | pp_set_col(0); 102 | pp_set_line(3); 103 | 104 | printf("Res: 0x%lx\n", res1); 105 | printf("Elapsed time fast:\t%ld usec\n", elapsed_time_fast / 1000); 106 | printf("Elapsed time z3:\t%ld usec\n", elapsed_time_z3 / 1000); 107 | 108 | free(inputs); 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /tools/findall-driver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "z3-fuzzy.h" 6 | 7 | #define NUM_ITERATIONS 1000 8 | #define TIMEOUT 1000 9 | 10 | fuzzy_ctx_t fctx; 11 | 12 | static inline unsigned long compute_time_usec(struct timeval* start, 13 | struct timeval* end) 14 | { 15 | return ((end->tv_sec - start->tv_sec) * 1000000 + end->tv_usec - 16 | start->tv_usec); 17 | } 18 | 19 | static inline void usage(char* filename) 20 | { 21 | fprintf(stderr, "wrong argv. usage:\n%s pi_filename bv_filename seed\n", 22 | filename); 23 | exit(1); 24 | } 25 | 26 | static fuzzy_findall_res_t findall_callback(const unsigned char* out_bytes, 27 | unsigned long out_bytes_len, 28 | unsigned long val) 29 | { 30 | printf("> found value 0x%016lx\n", val); 31 | return Z3FUZZ_GIVE_NEXT; 32 | } 33 | 34 | int main(int argc, char* argv[]) 35 | { 36 | if (argc < 3) 37 | usage(argv[0]); 38 | 39 | char* pi_filename = argv[1]; 40 | char* bv_filename = argv[2]; 41 | char* seed_filename = argv[3]; 42 | Z3_config cfg = Z3_mk_config(); 43 | Z3_context ctx = Z3_mk_context(cfg); 44 | Z3_ast* str_symbols; 45 | char var_name[128]; 46 | Z3_sort bsort = Z3_mk_bv_sort(ctx, 8); 47 | struct timeval stop, start; 48 | unsigned long elapsed_time = 0; 49 | unsigned long num_assert; 50 | unsigned int i; 51 | int n; 52 | 53 | z3fuzz_init(&fctx, ctx, seed_filename, NULL, NULL, TIMEOUT); 54 | 55 | str_symbols = (Z3_ast*)malloc(sizeof(Z3_ast) * fctx.n_symbols); 56 | for (i = 0; i < fctx.n_symbols; ++i) { 57 | n = snprintf(var_name, sizeof(var_name), "k!%u", i); 58 | assert(n > 0 && n < sizeof(var_name) && "symbol name too long"); 59 | Z3_symbol s = Z3_mk_string_symbol(ctx, var_name); 60 | Z3_ast s_bv = Z3_mk_const(ctx, s, bsort); 61 | str_symbols[i] = s_bv; 62 | } 63 | 64 | Z3_ast_vector pi_vector = 65 | Z3_parse_smtlib2_file(ctx, pi_filename, 0, 0, 0, 0, 0, 0); 66 | Z3_ast_vector_inc_ref(ctx, pi_vector); 67 | 68 | num_assert = Z3_ast_vector_size(ctx, pi_vector); 69 | assert(num_assert > 0 && "empty pi"); 70 | 71 | Z3_ast asserts[num_assert]; 72 | for (i = 0; i < num_assert; ++i) { 73 | asserts[i] = Z3_ast_vector_get(ctx, pi_vector, i); 74 | } 75 | Z3_ast_vector_dec_ref(ctx, pi_vector); 76 | 77 | Z3_ast pi = Z3_mk_and(ctx, num_assert, asserts); 78 | pi = Z3_substitute(ctx, pi, fctx.n_symbols, str_symbols, fctx.symbols); 79 | puts("[+] PI loaded"); 80 | 81 | Z3_ast_vector bv_asserts = 82 | Z3_parse_smtlib2_file(ctx, bv_filename, 0, 0, 0, 0, 0, 0); 83 | Z3_ast_vector_inc_ref(ctx, bv_asserts); 84 | assert(Z3_ast_vector_size(ctx, bv_asserts) == 1 && "bv must be unique"); 85 | 86 | // I can only parse asserts. So I assume something like (== BV whatever) 87 | Z3_ast bv_tmp = Z3_ast_vector_get(ctx, bv_asserts, 0); 88 | Z3_app bv_tmp_app = Z3_to_app(ctx, bv_tmp); 89 | Z3_ast bv = Z3_get_app_arg(ctx, bv_tmp_app, 0); 90 | bv = Z3_substitute(ctx, bv, fctx.n_symbols, str_symbols, fctx.symbols); 91 | Z3_ast_vector_dec_ref(ctx, bv_asserts); 92 | puts("[+] BV loaded\n"); 93 | 94 | gettimeofday(&start, NULL); 95 | 96 | puts("-- FINDALL --"); 97 | z3fuzz_find_all_values(&fctx, bv, pi, findall_callback); 98 | puts("-- FINDALL GD MIN --"); 99 | z3fuzz_find_all_values_gd(&fctx, bv, pi, 1, findall_callback); 100 | puts("-- FINDALL GD MAX --"); 101 | z3fuzz_find_all_values_gd(&fctx, bv, pi, 0, findall_callback); 102 | puts("--------------------"); 103 | 104 | gettimeofday(&stop, NULL); 105 | elapsed_time = compute_time_usec(&start, &stop); 106 | printf("elapsed time: %.03Lf msec\n", elapsed_time / 1000.0l); 107 | 108 | z3fuzz_free(&fctx); 109 | free(str_symbols); 110 | Z3_del_config(cfg); 111 | return 0; 112 | } 113 | -------------------------------------------------------------------------------- /tools/fuzzy-solver-notify.c: -------------------------------------------------------------------------------- 1 | #define FUZZY_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "pretty-print.h" 10 | #include "z3-fuzzy.h" 11 | 12 | #define BOLD(s) "\033[1m\033[37m" s "\033[0m" 13 | 14 | #define TIMEOUT 1000 15 | 16 | static fuzzy_ctx_t fctx; 17 | 18 | static inline unsigned long compute_time_msec(struct timeval* start, 19 | struct timeval* end) 20 | { 21 | return ((end->tv_sec - start->tv_sec) * 1000000 + end->tv_usec - 22 | start->tv_usec) / 23 | 1000; 24 | } 25 | 26 | static inline Z3_ast find_branch_condition(Z3_ast query) 27 | { 28 | if (Z3_get_ast_kind(fctx.z3_ctx, query) != Z3_APP_AST) 29 | return query; 30 | 31 | Z3_app app = Z3_to_app(fctx.z3_ctx, query); 32 | Z3_func_decl decl = Z3_get_app_decl(fctx.z3_ctx, app); 33 | Z3_decl_kind decl_kind = Z3_get_decl_kind(fctx.z3_ctx, decl); 34 | if (decl_kind != Z3_OP_AND) 35 | return query; 36 | 37 | return Z3_get_app_arg(fctx.z3_ctx, app, 0); 38 | } 39 | 40 | static inline void divide_query_in_assertions(Z3_ast query, Z3_ast** assertions, 41 | unsigned* n) 42 | { 43 | if (Z3_get_ast_kind(fctx.z3_ctx, query) != Z3_APP_AST) { 44 | *assertions = NULL; 45 | *n = 0; 46 | return; 47 | } 48 | 49 | Z3_app app = Z3_to_app(fctx.z3_ctx, query); 50 | Z3_func_decl decl = Z3_get_app_decl(fctx.z3_ctx, app); 51 | Z3_decl_kind decl_kind = Z3_get_decl_kind(fctx.z3_ctx, decl); 52 | if (decl_kind != Z3_OP_AND || Z3_get_app_num_args(fctx.z3_ctx, app) == 0) { 53 | *assertions = NULL; 54 | *n = 0; 55 | return; 56 | } 57 | 58 | *n = Z3_get_app_num_args(fctx.z3_ctx, app) - 1; 59 | *assertions = (Z3_ast*)malloc(sizeof(Z3_ast) * *n); 60 | 61 | unsigned i; 62 | for (i = 1; i < *n + 1; ++i) { 63 | Z3_ast v = Z3_get_app_arg(fctx.z3_ctx, app, i); 64 | (*assertions)[i - 1] = v; 65 | } 66 | } 67 | 68 | static Z3_func_decl* fdecl_cache = NULL; 69 | static size_t fdecl_cache_size = 0; 70 | static Z3_ast byte_val_cache[256] = {0}; 71 | 72 | static uint64_t Z3_eval(Z3_context ctx, Z3_ast query, uint64_t* data, 73 | uint8_t* symbols_sizes, size_t size) 74 | { 75 | uint64_t res; 76 | Z3_model z3_m = Z3_mk_model(ctx); 77 | Z3_model_inc_ref(ctx, z3_m); 78 | Z3_ast* z3_vals = (Z3_ast*)calloc(sizeof(Z3_ast), size); 79 | 80 | if (fdecl_cache == NULL) { 81 | fdecl_cache = (Z3_func_decl*)calloc(sizeof(Z3_func_decl), size); 82 | fdecl_cache_size = size; 83 | } else if (fdecl_cache_size < size) { 84 | fdecl_cache = 85 | (Z3_func_decl*)realloc(fdecl_cache, size * sizeof(Z3_func_decl)); 86 | size_t i; 87 | for (i = fdecl_cache_size; i < size; ++i) 88 | fdecl_cache[i] = 0; 89 | fdecl_cache_size = size; 90 | } 91 | 92 | unsigned i; 93 | for (i = 0; i < size; ++i) { 94 | Z3_ast e; 95 | if (symbols_sizes[i] == 8 && byte_val_cache[data[i]] != NULL) 96 | e = byte_val_cache[data[i] & 0xff]; 97 | else { 98 | Z3_sort sort = Z3_mk_bv_sort(ctx, symbols_sizes[i]); 99 | e = Z3_mk_unsigned_int64(ctx, data[i], sort); 100 | Z3_inc_ref(ctx, e); 101 | if (symbols_sizes[i] == 8) 102 | byte_val_cache[data[i] & 0xff] = e; 103 | else 104 | z3_vals[i] = e; 105 | } 106 | 107 | Z3_func_decl decl; 108 | if (fdecl_cache[i] != NULL) 109 | decl = fdecl_cache[i]; 110 | else { 111 | Z3_sort sort = Z3_mk_bv_sort(ctx, symbols_sizes[i]); 112 | Z3_symbol s = Z3_mk_int_symbol(ctx, i); 113 | decl = Z3_mk_func_decl(ctx, s, 0, NULL, sort); 114 | fdecl_cache[i] = decl; 115 | } 116 | 117 | Z3_add_const_interp(ctx, z3_m, decl, e); 118 | } 119 | 120 | // evaluate the query in the model 121 | Z3_ast solution; 122 | Z3_bool successfulEval = 123 | Z3_model_eval(ctx, z3_m, query, Z3_TRUE, &solution); 124 | if (!successfulEval) { 125 | puts("Failed to evaluate model"); 126 | exit(1); 127 | } 128 | 129 | Z3_model_dec_ref(ctx, z3_m); 130 | if (Z3_get_ast_kind(ctx, solution) == Z3_NUMERAL_AST) { 131 | Z3_bool successGet = Z3_get_numeral_uint64(ctx, solution, &res); 132 | if (successGet != Z3_TRUE) { 133 | puts("Z3_get_numeral_uint64() failed to get constant"); 134 | exit(1); 135 | } 136 | } else { 137 | res = Z3_get_bool_value(ctx, solution) == Z3_L_TRUE ? 1UL : 0UL; 138 | } 139 | 140 | for (i = 0; i < size; ++i) 141 | if (z3_vals[i] != NULL) 142 | Z3_dec_ref(ctx, z3_vals[i]); 143 | free(z3_vals); 144 | 145 | return res; 146 | } 147 | 148 | static inline void print_status(unsigned long current_query, 149 | unsigned long num_queries) 150 | { 151 | 152 | memory_impact_stats_t m_stats; 153 | z3fuzz_get_mem_stats(&fctx, &m_stats); 154 | 155 | pp_printf(0, 4, BOLD("query") " %ld/%ld", current_query, num_queries); 156 | pp_print_string( 157 | 1, 2, 158 | "o-------------------------------------------------------------o"); 159 | pp_printf(2, 2, "| " BOLD("num eval:") " %ld", fctx.stats.num_evaluate); 160 | pp_print_string(3, 2, "| "); 161 | pp_printf(4, 2, "| " BOLD("its:") " %ld", fctx.stats.input_to_state); 162 | pp_printf(5, 2, "| " BOLD("sm:") " %ld", fctx.stats.simple_math); 163 | pp_printf(6, 2, "| " BOLD("rbf:") " %ld", 164 | fctx.stats.range_brute_force); 165 | pp_printf(7, 2, "| " BOLD("gd:") " %ld", 166 | fctx.stats.gradient_descend); 167 | pp_printf(8, 2, "| " BOLD("bit flips:") " %ld, %ld, %ld", fctx.stats.flip1, 168 | fctx.stats.flip2, fctx.stats.flip4); 169 | pp_printf(9, 2, "| " BOLD("arithms:") " %ld", 170 | fctx.stats.arith8_sum + fctx.stats.arith8_sub + 171 | fctx.stats.arith16_sum_LE + fctx.stats.arith16_sum_BE + 172 | fctx.stats.arith16_sub_LE + fctx.stats.arith16_sub_BE + 173 | fctx.stats.arith32_sum_LE + fctx.stats.arith32_sum_BE + 174 | fctx.stats.arith32_sub_LE + fctx.stats.arith32_sub_BE + 175 | fctx.stats.arith64_sum_LE + fctx.stats.arith64_sum_BE + 176 | fctx.stats.arith64_sub_LE + fctx.stats.arith64_sub_BE); 177 | pp_printf(10, 2, "| " BOLD("multigoal:") " %ld", fctx.stats.multigoal); 178 | pp_print_string(11, 2, "| "); 179 | pp_printf(12, 2, "| " BOLD("# confl:") " %ld", 180 | fctx.stats.num_conflicting); 181 | pp_printf(13, 2, "| " BOLD("confl cache size:") " %ld", 182 | m_stats.conflicting_ast_size); 183 | pp_printf(14, 2, "| " BOLD("num timeouts:") " %ld", 184 | fctx.stats.num_timeouts); 185 | pp_printf(15, 2, "| "); 186 | pp_printf(16, 2, "| " BOLD("avg eval time:") " %.03lf usec", 187 | fctx.stats.avg_time_for_eval); 188 | 189 | pp_printf(2, 30, BOLD("sat:") " %ld (%ld) [%ld opt]", 190 | fctx.stats.num_sat, fctx.stats.sat_in_seed, fctx.stats.opt_sat); 191 | pp_print_string(2, 64, "|"); 192 | pp_print_string(3, 64, "|"); 193 | pp_printf(4, 30, BOLD("its ext:") " %ld", fctx.stats.input_to_state_ext); 194 | pp_print_string(4, 64, "|"); 195 | pp_printf(5, 30, BOLD("bf:") " %ld", fctx.stats.brute_force); 196 | pp_print_string(5, 64, "|"); 197 | pp_printf(6, 30, BOLD("rbf opt:") " %ld", 198 | fctx.stats.range_brute_force_opt); 199 | pp_print_string(6, 64, "|"); 200 | pp_printf(7, 30, BOLD("havoc:") " %ld", fctx.stats.havoc); 201 | pp_print_string(7, 64, "|"); 202 | pp_printf(8, 30, BOLD("byte flips:") " %ld, %ld, %ld, %ld", 203 | fctx.stats.flip8, fctx.stats.flip16, fctx.stats.flip32, 204 | fctx.stats.flip64); 205 | pp_print_string(8, 64, "|"); 206 | pp_printf(9, 30, BOLD("ints:") " %ld", 207 | fctx.stats.int8 + fctx.stats.int16 + fctx.stats.int32 + 208 | fctx.stats.int64); 209 | pp_print_string(9, 64, "|"); 210 | pp_printf(10, 30, BOLD("fallbacks:") " %ld (%ld)si (%ld)nt", 211 | fctx.stats.conflicting_fallbacks, 212 | fctx.stats.conflicting_fallbacks_same_inputs, 213 | fctx.stats.conflicting_fallbacks_no_true); 214 | pp_print_string(10, 64, "|"); 215 | pp_print_string(11, 64, "|"); 216 | pp_printf(12, 30, BOLD("# univ def:") " %ld", 217 | fctx.stats.num_univocally_defined); 218 | pp_print_string(12, 64, "|"); 219 | pp_printf(13, 30, BOLD("ast info cache size:") " %ld", 220 | m_stats.ast_info_cache_size); 221 | pp_print_string(13, 64, "|"); 222 | pp_printf(14, 30, BOLD("ast info cache hits:") " %ld", 223 | fctx.stats.ast_info_cache_hits); 224 | pp_print_string(14, 64, "|"); 225 | pp_print_string(15, 64, "|"); 226 | pp_print_string(16, 64, "|"); 227 | 228 | pp_print_string( 229 | 17, 2, 230 | "o-------------------------------------------------------------o"); 231 | 232 | pp_set_col(0); 233 | pp_set_line(18); 234 | } 235 | 236 | static char g_sat_queries_path[500] = {0}; 237 | static char g_proof_path[500] = {0}; 238 | 239 | static int g_no_tui = 0; 240 | static int g_dump_sat_queries = 0; 241 | static int g_dump_proofs = 0; 242 | static int g_check_consistency = 1; 243 | 244 | static const char* short_opt = "hq:s:o:"; 245 | static struct option long_opt[] = { 246 | {"help", no_argument, NULL, 'h'}, 247 | {"query", required_argument, NULL, 'q'}, 248 | {"seed", required_argument, NULL, 's'}, 249 | {"out", required_argument, NULL, 'o'}, 250 | {"dsat", no_argument, &g_dump_sat_queries, 1}, 251 | {"dproofs", no_argument, &g_dump_proofs, 1}, 252 | {"notui", no_argument, &g_no_tui, 1}, 253 | {NULL, 0, NULL, 0}}; 254 | 255 | static inline void usage(char* filename) 256 | { 257 | fprintf(stderr, 258 | "Usage: %s [OPTIONS]\n" 259 | " -h, --help print this help and exit\n" 260 | " -q, --query SMT2 query filename (required)\n" 261 | " -s, --seed binary seed file (required)\n" 262 | " -o, --out output directory\n" 263 | "\n" 264 | " --dsat dump sat queries\n" 265 | " --dproofs dump sat proofs\n" 266 | " --notui no text UI\n" 267 | "\n", 268 | filename); 269 | } 270 | 271 | int main(int argc, char* argv[]) 272 | { 273 | char* query_filename = NULL; 274 | char* seed_filename = NULL; 275 | char* output_dir = NULL; 276 | int opt; 277 | int option_index = 0; 278 | int n; 279 | 280 | while ((opt = getopt_long(argc, argv, short_opt, long_opt, 281 | &option_index)) != -1) { 282 | switch (opt) { 283 | case 0: 284 | break; 285 | case 'h': 286 | usage(argv[0]); 287 | exit(0); 288 | case 'q': 289 | query_filename = optarg; 290 | break; 291 | case 's': 292 | seed_filename = optarg; 293 | break; 294 | case 'o': 295 | output_dir = optarg; 296 | break; 297 | default: 298 | usage(argv[0]); 299 | } 300 | } 301 | 302 | if (query_filename == NULL || seed_filename == NULL) { 303 | usage(argv[0]); 304 | exit(1); 305 | } 306 | 307 | if ((g_dump_sat_queries || g_dump_proofs) && output_dir == NULL) { 308 | fprintf(stderr, 309 | "ERROR: if dsat or dproofs is set, an output directory must " 310 | "be specified\n"); 311 | exit(1); 312 | } 313 | 314 | struct stat sb; 315 | if (output_dir != NULL) { 316 | if (stat(output_dir, &sb) != 0 || !S_ISDIR(sb.st_mode)) { 317 | fprintf(stderr, "ERROR: %s is not a valid directory\n", output_dir); 318 | exit(1); 319 | } 320 | 321 | strncpy(g_sat_queries_path, output_dir, sizeof(g_sat_queries_path) - 1); 322 | } 323 | 324 | if (output_dir != NULL) { 325 | n = snprintf(g_sat_queries_path, sizeof(g_sat_queries_path), 326 | "%s/sat-queries.smt2", output_dir); 327 | assert(n > 0 && n < sizeof(g_sat_queries_path) && 328 | "snprintf failed (sat_queries)"); 329 | } 330 | 331 | Z3_config cfg = Z3_mk_config(); 332 | Z3_context ctx = Z3_mk_context(cfg); 333 | unsigned char const* proof; 334 | unsigned long proof_size; 335 | char var_name[128]; 336 | Z3_sort bsort = Z3_mk_bv_sort(ctx, 8); 337 | unsigned int i; 338 | 339 | z3fuzz_init(&fctx, ctx, seed_filename, NULL, NULL, TIMEOUT); 340 | 341 | Z3_ast* str_symbols = (Z3_ast*)malloc(sizeof(Z3_ast) * fctx.n_symbols); 342 | for (i = 0; i < fctx.n_symbols; ++i) { 343 | n = snprintf(var_name, sizeof(var_name), "k!%u", i); 344 | assert(n > 0 && n < sizeof(var_name) && "symbol name too long"); 345 | Z3_symbol s = Z3_mk_string_symbol(ctx, var_name); 346 | Z3_ast s_bv = Z3_mk_const(ctx, s, bsort); 347 | str_symbols[i] = s_bv; 348 | } 349 | 350 | FILE* sat_queries_file = NULL; 351 | if (g_dump_sat_queries) { 352 | sat_queries_file = fopen(g_sat_queries_path, "w"); 353 | setvbuf(sat_queries_file, NULL, _IONBF, 0); 354 | } 355 | 356 | if (!g_no_tui) { 357 | pp_init(); 358 | } 359 | 360 | struct timeval stop, start; 361 | unsigned long elapsed_time = 0, elapsed_time_fast_sat = 0, 362 | elapsed_time_parsing = 0; 363 | 364 | gettimeofday(&start, NULL); 365 | Z3_ast_vector queries = 366 | Z3_parse_smtlib2_file(ctx, query_filename, 0, 0, 0, 0, 0, 0); 367 | Z3_ast_vector_inc_ref(ctx, queries); 368 | gettimeofday(&stop, NULL); 369 | elapsed_time_parsing += compute_time_msec(&start, &stop); 370 | 371 | unsigned long num_queries = 0, sat_queries = 0; 372 | num_queries = Z3_ast_vector_size(ctx, queries); 373 | for (i = 0; i < num_queries; ++i) { 374 | Z3_ast query = Z3_ast_vector_get(ctx, queries, i); 375 | query = Z3_substitute(ctx, query, fctx.n_symbols, str_symbols, 376 | fctx.symbols); 377 | Z3_ast branch_condition = find_branch_condition(query); 378 | Z3_ast* assertions; 379 | unsigned n_assertions; 380 | 381 | Z3_ast query_no_branch; 382 | divide_query_in_assertions(query, &assertions, &n_assertions); 383 | if (n_assertions > 0) 384 | query_no_branch = Z3_mk_and(fctx.z3_ctx, n_assertions, assertions); 385 | else 386 | query_no_branch = Z3_mk_true(fctx.z3_ctx); 387 | 388 | gettimeofday(&start, NULL); 389 | int j; 390 | for (j = 0; j < n_assertions; ++j) { 391 | assert(assertions[j] != NULL && "null assertion!"); 392 | z3fuzz_notify_constraint(&fctx, assertions[j]); 393 | } 394 | int is_sat = z3fuzz_query_check_light( 395 | &fctx, query_no_branch, branch_condition, &proof, &proof_size); 396 | gettimeofday(&stop, NULL); 397 | elapsed_time += compute_time_msec(&start, &stop); 398 | 399 | if (is_sat) { 400 | sat_queries += 1; 401 | elapsed_time_fast_sat += compute_time_msec(&start, &stop); 402 | 403 | if (g_dump_proofs) { 404 | n = snprintf(g_proof_path, sizeof(g_proof_path), 405 | "%s/proof_%02u.bin", output_dir, i); 406 | assert(n > 0 && n < sizeof(g_proof_path) && 407 | "unable to dump proof"); 408 | 409 | z3fuzz_dump_proof(&fctx, g_proof_path, proof, proof_size); 410 | } 411 | 412 | if (g_dump_sat_queries) { 413 | fprintf(sat_queries_file, "(assert\n%s\n)\n", 414 | Z3_ast_to_string(ctx, query)); 415 | } 416 | 417 | if (g_check_consistency) { 418 | testcase_t* curr_t = &fctx.testcases.data[0]; 419 | uint64_t* tmp_proof = malloc(sizeof(uint64_t) * proof_size); 420 | for (j = 0; j < proof_size; ++j) 421 | tmp_proof[j] = proof[j]; 422 | assert(Z3_eval(ctx, query, tmp_proof, curr_t->value_sizes, 423 | proof_size) && 424 | "Invalid solution!"); 425 | free(tmp_proof); 426 | } 427 | } 428 | free(assertions); 429 | 430 | if (!g_no_tui) { 431 | print_status(i, num_queries); 432 | } else { 433 | unsigned long qtime = compute_time_msec(&start, &stop); 434 | fprintf(stdout, "%s, %.3lf\n", is_sat ? "SAT" : "UNKNOWN", 435 | (double)qtime / 1000); 436 | } 437 | } 438 | 439 | if (!g_no_tui) { 440 | print_status(i, num_queries); 441 | 442 | printf("\n" 443 | "num queries: %lu\n" 444 | "fast sat queries: %lu\n" 445 | "elaps time: %.3lf s\n" 446 | "elaps time sat: %.3lf s\n" 447 | "elaps par: %.3lf s\n" 448 | "elaps time + par: %.3lf s\n", 449 | num_queries, sat_queries, (double)elapsed_time / 1000, 450 | (double)elapsed_time_fast_sat / 1000, 451 | (double)elapsed_time_parsing / 1000, 452 | (double)(elapsed_time + elapsed_time_parsing) / 1000); 453 | } 454 | 455 | Z3_ast_vector_dec_ref(ctx, queries); 456 | free(str_symbols); 457 | free(fdecl_cache); 458 | z3fuzz_free(&fctx); 459 | Z3_del_config(cfg); 460 | Z3_del_context(ctx); 461 | 462 | if (g_dump_sat_queries) { 463 | fclose(sat_queries_file); 464 | } 465 | return 0; 466 | } 467 | -------------------------------------------------------------------------------- /tools/fuzzy-solver-vs-z3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "pretty-print.h" 6 | #include "z3-fuzzy.h" 7 | 8 | #define NREP 1 9 | #define Z3_SOLVER_TIMEOUT "10000" 10 | #define FUZZY_SOLVER_TIMEOUT 1000 11 | 12 | fuzzy_ctx_t fctx; 13 | const char* log_filename = "fuzzy_z3.csv"; 14 | FILE* log_file; 15 | const char* flip_info_filename = "fuzzy_flip_info.csv"; 16 | FILE* flip_info_file; 17 | 18 | static inline double compute_time_msec(struct timeval* start, 19 | struct timeval* end) 20 | { 21 | return ((end->tv_sec - start->tv_sec) * 1000000 + end->tv_usec - 22 | start->tv_usec) / 23 | 1000.0L; 24 | } 25 | 26 | static inline Z3_ast find_branch_condition(Z3_ast query) 27 | { 28 | if (Z3_get_ast_kind(fctx.z3_ctx, query) != Z3_APP_AST) 29 | return query; 30 | 31 | Z3_app app = Z3_to_app(fctx.z3_ctx, query); 32 | Z3_func_decl decl = Z3_get_app_decl(fctx.z3_ctx, app); 33 | Z3_decl_kind decl_kind = Z3_get_decl_kind(fctx.z3_ctx, decl); 34 | if (decl_kind != Z3_OP_AND) 35 | return query; 36 | 37 | return Z3_get_app_arg(fctx.z3_ctx, app, 0); 38 | } 39 | 40 | static inline void divide_query_in_assertions(Z3_ast query, Z3_ast** assertions, 41 | unsigned* n) 42 | { 43 | if (Z3_get_ast_kind(fctx.z3_ctx, query) != Z3_APP_AST) { 44 | *assertions = NULL; 45 | *n = 0; 46 | return; 47 | } 48 | 49 | Z3_app app = Z3_to_app(fctx.z3_ctx, query); 50 | Z3_func_decl decl = Z3_get_app_decl(fctx.z3_ctx, app); 51 | Z3_decl_kind decl_kind = Z3_get_decl_kind(fctx.z3_ctx, decl); 52 | if (decl_kind != Z3_OP_AND || Z3_get_app_num_args(fctx.z3_ctx, app) == 0) { 53 | *assertions = NULL; 54 | *n = 0; 55 | return; 56 | } 57 | 58 | *n = Z3_get_app_num_args(fctx.z3_ctx, app) - 1; 59 | *assertions = (Z3_ast*)malloc(sizeof(Z3_ast) * *n); 60 | 61 | unsigned i; 62 | for (i = 1; i < *n + 1; ++i) { 63 | Z3_ast v = Z3_get_app_arg(fctx.z3_ctx, app, i); 64 | (*assertions)[i - 1] = v; 65 | } 66 | } 67 | 68 | static inline void dump_flip_info() 69 | { 70 | fprintf(flip_info_file, 71 | "%ld," // input to state 72 | "%ld," // extended input to state 73 | "%ld," // interval analysis (brute force + range brute force + range 74 | // brute force opt + simple math) 75 | "%ld," // gradient descent 76 | "%ld," // flips 77 | "%ld," // arithms 78 | "%ld," // interesting 79 | "%ld," // havoc 80 | "%ld," // multigoal 81 | "%ld" // sat in seed 82 | , 83 | fctx.stats.input_to_state, fctx.stats.input_to_state_ext, 84 | fctx.stats.brute_force + fctx.stats.range_brute_force + 85 | fctx.stats.range_brute_force_opt + fctx.stats.simple_math, 86 | fctx.stats.gradient_descend, 87 | fctx.stats.flip1 + fctx.stats.flip2 + fctx.stats.flip4 + 88 | fctx.stats.flip8 + fctx.stats.flip16 + fctx.stats.flip32 + 89 | fctx.stats.flip64, 90 | fctx.stats.arith8_sum + fctx.stats.arith8_sub + 91 | fctx.stats.arith16_sum_LE + fctx.stats.arith16_sum_BE + 92 | fctx.stats.arith16_sub_LE + fctx.stats.arith16_sub_BE + 93 | fctx.stats.arith32_sum_LE + fctx.stats.arith32_sum_BE + 94 | fctx.stats.arith32_sub_LE + fctx.stats.arith32_sub_BE + 95 | fctx.stats.arith64_sum_LE + fctx.stats.arith64_sum_BE + 96 | fctx.stats.arith64_sub_LE + fctx.stats.arith64_sub_BE, 97 | fctx.stats.int8 + fctx.stats.int16 + fctx.stats.int32 + 98 | fctx.stats.int64, 99 | fctx.stats.havoc, fctx.stats.multigoal, fctx.stats.sat_in_seed); 100 | } 101 | 102 | static inline void usage(char* filename) 103 | { 104 | fprintf(stderr, "wrong argv. usage:\n%s query_filename seed [test_dir]\n", 105 | filename); 106 | exit(1); 107 | } 108 | 109 | int main(int argc, char* argv[]) 110 | { 111 | if (argc < 3) 112 | usage(argv[0]); 113 | 114 | char* query_filename = argv[1]; 115 | char* seed_filename = argv[2]; 116 | char* tests_dir = argc > 3 ? argv[3] : NULL; 117 | Z3_config cfg = Z3_mk_config(); 118 | Z3_set_param_value(cfg, "timeout", Z3_SOLVER_TIMEOUT); 119 | Z3_context ctx = Z3_mk_context(cfg); 120 | unsigned char const* proof; 121 | unsigned long proof_size; 122 | unsigned long num_queries = 0, fuzzy_sat = 0, z3_sat = 0; 123 | char var_name[128]; 124 | Z3_sort bsort = Z3_mk_bv_sort(ctx, 8); 125 | struct timeval stop, start; 126 | double elapsed_time = 0, cumulative_fuzzy = 0, cumulative_z3 = 0; 127 | unsigned int i, k; 128 | int n; 129 | 130 | log_file = fopen(log_filename, "w"); 131 | setvbuf(log_file, NULL, _IONBF, 0); 132 | flip_info_file = fopen(flip_info_filename, "w"); 133 | setvbuf(flip_info_file, NULL, _IONBF, 0); 134 | 135 | z3fuzz_init(&fctx, ctx, seed_filename, tests_dir, NULL, 136 | FUZZY_SOLVER_TIMEOUT); 137 | 138 | pp_init(); 139 | 140 | Z3_ast* str_symbols = (Z3_ast*)malloc(sizeof(Z3_ast) * fctx.n_symbols); 141 | for (i = 0; i < fctx.n_symbols; ++i) { 142 | n = snprintf(var_name, sizeof(var_name), "k!%u", i); 143 | assert(n > 0 && n < sizeof(var_name) && "symbol name too long"); 144 | Z3_symbol s = Z3_mk_string_symbol(ctx, var_name); 145 | Z3_ast s_bv = Z3_mk_const(ctx, s, bsort); 146 | str_symbols[i] = s_bv; 147 | } 148 | 149 | Z3_ast_vector queries = 150 | Z3_parse_smtlib2_file(ctx, query_filename, 0, 0, 0, 0, 0, 0); 151 | Z3_ast_vector_inc_ref(ctx, queries); 152 | 153 | fprintf(log_file, "time fuzzy,fuzzy res,time z3,z3 res\n"); 154 | 155 | num_queries = Z3_ast_vector_size(ctx, queries); 156 | for (i = 0; i < num_queries; ++i) { 157 | pp_printf(0, 1, "query %ld/%ld", i + 1, num_queries); 158 | 159 | Z3_ast query = Z3_ast_vector_get(ctx, queries, i); 160 | query = Z3_substitute(ctx, query, fctx.n_symbols, str_symbols, 161 | fctx.symbols); 162 | Z3_ast branch_condition = find_branch_condition(query); 163 | Z3_ast* assertions; 164 | unsigned n_assertions; 165 | divide_query_in_assertions(query, &assertions, &n_assertions); 166 | 167 | int is_sat_fuzzy = 0; 168 | int is_sat_z3 = 0; 169 | int is_unknown_z3 = 0; 170 | 171 | pp_printf(6, 1, "running fuzzy..."); 172 | for (k = 0; k < NREP; ++k) { 173 | is_sat_fuzzy = 0; 174 | gettimeofday(&start, NULL); 175 | int j; 176 | for (j = 0; j < n_assertions; ++j) { 177 | assert(assertions[j] != NULL && "null assertion!"); 178 | z3fuzz_notify_constraint(&fctx, assertions[j]); 179 | } 180 | 181 | if (z3fuzz_query_check_light(&fctx, query, branch_condition, &proof, 182 | &proof_size)) 183 | is_sat_fuzzy = 1; 184 | 185 | gettimeofday(&stop, NULL); 186 | elapsed_time = compute_time_msec(&start, &stop); 187 | cumulative_fuzzy += elapsed_time; 188 | fuzzy_sat += is_sat_fuzzy; 189 | 190 | fprintf(log_file, "%.3lf,%s,", elapsed_time, 191 | is_sat_fuzzy ? "sat" : "unknown"); 192 | } 193 | free(assertions); 194 | 195 | pp_printf(6, 1, "running z3..."); 196 | 197 | for (k = 0; k < NREP; ++k) { 198 | is_sat_z3 = 0; 199 | is_unknown_z3 = 0; 200 | 201 | Z3_lbool query_result; 202 | Z3_solver solver = Z3_mk_solver(ctx); 203 | Z3_solver_inc_ref(ctx, solver); 204 | 205 | gettimeofday(&start, NULL); 206 | Z3_solver_assert(ctx, solver, query); 207 | switch ((query_result = Z3_solver_check(ctx, solver))) { 208 | case Z3_L_FALSE: 209 | break; 210 | case Z3_L_UNDEF: 211 | is_unknown_z3 = 1; 212 | break; 213 | case Z3_L_TRUE: 214 | is_sat_z3 = 1; 215 | break; 216 | } 217 | 218 | gettimeofday(&stop, NULL); 219 | elapsed_time = compute_time_msec(&start, &stop); 220 | cumulative_z3 += elapsed_time; 221 | z3_sat += is_sat_z3; 222 | 223 | Z3_solver_dec_ref(ctx, solver); 224 | fprintf(log_file, "%.3lf,%s", elapsed_time, 225 | is_sat_z3 ? "sat" : (is_unknown_z3 ? "unknown" : "unsat")); 226 | } 227 | fprintf(log_file, "\n"); 228 | 229 | pp_printf(1, 1, "cumulative z3 %.03lf msec", cumulative_z3 / NREP); 230 | pp_printf(2, 1, "cumulative fuzzy %.03lf msec", 231 | cumulative_fuzzy / NREP); 232 | pp_printf(3, 1, "sat fuzzy %ld", fuzzy_sat / NREP); 233 | pp_printf(4, 1, "sat z3 %ld", z3_sat / NREP); 234 | } 235 | 236 | dump_flip_info(); 237 | 238 | pp_printf(6, 1, "speedup %.02lf x", cumulative_z3 / cumulative_fuzzy); 239 | pp_printf(7, 1, "detected %ld / %ld", fuzzy_sat / NREP, z3_sat / NREP); 240 | pp_set_line(8); 241 | 242 | Z3_ast_vector_dec_ref(ctx, queries); 243 | free(str_symbols); 244 | z3fuzz_free(&fctx); 245 | Z3_del_config(cfg); 246 | Z3_del_context(ctx); 247 | fclose(log_file); 248 | fclose(flip_info_file); 249 | return 0; 250 | } 251 | -------------------------------------------------------------------------------- /tools/fuzzy-solver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "pretty-print.h" 5 | #include "z3-fuzzy.h" 6 | 7 | #define SOLVER_TIMEOUT "10000" // 10 sec // 0 8 | 9 | #define PRINT_STATUS 10 | // #define PRINT_SAT_IDX 11 | // #define PRINT_STATS_ON_FILE 12 | // #define DUMP_SAT_QUERIES 13 | // #define DUMP_Z3_SAT_ONLY 14 | // #define DUMP_PROOFS 15 | // #define EVAL_ONLY_BRANCH 16 | // #define Z3_FALLTHROUGH 17 | #define TIMEOUT 1000 18 | 19 | fuzzy_ctx_t fctx; 20 | const char* sat_queries_filename = "fuzzy-sat-queries.smt2"; 21 | const char* sat_queries_only_z3_filename = "/tmp/sat-z3-only.smt2"; 22 | 23 | static inline unsigned long compute_time_msec(struct timeval* start, 24 | struct timeval* end) 25 | { 26 | return ((end->tv_sec - start->tv_sec) * 1000000 + end->tv_usec - 27 | start->tv_usec) / 28 | 1000; 29 | } 30 | 31 | static inline Z3_ast find_branch_condition(Z3_ast query) 32 | { 33 | if (Z3_get_ast_kind(fctx.z3_ctx, query) != Z3_APP_AST) 34 | return query; 35 | 36 | Z3_app app = Z3_to_app(fctx.z3_ctx, query); 37 | Z3_func_decl decl = Z3_get_app_decl(fctx.z3_ctx, app); 38 | Z3_decl_kind decl_kind = Z3_get_decl_kind(fctx.z3_ctx, decl); 39 | if (decl_kind != Z3_OP_AND) 40 | return query; 41 | 42 | return Z3_get_app_arg(fctx.z3_ctx, app, 0); 43 | } 44 | 45 | static inline void print_status(unsigned long current_query, 46 | unsigned long num_queries, 47 | unsigned long sat_queries_z3, 48 | unsigned long unsat_queries_z3, 49 | unsigned long unkn_queries_z3) 50 | { 51 | pp_printf(0, 1, "query %ld/%ld", current_query, num_queries); 52 | pp_printf(1, 1, "num_evaluate: %ld", fctx.stats.num_evaluate); 53 | pp_printf(2, 1, "num_sat: %ld", fctx.stats.num_sat); 54 | pp_printf(3, 1, "reuse: %ld", fctx.stats.reuse); 55 | pp_printf(4, 1, "input_to_state: %ld", fctx.stats.input_to_state); 56 | pp_printf(5, 1, "input_to_state_ext: %ld", fctx.stats.input_to_state_ext); 57 | pp_printf(6, 1, "brute_force: %ld", fctx.stats.brute_force); 58 | pp_printf(7, 1, "gradient_descend: %ld", fctx.stats.gradient_descend); 59 | pp_printf(8, 1, "flip1: %ld", fctx.stats.flip1); 60 | pp_printf(9, 1, "flip2: %ld", fctx.stats.flip2); 61 | pp_printf(10, 1, "flip4: %ld", fctx.stats.flip4); 62 | pp_printf(11, 1, "flip8: %ld", fctx.stats.flip8); 63 | pp_printf(12, 1, "flip16: %ld", fctx.stats.flip16); 64 | pp_printf(13, 1, "flip32: %ld", fctx.stats.flip32); 65 | pp_printf(14, 1, "flip64: %ld", fctx.stats.flip64); 66 | pp_printf(15, 1, "arith8_sum: %ld", fctx.stats.arith8_sum); 67 | pp_printf(16, 1, "arith8_sub: %ld", fctx.stats.arith8_sub); 68 | pp_printf(17, 1, "arith16_sum_LE: %ld", fctx.stats.arith16_sum_LE); 69 | pp_printf(18, 1, "arith16_sum_BE: %ld", fctx.stats.arith16_sum_BE); 70 | pp_printf(19, 1, "arith16_sub_LE: %ld", fctx.stats.arith16_sub_LE); 71 | pp_printf(20, 1, "arith16_sub_BE: %ld", fctx.stats.arith16_sub_BE); 72 | pp_printf(21, 1, "arith32_sum_LE: %ld", fctx.stats.arith32_sum_LE); 73 | pp_printf(22, 1, "arith32_sum_BE: %ld", fctx.stats.arith32_sum_BE); 74 | pp_printf(23, 1, "arith32_sub_LE: %ld", fctx.stats.arith32_sub_LE); 75 | pp_printf(24, 1, "arith32_sub_BE: %ld", fctx.stats.arith32_sub_BE); 76 | pp_printf(25, 1, "arith64_sum_LE: %ld", fctx.stats.arith64_sum_LE); 77 | pp_printf(26, 1, "arith64_sum_BE: %ld", fctx.stats.arith64_sum_BE); 78 | pp_printf(27, 1, "arith64_sub_LE: %ld", fctx.stats.arith64_sub_LE); 79 | pp_printf(28, 1, "arith64_sub_BE: %ld", fctx.stats.arith64_sub_BE); 80 | pp_printf(29, 1, "int8: %ld", fctx.stats.int8); 81 | pp_printf(30, 1, "int16: %ld", fctx.stats.int16); 82 | pp_printf(31, 1, "int32: %ld", fctx.stats.int32); 83 | pp_printf(32, 1, "int64: %ld", fctx.stats.int64); 84 | pp_printf(33, 1, "havoc: %ld", fctx.stats.havoc); 85 | pp_printf(34, 1, "ast_info_cache_hits: %ld", 86 | fctx.stats.ast_info_cache_hits); 87 | #ifdef Z3_FALLTHROUGH 88 | pp_printf(35, 1, "sat z3: %ld", sat_queries_z3); 89 | pp_printf(36, 1, "unsat z3: %ld", unsat_queries_z3); 90 | pp_printf(37, 1, "unkn z3: %ld", unkn_queries_z3); 91 | #endif 92 | pp_set_col(0); 93 | pp_set_line(38); 94 | } 95 | 96 | static inline void 97 | print_stats_on_file(const char* query_name, unsigned long num_queries, 98 | unsigned long num_sat_fast, unsigned long num_sat_z3, 99 | unsigned long num_unsat, unsigned long num_unkn, 100 | double elapsed_time, double elapsed_time_fast_sat, 101 | double elapsed_time_slow_sat, double elapsed_time_unsat, 102 | double elapsed_time_unkn) 103 | { 104 | FILE* logfile = fopen("/tmp/z3fuzzy-log.csv", "w"); 105 | fprintf(logfile, "%s;%ld;%ld;flip data;\n", query_name, num_queries, 106 | fctx.stats.num_sat); 107 | fprintf(logfile, ";;;reuse;%ld\n", fctx.stats.reuse); 108 | fprintf(logfile, ";;;input_to_state;%ld\n", fctx.stats.input_to_state); 109 | fprintf(logfile, ";;;input_to_state_ext;%ld\n", 110 | fctx.stats.input_to_state_ext); 111 | fprintf(logfile, ";;;brute_force;%ld\n", fctx.stats.brute_force); 112 | fprintf(logfile, ";;;gradient_descend;%ld\n", fctx.stats.gradient_descend); 113 | fprintf(logfile, ";;;flip1;%ld\n", fctx.stats.flip1); 114 | fprintf(logfile, ";;;flip2;%ld\n", fctx.stats.flip2); 115 | fprintf(logfile, ";;;flip4;%ld\n", fctx.stats.flip4); 116 | fprintf(logfile, ";;;flip16;%ld\n", fctx.stats.flip16); 117 | fprintf(logfile, ";;;flip32;%ld\n", fctx.stats.flip32); 118 | fprintf(logfile, ";;;flip64;%ld\n", fctx.stats.flip64); 119 | fprintf(logfile, ";;;arith8_sum;%ld\n", fctx.stats.arith8_sum); 120 | fprintf(logfile, ";;;arith8_sub;%ld\n", fctx.stats.arith8_sub); 121 | fprintf(logfile, ";;;arith16_sum_LE;%ld\n", fctx.stats.arith16_sum_LE); 122 | fprintf(logfile, ";;;arith16_sum_BE;%ld\n", fctx.stats.arith16_sum_BE); 123 | fprintf(logfile, ";;;arith16_sub_LE;%ld\n", fctx.stats.arith16_sub_LE); 124 | fprintf(logfile, ";;;arith16_sub_BE;%ld\n", fctx.stats.arith16_sub_BE); 125 | fprintf(logfile, ";;;arith32_sum_LE;%ld\n", fctx.stats.arith32_sum_LE); 126 | fprintf(logfile, ";;;arith32_sum_BE;%ld\n", fctx.stats.arith32_sum_BE); 127 | fprintf(logfile, ";;;arith32_sub_LE;%ld\n", fctx.stats.arith32_sub_LE); 128 | fprintf(logfile, ";;;arith32_sub_BE;%ld\n", fctx.stats.arith32_sub_BE); 129 | fprintf(logfile, ";;;arith64_sum_LE;%ld\n", fctx.stats.arith64_sum_LE); 130 | fprintf(logfile, ";;;arith64_sum_BE;%ld\n", fctx.stats.arith64_sum_BE); 131 | fprintf(logfile, ";;;arith64_sub_LE;%ld\n", fctx.stats.arith64_sub_LE); 132 | fprintf(logfile, ";;;arith64_sub_BE;%ld\n", fctx.stats.arith64_sub_BE); 133 | fprintf(logfile, ";;;int8;%ld\n", fctx.stats.int8); 134 | fprintf(logfile, ";;;int16;%ld\n", fctx.stats.int16); 135 | fprintf(logfile, ";;;int32;%ld\n", fctx.stats.int32); 136 | fprintf(logfile, ";;;int64;%ld\n", fctx.stats.int64); 137 | fprintf(logfile, ";;;havoc;%ld\n", fctx.stats.havoc); 138 | fprintf(logfile, ";;;other data;\n"); 139 | fprintf(logfile, ";;;elapsed time;%.3lf\n", elapsed_time); 140 | fprintf(logfile, ";;;elapsed time fast sat;%.3lf\n", elapsed_time_fast_sat); 141 | #ifdef Z3_FALLTHROUGH 142 | fprintf(logfile, ";;;num sat fuzzy;%ld\n", num_sat_fast); 143 | fprintf(logfile, ";;;num sat z3;%ld\n", num_sat_z3); 144 | fprintf(logfile, ";;;elapsed time sat;%.3lf\n", 145 | elapsed_time_slow_sat + elapsed_time_fast_sat); 146 | fprintf(logfile, ";;;num unsat;%ld\n", num_unsat); 147 | fprintf(logfile, ";;;elapsed time unsat;%.3lf\n", elapsed_time_unsat); 148 | fprintf(logfile, ";;;num unknown;%ld\n", num_unkn); 149 | fprintf(logfile, ";;;elapsed time unknown;%.3lf\n", elapsed_time_unkn); 150 | #endif 151 | fprintf(logfile, ";;;num evaluate;%ld\n", fctx.stats.num_evaluate); 152 | 153 | fclose(logfile); 154 | } 155 | 156 | static inline void usage(char* filename) 157 | { 158 | fprintf(stderr, "wrong argv. usage:\n%s query_filename seed [test_dir]\n", 159 | filename); 160 | exit(1); 161 | } 162 | 163 | int main(int argc, char* argv[]) 164 | { 165 | if (argc < 3) 166 | usage(argv[0]); 167 | 168 | char* query_filename = argv[1]; 169 | char* seed_filename = argv[2]; 170 | char* tests_dir = argc > 3 ? argv[3] : NULL; 171 | Z3_config cfg = Z3_mk_config(); 172 | Z3_set_param_value(cfg, "timeout", SOLVER_TIMEOUT); 173 | Z3_context ctx = Z3_mk_context(cfg); 174 | unsigned char const* proof; 175 | unsigned long proof_size; 176 | __attribute__((unused)) unsigned long num_queries = 0, sat_queries = 0, 177 | sat_queries_z3 = 0, 178 | unsat_queries_z3 = 0, 179 | unkn_queries_z3 = 0; 180 | Z3_ast* str_symbols; 181 | char var_name[128]; 182 | Z3_sort bsort = Z3_mk_bv_sort(ctx, 8); 183 | struct timeval stop, start; 184 | __attribute__((unused)) unsigned long elapsed_time = 0, 185 | elapsed_time_fast_sat = 0, 186 | elapsed_time_slow_sat = 0, 187 | elapsed_time_unsat = 0, 188 | elapsed_time_unknown = 0; 189 | unsigned int i; 190 | int n; 191 | 192 | #ifdef DUMP_Z3_SAT_ONLY 193 | FILE* sat_queries_z3_file = fopen(sat_queries_only_z3_filename, "w"); 194 | #endif 195 | #ifdef DUMP_SAT_QUERIES 196 | FILE* sat_queries_file = fopen(sat_queries_filename, "w"); 197 | setvbuf(sat_queries_file, NULL, _IONBF, 0); 198 | #endif 199 | z3fuzz_init(&fctx, ctx, seed_filename, tests_dir, NULL, TIMEOUT); 200 | 201 | #ifdef PRINT_STATUS 202 | pp_init(); 203 | #endif 204 | 205 | str_symbols = (Z3_ast*)malloc(sizeof(Z3_ast) * fctx.n_symbols); 206 | for (i = 0; i < fctx.n_symbols; ++i) { 207 | n = snprintf(var_name, sizeof(var_name), "k!%u", i); 208 | assert(n > 0 && n < sizeof(var_name) && "symbol name too long"); 209 | Z3_symbol s = Z3_mk_string_symbol(ctx, var_name); 210 | Z3_ast s_bv = Z3_mk_const(ctx, s, bsort); 211 | str_symbols[i] = s_bv; 212 | } 213 | 214 | Z3_ast_vector queries = 215 | Z3_parse_smtlib2_file(ctx, query_filename, 0, 0, 0, 0, 0, 0); 216 | Z3_ast_vector_inc_ref(ctx, queries); 217 | 218 | #ifdef PRINT_SAT_IDX 219 | FILE* log_idx_sat = fopen("/tmp/idx_sat.csv", "w"); 220 | #endif 221 | 222 | num_queries = Z3_ast_vector_size(ctx, queries); 223 | for (i = 0; i < num_queries; ++i) { 224 | Z3_ast query = Z3_ast_vector_get(ctx, queries, i); 225 | query = Z3_substitute(ctx, query, fctx.n_symbols, str_symbols, 226 | fctx.symbols); 227 | __attribute__((unused)) Z3_ast branch_condition = 228 | find_branch_condition(query); 229 | 230 | #ifdef EVAL_ONLY_BRANCH 231 | query = branch_condition; 232 | #endif 233 | gettimeofday(&start, NULL); 234 | if (z3fuzz_query_check_light(&fctx, query, find_branch_condition(query), 235 | &proof, &proof_size)) { 236 | sat_queries += 1; 237 | gettimeofday(&stop, NULL); 238 | elapsed_time_fast_sat += compute_time_msec(&start, &stop); 239 | 240 | #ifdef PRINT_SAT_IDX 241 | fprintf(log_idx_sat, "%u ; SAT\n", i); 242 | #endif 243 | #ifdef DUMP_SAT_QUERIES 244 | fprintf(sat_queries_file, "(assert\n%s\n)\n", 245 | Z3_ast_to_string(ctx, query)); 246 | #endif 247 | #ifdef DUMP_PROOFS 248 | n = snprintf(var_name, sizeof(var_name), "tests/test_%02u", i); 249 | assert(n > 0 && n < sizeof(var_name) && "test case name too long"); 250 | z3fuzz_dump_proof(&fctx, var_name, proof, proof_size); 251 | #endif 252 | } else { 253 | unsat_queries_z3++; 254 | gettimeofday(&stop, NULL); 255 | elapsed_time_unsat += compute_time_msec(&start, &stop); 256 | #ifdef PRINT_SAT_IDX 257 | fprintf(log_idx_sat, "%u ; UNSAT\n", i); 258 | #endif 259 | #ifdef Z3_FALLTHROUGH 260 | Z3_solver solver = Z3_mk_solver(ctx); 261 | Z3_solver_inc_ref(ctx, solver); 262 | 263 | #ifdef EVAL_ONLY_BRANCH 264 | Z3_solver_assert(ctx, solver, find_branch_condition(ctx, query)); 265 | #else 266 | Z3_solver_assert(ctx, solver, query); 267 | #endif 268 | Z3_lbool query_result; 269 | switch ((query_result = Z3_solver_check(ctx, solver))) { 270 | case Z3_L_FALSE: 271 | // printf("Query is UNSAT\n"); 272 | unsat_queries_z3 += 1; 273 | gettimeofday(&stop, NULL); 274 | elapsed_time_unsat += compute_time_msec(&start, &stop); 275 | break; 276 | case Z3_L_UNDEF: 277 | /* Z3 failed to prove/disprove f. */ 278 | unkn_queries_z3 += 1; 279 | gettimeofday(&stop, NULL); 280 | elapsed_time_unknown += compute_time_msec(&start, &stop); 281 | break; 282 | case Z3_L_TRUE: 283 | // printf("Query is SAT\n"); 284 | sat_queries_z3 += 1; 285 | gettimeofday(&stop, NULL); 286 | elapsed_time_slow_sat += compute_time_msec(&start, &stop); 287 | #ifdef DUMP_Z3_SAT_ONLY 288 | fprintf(sat_queries_z3_file, "(assert\n%s\n)\n", 289 | Z3_ast_to_string(ctx, query)); 290 | #endif 291 | break; 292 | } 293 | 294 | if (query_result == Z3_L_TRUE) { 295 | #ifdef DUMP_SAT_QUERIES 296 | fprintf(sat_queries_file, "(assert\n%s\n)\n", 297 | Z3_ast_to_string(ctx, query)); 298 | #endif 299 | #ifdef DUMP_PROOFS 300 | n = snprintf(var_name, sizeof(var_name), "tests/test_%02u", i); 301 | assert(n > 0 && n < sizeof(var_name) && 302 | "test case name too long"); 303 | 304 | Z3_model m = Z3_solver_get_model(ctx, solver); 305 | Z3_model_inc_ref(ctx, m); 306 | dump_proof(ctx, m, var_name); 307 | Z3_model_dec_ref(ctx, m); 308 | #endif 309 | } 310 | 311 | Z3_solver_dec_ref(ctx, solver); 312 | } 313 | #else 314 | } 315 | gettimeofday(&stop, NULL); 316 | #endif 317 | 318 | elapsed_time += compute_time_msec(&start, &stop); 319 | 320 | #ifdef PRINT_STATUS 321 | print_status(i, num_queries, sat_queries_z3, unsat_queries_z3, 322 | unkn_queries_z3); 323 | #endif 324 | } 325 | 326 | #ifdef PRINT_STATS_ON_FILE 327 | print_stats_on_file( 328 | query_filename, num_queries, sat_queries, sat_queries_z3, 329 | unsat_queries_z3, unkn_queries_z3, (double)elapsed_time / 1000, 330 | (double)elapsed_time_fast_sat / 1000, 331 | (double)elapsed_time_slow_sat / 1000, (double)elapsed_time_unsat / 1000, 332 | (double)elapsed_time_unknown / 1000); 333 | #endif 334 | #ifdef PRINT_SAT_IDX 335 | fclose(log_idx_sat); 336 | #endif 337 | printf("\n" 338 | "num queries:\t%lu\n" 339 | "fast sat queries:\t%lu\n" 340 | "elaps time:\t%.3lf s\n" 341 | "elaps time sat:\t%.3lf s\n", 342 | num_queries, sat_queries, (double)elapsed_time / 1000, 343 | (double)elapsed_time_fast_sat / 1000); 344 | #ifdef Z3_FALLTHROUGH 345 | printf("slow z3 sat:\t%lu\n" 346 | "slow z3 unsat:\t%lu\n" 347 | "slow z3 unkn:\t%lu\n" 348 | "elaps time sat:\t%.3lf s\n" 349 | "elaps time unsat:\t%.3lf s\n" 350 | "elaps time unkn:\t%.3lf s\n", 351 | sat_queries_z3, unsat_queries_z3, unkn_queries_z3, 352 | (double)elapsed_time_slow_sat / 1000, 353 | (double)elapsed_time_unsat / 1000, 354 | (double)elapsed_time_unknown / 1000); 355 | #endif 356 | 357 | printf("elaps time unsat:\t%.3lf s\n" 358 | "num unsat:\t%lu\n", 359 | (double)elapsed_time_unsat / 1000, unsat_queries_z3); 360 | 361 | Z3_ast_vector_dec_ref(ctx, queries); 362 | free(str_symbols); 363 | z3fuzz_free(&fctx); 364 | Z3_del_config(cfg); 365 | #ifdef DUMP_SAT_QUERIES 366 | fclose(sat_queries_file); 367 | #endif 368 | #ifdef DUMP_Z3_SAT_ONLY 369 | fclose(sat_queries_z3_file); 370 | #endif 371 | return 0; 372 | } 373 | -------------------------------------------------------------------------------- /tools/interval_test.c: -------------------------------------------------------------------------------- 1 | #include "wrapped_interval.h" 2 | #include 3 | 4 | int main() 5 | { 6 | wrapped_interval_t wi1 = wi_init(8); 7 | wi_update_add(&wi1, 10); 8 | wi_print(&wi1); 9 | 10 | printf("contains %d ? %d\n", 9, wi_contains_element(&wi1, 9)); 11 | printf("contains %d ? %d\n", 10, wi_contains_element(&wi1, 10)); 12 | printf("contains %d ? %d\n", 255, wi_contains_element(&wi1, 255)); 13 | 14 | wi_update_cmp(&wi1, -4, OP_SGT); 15 | wi_print(&wi1); 16 | 17 | wi_update_sub(&wi1, 13); 18 | wi_print(&wi1); 19 | 20 | wi_update_add(&wi1, 30); 21 | wi_print(&wi1); 22 | 23 | wrapped_interval_t wi2 = wi_init(8); 24 | wi_update_cmp(&wi2, 0xb0, OP_UGT); 25 | wi_update_sub(&wi2, 0x0a); 26 | wi_print(&wi2); 27 | 28 | wrapped_interval_t wi3 = wi_init(32); 29 | wi_update_cmp(&wi3, 0xbbbbbbbb, OP_ULT); 30 | wi_update_sub(&wi3, 0xaaaaaaaa); 31 | wi_print(&wi3); 32 | } -------------------------------------------------------------------------------- /tools/maxmin-driver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "z3-fuzzy.h" 5 | 6 | #define NUM_ITERATIONS 1000 7 | #define TIMEOUT 1000 8 | 9 | fuzzy_ctx_t fctx; 10 | 11 | static inline unsigned long compute_time_usec(struct timeval* start, 12 | struct timeval* end) 13 | { 14 | return ((end->tv_sec - start->tv_sec) * 1000000 + end->tv_usec - 15 | start->tv_usec); 16 | } 17 | 18 | static inline void usage(char* filename) 19 | { 20 | fprintf(stderr, "wrong argv. usage:\n%s pi_filename bv_filename seed\n", 21 | filename); 22 | exit(1); 23 | } 24 | 25 | static inline void dump_proof(Z3_context ctx, Z3_model m, 26 | char const* test_case_name) 27 | { 28 | FILE* fp; 29 | unsigned long num_symbols, i; 30 | Z3_sort bsort = Z3_mk_bv_sort(ctx, 8); 31 | 32 | fp = fopen(test_case_name, "w"); 33 | num_symbols = Z3_model_get_num_consts(ctx, m); 34 | for (i = 0; i < num_symbols; ++i) { 35 | Z3_symbol s = Z3_mk_int_symbol(ctx, i); 36 | Z3_ast s_bv = Z3_mk_const(ctx, s, bsort); 37 | 38 | Z3_ast solution; 39 | Z3_bool successfulEval = 40 | Z3_model_eval(ctx, m, s_bv, 41 | /*model_completion=*/Z3_TRUE, &solution); 42 | assert(successfulEval && "Failed to evaluate model"); 43 | 44 | int solution_byte = 0; 45 | Z3_bool successGet = Z3_get_numeral_int(ctx, solution, &solution_byte); 46 | assert (successGet == Z3_TRUE); 47 | fwrite(&solution_byte, sizeof(char), 1, fp); 48 | } 49 | fclose(fp); 50 | } 51 | 52 | int main(int argc, char* argv[]) 53 | { 54 | if (argc < 3) 55 | usage(argv[0]); 56 | 57 | char* pi_filename = argv[1]; 58 | char* bv_filename = argv[2]; 59 | char* seed_filename = argv[3]; 60 | Z3_config cfg = Z3_mk_config(); 61 | Z3_context ctx = Z3_mk_context(cfg); 62 | Z3_ast* str_symbols; 63 | char var_name[128]; 64 | Z3_sort bsort = Z3_mk_bv_sort(ctx, 8); 65 | struct timeval stop, start; 66 | unsigned long elapsed_time_z3 = 0, elapsed_time_fast = 0; 67 | unsigned long num_assert; 68 | unsigned int i; 69 | int n; 70 | 71 | z3fuzz_init(&fctx, ctx, seed_filename, NULL, NULL, TIMEOUT); 72 | 73 | str_symbols = (Z3_ast*)malloc(sizeof(Z3_ast) * fctx.n_symbols); 74 | for (i = 0; i < fctx.n_symbols; ++i) { 75 | n = snprintf(var_name, sizeof(var_name), "k!%u", i); 76 | assert(n > 0 && n < sizeof(var_name) && "symbol name too long"); 77 | Z3_symbol s = Z3_mk_string_symbol(ctx, var_name); 78 | Z3_ast s_bv = Z3_mk_const(ctx, s, bsort); 79 | str_symbols[i] = s_bv; 80 | } 81 | 82 | Z3_ast_vector pi_vector = 83 | Z3_parse_smtlib2_file(ctx, pi_filename, 0, 0, 0, 0, 0, 0); 84 | Z3_ast_vector_inc_ref(ctx, pi_vector); 85 | 86 | num_assert = Z3_ast_vector_size(ctx, pi_vector); 87 | assert(num_assert > 0 && "empty pi"); 88 | 89 | Z3_ast asserts[num_assert]; 90 | for (i = 0; i < num_assert; ++i) { 91 | asserts[i] = Z3_ast_vector_get(ctx, pi_vector, i); 92 | } 93 | Z3_ast_vector_dec_ref(ctx, pi_vector); 94 | 95 | Z3_ast pi = Z3_mk_and(ctx, num_assert, asserts); 96 | pi = Z3_substitute(ctx, pi, fctx.n_symbols, str_symbols, fctx.symbols); 97 | puts("[+] PI loaded"); 98 | 99 | Z3_ast_vector bv_asserts = 100 | Z3_parse_smtlib2_file(ctx, bv_filename, 0, 0, 0, 0, 0, 0); 101 | assert(Z3_ast_vector_size(ctx, bv_asserts) == 1 && "bv must be unique"); 102 | 103 | // I can only parse asserts. So I assume something like (== BV whatever) 104 | Z3_ast bv_tmp = Z3_ast_vector_get(ctx, bv_asserts, 0); 105 | Z3_app bv_tmp_app = Z3_to_app(ctx, bv_tmp); 106 | Z3_ast bv = Z3_get_app_arg(ctx, bv_tmp_app, 0); 107 | bv = Z3_substitute(ctx, bv, fctx.n_symbols, str_symbols, fctx.symbols); 108 | puts("[+] BV loaded\n"); 109 | 110 | gettimeofday(&start, NULL); 111 | unsigned char const* inputs; 112 | unsigned long n_inputs; 113 | unsigned long max_val = z3fuzz_maximize(&fctx, pi, bv, &inputs, &n_inputs); 114 | z3fuzz_dump_proof(&fctx, "tests/max_val.bin", inputs, n_inputs); 115 | 116 | unsigned long min_val = z3fuzz_minimize(&fctx, pi, bv, &inputs, &n_inputs); 117 | z3fuzz_dump_proof(&fctx, "tests/min_val.bin", inputs, n_inputs); 118 | gettimeofday(&stop, NULL); 119 | elapsed_time_fast = compute_time_usec(&start, &stop); 120 | 121 | gettimeofday(&start, NULL); 122 | Z3_optimize opt; 123 | Z3_model m; 124 | unsigned long max_val_z3 = 0; 125 | opt = Z3_mk_optimize(ctx); 126 | Z3_optimize_inc_ref(ctx, opt); 127 | Z3_optimize_assert(ctx, opt, pi); 128 | Z3_optimize_maximize(ctx, opt, bv); 129 | 130 | switch (Z3_optimize_check(ctx, opt, 0, NULL)) { 131 | case Z3_L_FALSE: 132 | printf("max false! \n"); 133 | break; 134 | case Z3_L_UNDEF: 135 | printf("max unknown! \n"); 136 | break; 137 | case Z3_L_TRUE: 138 | m = Z3_optimize_get_model(ctx, opt); 139 | Z3_model_inc_ref(ctx, m); 140 | dump_proof(ctx, m, "tests/max_val_z3.bin"); 141 | 142 | Z3_ast solution; 143 | Z3_bool successfulEval = 144 | Z3_model_eval(ctx, m, bv, 145 | /*model_completion=*/Z3_TRUE, &solution); 146 | assert(successfulEval && "Failed to evaluate model"); 147 | 148 | Z3_bool successGet = Z3_get_numeral_uint64(ctx, solution, &max_val_z3); 149 | assert(successGet && "Failed to get numeral int"); 150 | 151 | Z3_model_dec_ref(ctx, m); 152 | break; 153 | } 154 | Z3_optimize_dec_ref(ctx, opt); 155 | 156 | unsigned long min_val_z3 = 0; 157 | opt = Z3_mk_optimize(ctx); 158 | Z3_optimize_inc_ref(ctx, opt); 159 | Z3_optimize_assert(ctx, opt, pi); 160 | Z3_optimize_minimize(ctx, opt, bv); 161 | 162 | switch (Z3_optimize_check(ctx, opt, 0, NULL)) { 163 | case Z3_L_FALSE: 164 | printf("max false! \n"); 165 | break; 166 | case Z3_L_UNDEF: 167 | printf("max unknown! \n"); 168 | break; 169 | case Z3_L_TRUE: 170 | m = Z3_optimize_get_model(ctx, opt); 171 | Z3_model_inc_ref(ctx, m); 172 | dump_proof(ctx, m, "tests/min_val_z3.bin"); 173 | 174 | Z3_ast solution; 175 | Z3_bool successfulEval = 176 | Z3_model_eval(ctx, m, bv, 177 | /*model_completion=*/Z3_TRUE, &solution); 178 | assert(successfulEval && "Failed to evaluate model"); 179 | 180 | Z3_bool successGet = Z3_get_numeral_uint64(ctx, solution, &min_val_z3); 181 | assert(successGet && "Failed to get numeral int"); 182 | Z3_model_dec_ref(ctx, m); 183 | break; 184 | } 185 | Z3_optimize_dec_ref(ctx, opt); 186 | gettimeofday(&stop, NULL); 187 | elapsed_time_z3 = compute_time_usec(&start, &stop); 188 | 189 | printf("z3fuzz max_val:\t0x%lx\n", max_val); 190 | printf("z3fuzz min_val:\t0x%lx\n", min_val); 191 | printf("z3fuzz time:\t%ld usec\n", elapsed_time_fast); 192 | putchar('\n'); 193 | printf("z3 max_val:\t0x%lx\n", max_val_z3); 194 | printf("z3 min_val:\t0x%lx\n", min_val_z3); 195 | printf("z3 time:\t%ld usec\n", elapsed_time_z3); 196 | 197 | z3fuzz_free(&fctx); 198 | 199 | return 0; 200 | } 201 | -------------------------------------------------------------------------------- /tools/pretty-print.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "pretty-print.h" 6 | 7 | #define UP(n) printf("\x1b[%dA", n) 8 | #define DOWN(n) printf("\x1b[%dB", n) 9 | #define RIGHT(n) printf("\x1b[%dC", n) 10 | #define LEFT(n) printf("\x1b[%dD", n) 11 | 12 | static int row_idx = 0; 13 | static int num_rows = 0; 14 | static int col_idx = 0; 15 | static int num_cols = 0; 16 | 17 | static inline void __clear_line() { 18 | int i; 19 | for (i = 0; i < num_cols - col_idx - 1; ++i) 20 | putchar(' '); 21 | 22 | LEFT(num_cols - col_idx); 23 | } 24 | 25 | static inline void __reset_cursor() { 26 | LEFT(col_idx); 27 | UP(row_idx); 28 | 29 | col_idx = 0; 30 | row_idx = 0; 31 | } 32 | 33 | static int __dim_changed() { 34 | struct winsize w; 35 | ioctl(0, TIOCGWINSZ, &w); 36 | 37 | return w.ws_row -1 != num_rows || \ 38 | w.ws_col - 1 != num_cols; 39 | } 40 | 41 | void pp_init() { 42 | setvbuf(stdin, NULL, _IONBF, 0); 43 | setvbuf(stdout, NULL, _IONBF, 0); 44 | 45 | struct winsize w; 46 | ioctl(0, TIOCGWINSZ, &w); 47 | 48 | num_rows = w.ws_row - 1; 49 | num_cols = w.ws_col - 1; 50 | 51 | int i; 52 | for (i = 0; i < num_rows; ++i) 53 | putchar('\n'); 54 | 55 | row_idx = num_rows; 56 | col_idx = 0; 57 | __reset_cursor(); 58 | } 59 | 60 | void pp_set_line(int i) { 61 | if (row_idx - i > 0) 62 | UP(row_idx - i); 63 | else if (row_idx - i < 0) 64 | DOWN(i - row_idx); 65 | 66 | row_idx = i; 67 | } 68 | 69 | void pp_set_col(int i) { 70 | if (col_idx - i > 0) 71 | LEFT(col_idx - i); 72 | else if (col_idx - i < 0) 73 | RIGHT(i - col_idx); 74 | 75 | col_idx = i; 76 | } 77 | 78 | void pp_print_string(int row, int col, const char* s) { 79 | if (__dim_changed()) 80 | pp_init(); 81 | 82 | pp_set_line(row); 83 | pp_set_col(col); 84 | __clear_line(); 85 | 86 | int j; 87 | for (j = 0; j < num_cols - col && s[j] != 0; ++j) 88 | if (s[j] != '\n') { 89 | putchar(s[j]); 90 | col_idx += 1; 91 | } else { 92 | assert (0 && "no newline allowed"); 93 | } 94 | 95 | __reset_cursor(); 96 | } 97 | 98 | void pp_printf(int row, int col, const char *format, ...) { 99 | va_list args; 100 | va_start(args, format); 101 | 102 | char var_name[512]; 103 | int n = vsnprintf(var_name, sizeof(var_name), format, args); 104 | assert(n > 0 && n < sizeof(var_name) && 105 | "pp_printf() - var name too long"); 106 | 107 | pp_print_string(row, col, var_name); 108 | va_end(args); 109 | } 110 | 111 | int pp_get_cols() { 112 | return num_cols; 113 | } 114 | 115 | int pp_get_rows() { 116 | return num_rows; 117 | } 118 | -------------------------------------------------------------------------------- /tools/pretty-print.h: -------------------------------------------------------------------------------- 1 | #ifndef PRETTY_PRINT_H 2 | #define PRETTY_PRINT_H 3 | 4 | void pp_init(); 5 | void pp_set_line(int i); 6 | void pp_set_col(int i); 7 | void pp_print_string(int row, int col, const char* s); 8 | void pp_printf(int row, int col, const char *format, ...); 9 | 10 | int pp_get_cols(); 11 | int pp_get_rows(); 12 | 13 | #endif -------------------------------------------------------------------------------- /tools/stats-collection-fuzzy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "pretty-print.h" 6 | #include "z3-fuzzy.h" 7 | 8 | #define LOG_ON_FILE 9 | #define FUZZY_SOLVER_TIMEOUT 1000 10 | 11 | fuzzy_ctx_t fctx; 12 | const char* log_filename = "fuzzy_queries.csv"; 13 | FILE* log_file; 14 | const char* flip_info_filename = "fuzzy_flip_info.csv"; 15 | FILE* flip_info_file; 16 | 17 | static inline double compute_time_msec(struct timeval* start, 18 | struct timeval* end) 19 | { 20 | return ((end->tv_sec - start->tv_sec) * 1000000 + end->tv_usec - 21 | start->tv_usec) / 22 | 1000.0L; 23 | } 24 | 25 | static inline Z3_ast find_branch_condition(Z3_ast query) 26 | { 27 | if (Z3_get_ast_kind(fctx.z3_ctx, query) != Z3_APP_AST) 28 | return query; 29 | 30 | Z3_app app = Z3_to_app(fctx.z3_ctx, query); 31 | Z3_func_decl decl = Z3_get_app_decl(fctx.z3_ctx, app); 32 | Z3_decl_kind decl_kind = Z3_get_decl_kind(fctx.z3_ctx, decl); 33 | if (decl_kind != Z3_OP_AND) 34 | return query; 35 | 36 | return Z3_get_app_arg(fctx.z3_ctx, app, 0); 37 | } 38 | 39 | static inline void divide_query_in_assertions(Z3_ast query, Z3_ast** assertions, 40 | unsigned* n) 41 | { 42 | if (Z3_get_ast_kind(fctx.z3_ctx, query) != Z3_APP_AST) { 43 | *assertions = NULL; 44 | *n = 0; 45 | return; 46 | } 47 | 48 | Z3_app app = Z3_to_app(fctx.z3_ctx, query); 49 | Z3_func_decl decl = Z3_get_app_decl(fctx.z3_ctx, app); 50 | Z3_decl_kind decl_kind = Z3_get_decl_kind(fctx.z3_ctx, decl); 51 | if (decl_kind != Z3_OP_AND || Z3_get_app_num_args(fctx.z3_ctx, app) == 0) { 52 | *assertions = NULL; 53 | *n = 0; 54 | return; 55 | } 56 | 57 | *n = Z3_get_app_num_args(fctx.z3_ctx, app) - 1; 58 | *assertions = (Z3_ast*)malloc(sizeof(Z3_ast) * *n); 59 | 60 | unsigned i; 61 | for (i = 1; i < *n + 1; ++i) { 62 | Z3_ast v = Z3_get_app_arg(fctx.z3_ctx, app, i); 63 | (*assertions)[i - 1] = v; 64 | } 65 | } 66 | 67 | static inline void dump_flip_info() 68 | { 69 | fprintf(flip_info_file, 70 | "%ld," // input to state 71 | "%ld," // extended input to state 72 | "%ld," // interval analysis (brute force + range brute force + range 73 | // brute force opt + simple math) 74 | "%ld," // gradient descent 75 | "%ld," // flips 76 | "%ld," // arithms 77 | "%ld," // interesting 78 | "%ld," // havoc 79 | "%ld," // multigoal 80 | "%ld" // sat in seed 81 | , 82 | fctx.stats.input_to_state, fctx.stats.input_to_state_ext, 83 | fctx.stats.brute_force + fctx.stats.range_brute_force + 84 | fctx.stats.range_brute_force_opt + fctx.stats.simple_math, 85 | fctx.stats.gradient_descend, 86 | fctx.stats.flip1 + fctx.stats.flip2 + fctx.stats.flip4 + 87 | fctx.stats.flip8 + fctx.stats.flip16 + fctx.stats.flip32 + 88 | fctx.stats.flip64, 89 | fctx.stats.arith8_sum + fctx.stats.arith8_sub + 90 | fctx.stats.arith16_sum_LE + fctx.stats.arith16_sum_BE + 91 | fctx.stats.arith16_sub_LE + fctx.stats.arith16_sub_BE + 92 | fctx.stats.arith32_sum_LE + fctx.stats.arith32_sum_BE + 93 | fctx.stats.arith32_sub_LE + fctx.stats.arith32_sub_BE + 94 | fctx.stats.arith64_sum_LE + fctx.stats.arith64_sum_BE + 95 | fctx.stats.arith64_sub_LE + fctx.stats.arith64_sub_BE, 96 | fctx.stats.int8 + fctx.stats.int16 + fctx.stats.int32 + 97 | fctx.stats.int64, 98 | fctx.stats.havoc, fctx.stats.multigoal, fctx.stats.sat_in_seed); 99 | } 100 | 101 | static inline void usage(char* filename) 102 | { 103 | fprintf(stderr, "wrong argv. usage:\n%s query_filename seed [test_dir]\n", 104 | filename); 105 | exit(1); 106 | } 107 | 108 | int main(int argc, char* argv[]) 109 | { 110 | if (argc < 3) 111 | usage(argv[0]); 112 | 113 | char* query_filename = argv[1]; 114 | char* seed_filename = argv[2]; 115 | char* tests_dir = argc > 3 ? argv[3] : NULL; 116 | Z3_config cfg = Z3_mk_config(); 117 | Z3_context ctx = Z3_mk_context(cfg); 118 | unsigned char const* proof; 119 | unsigned long proof_size; 120 | unsigned long num_queries = 0, fuzzy_sat = 0; 121 | char var_name[128]; 122 | Z3_sort bsort = Z3_mk_bv_sort(ctx, 8); 123 | struct timeval stop, start; 124 | double elapsed_time = 0, cumulative_fuzzy = 0; 125 | unsigned int i; 126 | int n; 127 | 128 | #ifdef LOG_ON_FILE 129 | log_file = fopen(log_filename, "w"); 130 | setvbuf(log_file, NULL, _IONBF, 0); 131 | flip_info_file = fopen(flip_info_filename, "w"); 132 | setvbuf(flip_info_file, NULL, _IONBF, 0); 133 | #endif 134 | 135 | z3fuzz_init(&fctx, ctx, seed_filename, tests_dir, NULL, 136 | FUZZY_SOLVER_TIMEOUT); 137 | 138 | pp_init(); 139 | 140 | Z3_ast* str_symbols = (Z3_ast*)malloc(sizeof(Z3_ast) * fctx.n_symbols); 141 | for (i = 0; i < fctx.n_symbols; ++i) { 142 | n = snprintf(var_name, sizeof(var_name), "k!%u", i); 143 | assert(n > 0 && n < sizeof(var_name) && "symbol name too long"); 144 | Z3_symbol s = Z3_mk_string_symbol(ctx, var_name); 145 | Z3_ast s_bv = Z3_mk_const(ctx, s, bsort); 146 | str_symbols[i] = s_bv; 147 | } 148 | 149 | Z3_ast_vector queries = 150 | Z3_parse_smtlib2_file(ctx, query_filename, 0, 0, 0, 0, 0, 0); 151 | Z3_ast_vector_inc_ref(ctx, queries); 152 | 153 | #ifdef LOG_ON_FILE 154 | fprintf(log_file, "time fuzzy,fuzzy res,time z3,z3 res\n"); 155 | #endif 156 | 157 | num_queries = Z3_ast_vector_size(ctx, queries); 158 | for (i = 0; i < num_queries; ++i) { 159 | pp_printf(0, 1, "query %ld/%ld", i + 1, num_queries); 160 | 161 | Z3_ast query = Z3_ast_vector_get(ctx, queries, i); 162 | query = Z3_substitute(ctx, query, fctx.n_symbols, str_symbols, 163 | fctx.symbols); 164 | Z3_ast branch_condition = find_branch_condition(query); 165 | Z3_ast* assertions; 166 | unsigned n_assertions; 167 | divide_query_in_assertions(query, &assertions, &n_assertions); 168 | 169 | int is_sat_fuzzy = 0; 170 | gettimeofday(&start, NULL); 171 | int j; 172 | for (j = 0; j < n_assertions; ++j) { 173 | assert(assertions[j] != NULL && "null assertion!"); 174 | z3fuzz_notify_constraint(&fctx, assertions[j]); 175 | } 176 | 177 | if (z3fuzz_query_check_light(&fctx, query, branch_condition, &proof, 178 | &proof_size)) 179 | is_sat_fuzzy = 1; 180 | 181 | gettimeofday(&stop, NULL); 182 | elapsed_time = compute_time_msec(&start, &stop); 183 | cumulative_fuzzy += elapsed_time; 184 | fuzzy_sat += is_sat_fuzzy; 185 | 186 | #ifdef LOG_ON_FILE 187 | fprintf(log_file, "%.3lf,%s\n", elapsed_time, 188 | is_sat_fuzzy ? "sat" : "unknown"); 189 | #endif 190 | 191 | free(assertions); 192 | 193 | pp_printf(2, 1, "cumulative fuzzy %.03lf msec", cumulative_fuzzy); 194 | pp_printf(3, 1, "sat fuzzy %ld", fuzzy_sat); 195 | } 196 | 197 | #ifdef LOG_ON_FILE 198 | dump_flip_info(); 199 | #endif 200 | 201 | pp_printf(2, 1, "cumulative fuzzy %.03lf msec", cumulative_fuzzy); 202 | pp_printf(3, 1, "sat fuzzy %ld", fuzzy_sat); 203 | pp_set_line(5); 204 | puts(""); 205 | 206 | Z3_ast_vector_dec_ref(ctx, queries); 207 | free(str_symbols); 208 | z3fuzz_free(&fctx); 209 | Z3_del_config(cfg); 210 | Z3_del_context(ctx); 211 | fclose(log_file); 212 | fclose(flip_info_file); 213 | return 0; 214 | } 215 | -------------------------------------------------------------------------------- /tools/stats-collection-z3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "pretty-print.h" 6 | #include "z3-fuzzy.h" 7 | 8 | #define LOG_ON_FILE 9 | #define Z3_SOLVER_TIMEOUT "10000" 10 | 11 | const char* log_filename = "z3_queries.csv"; 12 | FILE* log_file; 13 | 14 | static inline double compute_time_msec(struct timeval* start, 15 | struct timeval* end) 16 | { 17 | return ((end->tv_sec - start->tv_sec) * 1000000 + end->tv_usec - 18 | start->tv_usec) / 19 | 1000.0L; 20 | } 21 | 22 | static inline void usage(char* filename) 23 | { 24 | fprintf(stderr, "wrong argv. usage:\n%s query_filename\n", filename); 25 | exit(1); 26 | } 27 | 28 | int main(int argc, char* argv[]) 29 | { 30 | if (argc < 2) 31 | usage(argv[0]); 32 | 33 | char* query_filename = argv[1]; 34 | Z3_config cfg = Z3_mk_config(); 35 | Z3_set_param_value(cfg, "timeout", Z3_SOLVER_TIMEOUT); 36 | Z3_context ctx = Z3_mk_context(cfg); 37 | unsigned long num_queries = 0, z3_sat = 0; 38 | struct timeval stop, start; 39 | double elapsed_time, cumulative_z3 = 0; 40 | unsigned int i; 41 | 42 | #ifdef LOG_ON_FILE 43 | log_file = fopen(log_filename, "w"); 44 | setvbuf(log_file, NULL, _IONBF, 0); 45 | #endif 46 | 47 | pp_init(); 48 | 49 | Z3_ast_vector queries = 50 | Z3_parse_smtlib2_file(ctx, query_filename, 0, 0, 0, 0, 0, 0); 51 | Z3_ast_vector_inc_ref(ctx, queries); 52 | 53 | #ifdef LOG_ON_FILE 54 | fprintf(log_file, "time z3,z3 res\n"); 55 | #endif 56 | 57 | num_queries = Z3_ast_vector_size(ctx, queries); 58 | for (i = 0; i < num_queries; ++i) { 59 | pp_printf(0, 1, "query %ld/%ld", i + 1, num_queries); 60 | 61 | Z3_ast query = Z3_ast_vector_get(ctx, queries, i); 62 | 63 | int is_sat_z3 = 0; 64 | int is_unknown_z3 = 0; 65 | 66 | Z3_lbool query_result; 67 | Z3_solver solver = Z3_mk_solver(ctx); 68 | Z3_solver_inc_ref(ctx, solver); 69 | 70 | gettimeofday(&start, NULL); 71 | Z3_solver_assert(ctx, solver, query); 72 | switch ((query_result = Z3_solver_check(ctx, solver))) { 73 | case Z3_L_FALSE: 74 | break; 75 | case Z3_L_UNDEF: 76 | is_unknown_z3 = 1; 77 | break; 78 | case Z3_L_TRUE: 79 | is_sat_z3 = 1; 80 | break; 81 | } 82 | 83 | gettimeofday(&stop, NULL); 84 | elapsed_time = compute_time_msec(&start, &stop); 85 | cumulative_z3 += elapsed_time; 86 | z3_sat += is_sat_z3; 87 | 88 | Z3_solver_dec_ref(ctx, solver); 89 | 90 | #ifdef LOG_ON_FILE 91 | fprintf(log_file, "%.3lf,%s", elapsed_time, 92 | is_sat_z3 ? "sat" : (is_unknown_z3 ? "unknown" : "unsat")); 93 | fprintf(log_file, "\n"); 94 | #endif 95 | 96 | pp_printf(2, 1, "cumulative z3 %.03lf msec", cumulative_z3); 97 | pp_printf(3, 1, "sat z3 %ld", z3_sat); 98 | } 99 | 100 | pp_printf(2, 1, "cumulative z3 %.03lf msec", cumulative_z3); 101 | pp_printf(3, 1, "sat z3 %ld", z3_sat); 102 | pp_set_line(5); 103 | puts(""); 104 | Z3_ast_vector_dec_ref(ctx, queries); 105 | Z3_del_config(cfg); 106 | Z3_del_context(ctx); 107 | fclose(log_file); 108 | return 0; 109 | } -------------------------------------------------------------------------------- /tools/test-easy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "z3-fuzzy.h" 5 | 6 | // #define DUMP_SAT_QUERIES 7 | // #define DUMP_PROOFS 8 | 9 | fuzzy_ctx_t fctx; 10 | 11 | int main(int argc, char* argv[]) 12 | { 13 | Z3_config cfg = Z3_mk_config(); 14 | Z3_context ctx = Z3_mk_context(cfg); 15 | Z3_ast const* proof; 16 | unsigned long proof_size; 17 | Z3_ast query; 18 | Z3_sort bsort = Z3_mk_bv_sort(ctx, 8); 19 | 20 | z3fuzz_init(&fctx, ctx, "query_db/simple.seed", NULL); 21 | 22 | Z3_symbol sk0 = Z3_mk_int_symbol(ctx, 0); 23 | Z3_ast k0 = Z3_mk_const(ctx, sk0, bsort); 24 | Z3_symbol sk1 = Z3_mk_int_symbol(ctx, 1); 25 | Z3_ast k1 = Z3_mk_const(ctx, sk1, bsort); 26 | Z3_symbol sk2 = Z3_mk_int_symbol(ctx, 2); 27 | Z3_ast k2 = Z3_mk_const(ctx, sk2, bsort); 28 | Z3_symbol sk3 = Z3_mk_int_symbol(ctx, 3); 29 | Z3_ast k3 = Z3_mk_const(ctx, sk3, bsort); 30 | 31 | query = Z3_mk_concat(ctx, k0, k1); 32 | query = Z3_mk_concat(ctx, query, k2); 33 | query = Z3_mk_concat(ctx, query, k3); 34 | 35 | query = Z3_mk_eq(ctx, query, 36 | Z3_mk_unsigned_int(ctx, 42, Z3_mk_bv_sort(ctx, 32))); 37 | 38 | z3fuzz_query_check_light(&fctx, query, query, &proof, &proof_size); 39 | 40 | z3fuzz_free(&fctx); 41 | return 0; 42 | } --------------------------------------------------------------------------------