From 43bc23ef05177bebc2d6b97abce240c76c5f6d45 Mon Sep 17 00:00:00 2001 From: David Korczynski Date: Thu, 25 Jul 2024 13:02:26 -0700 Subject: [PATCH] llamacpp: add load model fuzzer Signed-off-by: David Korczynski --- projects/llamacpp/build.sh | 15 ++++++ projects/llamacpp/fuzzers/fuzz_load_model.cpp | 53 +++++++++++++++++++ .../llamacpp/fuzzers/fuzz_load_model.dict | 1 + 3 files changed, 69 insertions(+) create mode 100644 projects/llamacpp/fuzzers/fuzz_load_model.cpp create mode 100644 projects/llamacpp/fuzzers/fuzz_load_model.dict diff --git a/projects/llamacpp/build.sh b/projects/llamacpp/build.sh index e462ddb25dab..3af95082abb6 100755 --- a/projects/llamacpp/build.sh +++ b/projects/llamacpp/build.sh @@ -18,6 +18,11 @@ export GGML_NO_OPENMP=1 sed -i 's/:= c++/:= ${CXX}/g' ./Makefile sed -i 's/:= cc/:= ${CC}/g' ./Makefile +# Avoid function that forks + starts instance of gdb. +sed -i 's/ggml_print_backtrace();//g' ./ggml/include/ggml.h + +# Remove statefulness during fuzzing. +sed -i 's/static bool is_first_call/bool is_first_call/g' ./ggml/src/ggml.c UNAME_M=amd642 UNAME_p=amd642 LLAMA_NO_METAL=1 make -j$(nproc) @@ -42,6 +47,16 @@ cp fuzzers/*.dict $OUT/ $CXX $LIB_FUZZING_ENGINE $CXXFLAGS ${FLAGS} ${OBJ_FILES} fuzzers/fuzz_json_to_grammar.cpp -o $OUT/fuzz_json_to_grammar $CXX $LIB_FUZZING_ENGINE $CXXFLAGS ${FLAGS} ${OBJ_FILES} fuzzers/fuzz_grammar.cpp -o $OUT/fuzz_grammar +# Create a corpus for load_model_fuzzer +./llama-gguf dummy.gguf w +mkdir $SRC/load-model-corpus +mv dummy.gguf $SRC/load-model-corpus/ +zip -j $OUT/fuzz_load_model_seed_corpus.zip $SRC/load-model-corpus/* +$CXX $LIB_FUZZING_ENGINE $CXXFLAGS ${FLAGS} ${OBJ_FILES} \ + -Wl,--wrap,abort fuzzers/fuzz_load_model.cpp -o $OUT/fuzz_load_model +echo "[libfuzzer]" > $OUT/fuzz_load_model.options +echo "detect_leaks=0" >> $OUT/fuzz_load_model.options + if [ "$FUZZING_ENGINE" != "afl" ] then $CXX $LIB_FUZZING_ENGINE $CXXFLAGS ${FLAGS} ${OBJ_FILES} -DFUZZ_BGE fuzzers/fuzz_tokenizer.cpp -o $OUT/fuzz_tokenizer_bge diff --git a/projects/llamacpp/fuzzers/fuzz_load_model.cpp b/projects/llamacpp/fuzzers/fuzz_load_model.cpp new file mode 100644 index 000000000000..d8e9f3c2c2d5 --- /dev/null +++ b/projects/llamacpp/fuzzers/fuzz_load_model.cpp @@ -0,0 +1,53 @@ +/* Copyright 2024 Google LLC +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "llama.h" +#include +#include +#include + +jmp_buf fuzzing_jmp_buf; + +extern "C" void __wrap_abort(void) { longjmp(fuzzing_jmp_buf, 1); } + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + llama_backend_init(); + + char filename[256]; + sprintf(filename, "/tmp/libfuzzer.%d", getpid()); + + FILE *fp = fopen(filename, "wb"); + if (!fp) { + return 0; + } + fwrite(data, size, 1, fp); + fclose(fp); + + auto params = llama_model_params{}; + memset(¶ms, 0x0, sizeof(struct llama_model_params)); + params.use_mmap = false; + params.progress_callback = [](float progress, void *ctx) { + (void)ctx; + return progress > 0.50; + }; + + if (setjmp(fuzzing_jmp_buf) == 0) { + auto *model = llama_load_model_from_file(filename, params); + if (model != nullptr) { + llama_free_model(model); + } + } + llama_backend_free(); + + unlink(filename); + return 0; +} diff --git a/projects/llamacpp/fuzzers/fuzz_load_model.dict b/projects/llamacpp/fuzzers/fuzz_load_model.dict new file mode 100644 index 000000000000..463bd4d1c8f5 --- /dev/null +++ b/projects/llamacpp/fuzzers/fuzz_load_model.dict @@ -0,0 +1 @@ +"GUFF"