瀏覽代碼

Merge pull request #378 from randy408/fuzz

Add libFuzzer fuzz target / OSS-Fuzz integration
Alanscut 5 年之前
父節點
當前提交
f00060af44
共有 4 個文件被更改,包括 146 次插入0 次删除
  1. 5 0
      fuzzing/CMakeLists.txt
  2. 68 0
      fuzzing/cjson_read_fuzzer.c
  3. 54 0
      fuzzing/fuzz_main.c
  4. 19 0
      fuzzing/ossfuzz.sh

+ 5 - 0
fuzzing/CMakeLists.txt

@@ -26,3 +26,8 @@ if (ENABLE_FUZZING)
 
 
 endif()
+
+if(ENABLE_CJSON_TEST)
+    ADD_EXECUTABLE(fuzz_main fuzz_main.c cjson_read_fuzzer.c)
+    TARGET_LINK_LIBRARIES(fuzz_main cjson)
+endif()

+ 68 - 0
fuzzing/cjson_read_fuzzer.c

@@ -0,0 +1,68 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "../cJSON.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); /* required by C89 */
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
+{
+    cJSON *json;
+    size_t offset = 4;
+    unsigned char *copied;
+    char *printed_json = NULL;
+    int minify, require_termination, formatted, buffered;
+
+
+    if(size <= offset) return 0;
+    if(data[size-1] != '\0') return 0;
+    if(data[0] != '1' && data[0] != '0') return 0;
+    if(data[1] != '1' && data[1] != '0') return 0;
+    if(data[2] != '1' && data[2] != '0') return 0;
+    if(data[3] != '1' && data[3] != '0') return 0;
+
+    minify              = data[0] == '1' ? 1 : 0;
+    require_termination = data[1] == '1' ? 1 : 0;
+    formatted           = data[2] == '1' ? 1 : 0;
+    buffered            = data[3] == '1' ? 1 : 0;
+
+    json = cJSON_ParseWithOpts((const char*)data + offset, NULL, require_termination);
+
+    if(json == NULL) return 0;
+
+    if(buffered)
+    {
+        printed_json = cJSON_PrintBuffered(json, 1, formatted);
+    }
+    else
+    {
+        /* unbuffered printing */
+        if(formatted)
+        {
+            printed_json = cJSON_Print(json);
+        }
+        else
+        {
+            printed_json = cJSON_PrintUnformatted(json);
+        }
+    }
+
+    if(printed_json != NULL) free(printed_json);
+
+    if(minify)
+    {
+        copied = (unsigned char*)malloc(size);
+        if(copied == NULL) return 0;
+
+        memcpy(copied, data, size);
+
+        cJSON_Minify((char*)copied + offset);
+
+        free(copied);
+    }
+
+    cJSON_Delete(json);
+
+    return 0;
+}

+ 54 - 0
fuzzing/fuzz_main.c

@@ -0,0 +1,54 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); /* required by C89 */
+
+/* fuzz target entry point, works without libFuzzer */
+
+int main(int argc, char **argv)
+{
+    FILE *f;
+    char *buf = NULL;
+    long siz_buf;
+
+    if(argc < 2)
+    {
+        fprintf(stderr, "no input file\n");
+        goto err;
+    }
+
+    f = fopen(argv[1], "rb");
+    if(f == NULL)
+    {
+        fprintf(stderr, "error opening input file %s\n", argv[1]);
+        goto err;
+    }
+
+    fseek(f, 0, SEEK_END);
+
+    siz_buf = ftell(f);
+    rewind(f);
+
+    if(siz_buf < 1) goto err;
+
+    buf = (char*)malloc((size_t)siz_buf);
+    if(buf == NULL)
+    {
+        fprintf(stderr, "malloc() failed\n");
+        goto err;
+    }
+
+    if(fread(buf, (size_t)siz_buf, 1, f) != 1)
+    {
+        fprintf(stderr, "fread() failed\n");
+        goto err;
+    }
+
+    (void)LLVMFuzzerTestOneInput((uint8_t*)buf, (size_t)siz_buf);
+
+err:
+    free(buf);
+
+    return 0;
+}

+ 19 - 0
fuzzing/ossfuzz.sh

@@ -0,0 +1,19 @@
+#!/bin/bash -eu
+
+# This script is meant to be run by
+# https://github.com/google/oss-fuzz/blob/master/projects/cjson/Dockerfile
+
+mkdir build
+cd build
+cmake -DBUILD_SHARED_LIBS=OFF -DENABLE_CJSON_TEST=OFF ..
+make -j$(nproc)
+
+$CC $CFLAGS -std=c89 -I. \
+    $SRC/cjson/fuzzing/cjson_read_fuzzer.c \
+    -o $OUT/cjson_read_fuzzer \
+    $LIB_FUZZING_ENGINE $SRC/cjson/build/libcjson.a
+
+find $SRC/cjson/fuzzing/inputs -name "*" | \
+     xargs zip $OUT/cjson_read_fuzzer_seed_corpus.zip
+
+cp $SRC/cjson/fuzzing/json.dict $OUT/cjson_read_fuzzer.dict