aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Ari Rubinstein <arirubinstein@users.noreply.github.com>2022-06-24 16:38:05 -0700
committerGravatar GitHub <noreply@github.com>2022-06-24 19:38:05 -0400
commit45023e3a63a19719e42bbf265db1851ee2ab1eb0 (patch)
tree201c3b867bb90256caf628bbe27aea9e52fb7a0a
parentd1e407f0f335d167620c48a4bd93ff65aaec7bac (diff)
XS: implement xst_jsonparse target, and wrap fuzzing binaries (#7910)
XS: implement json_parse target, and wrap fuzzing binaries with a wrapper binary to ignore leaks
-rw-r--r--projects/xs/Dockerfile1
-rwxr-xr-xprojects/xs/build.sh29
-rw-r--r--projects/xs/target.c79
3 files changed, 108 insertions, 1 deletions
diff --git a/projects/xs/Dockerfile b/projects/xs/Dockerfile
index 8264c9ac..4b266df2 100644
--- a/projects/xs/Dockerfile
+++ b/projects/xs/Dockerfile
@@ -17,5 +17,6 @@ FROM gcr.io/oss-fuzz-base/base-builder
RUN git clone --depth=1 https://github.com/Moddable-OpenSource/moddable moddable
WORKDIR moddable
+COPY target.c $SRC/
COPY build.sh $SRC/
COPY xst.options $SRC/
diff --git a/projects/xs/build.sh b/projects/xs/build.sh
index 65d022c4..518ac90f 100755
--- a/projects/xs/build.sh
+++ b/projects/xs/build.sh
@@ -17,9 +17,36 @@
export MODDABLE=$PWD
export ASAN_OPTIONS="detect_leaks=0"
+FUZZ_TARGETS=(
+ xst
+ xst_jsonparse
+)
+
+# Build a wrapper binary for each target to set environment variables.
+for FUZZ_TARGET in ${FUZZ_TARGETS[@]}
+do
+ $CC $CFLAGS -O0 \
+ -DFUZZ_TARGET=$FUZZ_TARGET \
+ $SRC/target.c -o $OUT/$FUZZ_TARGET
+done
+
+# Stash actual binaries in subdirectory so they aren't picked up by target discovery
+mkdir -p $OUT/real
+
+# build main target
cd "$MODDABLE/xs/makefiles/lin"
FUZZING=1 OSSFUZZ=1 make debug
cd "$MODDABLE"
-cp ./build/bin/lin/debug/xst $OUT/
+cp ./build/bin/lin/debug/xst $OUT/real/xst
cp $SRC/xst.options $OUT/
+
+# build jsonparse target
+cd "$MODDABLE/xs/makefiles/lin"
+make -f xst.mk clean
+FUZZING=1 OSSFUZZ=1 OSSFUZZ_JSONPARSE=1 make debug
+
+cd "$MODDABLE"
+cp ./build/bin/lin/debug/xst $OUT/real/xst_jsonparse
+
+cp $SRC/xst.options $OUT/xst_jsonparse.options
diff --git a/projects/xs/target.c b/projects/xs/target.c
new file mode 100644
index 00000000..55ac2cde
--- /dev/null
+++ b/projects/xs/target.c
@@ -0,0 +1,79 @@
+/*
+#
+# 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 <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define STRINGLIT(S) #S
+#define STRINGIFY(S) STRINGLIT(S)
+
+// Heavily inspired by firefox's wrapper located at
+// https://github.com/google/oss-fuzz/blob/master/projects/firefox/target.c
+
+// Required for oss-fuzz to consider the binary a target.
+static const char* magic __attribute__((used)) = "LLVMFuzzerTestOneInput";
+
+int main(int argc, char* argv[]) {
+ char path[PATH_MAX] = {0};
+
+ // Handle (currently not used) relative binary path.
+ if (**argv != '/') {
+ if (!getcwd(path, PATH_MAX - 1)) {
+ perror("getcwd");
+ exit(1);
+ }
+ strcat(path, "/");
+ }
+
+ if (strlen(path) + strlen(*argv) + 40 >= PATH_MAX) {
+ fprintf(stderr, "Path length would exceed PATH_MAX\n");
+ exit(1);
+ }
+
+ strcat(path, *argv);
+ char* solidus = strrchr(path, '/');
+ *solidus = 0; // terminate path before last /
+
+ setenv("FUZZER", STRINGIFY(FUZZ_TARGET), 1);
+
+ // Temporary (or permanent?) work-arounds for fuzzing interface bugs.
+ char* options = getenv("ASAN_OPTIONS");
+ if (options) {
+ char* ptr;
+ char* new_options = strdup(options);
+ // ptr = strstr(new_options, "detect_stack_use_after_return=1");
+ // if (ptr) ptr[30] = '0';
+ ptr = strstr(new_options, "detect_leaks=1");
+ if (ptr) ptr[13] = '0';
+ setenv("ASAN_OPTIONS", new_options, 1);
+ free(new_options);
+ }
+
+ char real_fuzz_bin[PATH_MAX] = {0};
+ strcpy(real_fuzz_bin, path);
+ strcat(real_fuzz_bin, "/real/");
+ strcat(real_fuzz_bin, STRINGIFY(FUZZ_TARGET));
+ fprintf(stderr, "Invoking %s with detect_leaks=0\n", real_fuzz_bin);
+
+ int ret = execv(real_fuzz_bin, argv);
+ if (ret)
+ perror("execv");
+ return ret;
+}