Skip to content

Commit

Permalink
Merge pull request #2 from ngtcp2/fuzzer
Browse files Browse the repository at this point in the history
Add fuzzer
  • Loading branch information
tatsuhiro-t authored Nov 12, 2024
2 parents 895c587 + 6ab034f commit ad65582
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .clusterfuzzlite/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM gcr.io/oss-fuzz-base/base-builder:v1
RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config
COPY . $SRC/urlparse
WORKDIR urlparse
COPY .clusterfuzzlite/build.sh $SRC/
11 changes: 11 additions & 0 deletions .clusterfuzzlite/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash -eu

autoreconf -i
./configure --disable-dependency-tracking
make -j$(nproc) check TESTS=""

$CXX $CXXFLAGS -std=c++17 -I. \
fuzz/parser.cc -o $OUT/parser \
$LIB_FUZZING_ENGINE .libs/liburlparse.a .libs/libhttp-parser.a

zip -j $OUT/parser_seed_corpus.zip fuzz/corpus/parser/*
1 change: 1 addition & 0 deletions .clusterfuzzlite/project.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
language: c++
36 changes: 36 additions & 0 deletions .github/workflows/cflite_batch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: ClusterFuzzLite batch fuzzing
on:
schedule:
- cron: '0 0/6 * * *'
permissions: read-all
jobs:
BatchFuzzing:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
sanitizer:
- address
- undefined
- memory
steps:
- name: LLVM workaround
run: |
# https://github.com/actions/runner-images/issues/9491#issuecomment-1989718917
# Asan in llvm 14 provided in ubuntu 22.04 is incompatible with
# high-entropy ASLR in much newer kernels that GitHub runners are
# using leading to random crashes: https://reviews.llvm.org/D148280
sudo sysctl vm.mmap_rnd_bits=28
- name: Build Fuzzers (${{ matrix.sanitizer }})
id: build
uses: google/clusterfuzzlite/actions/build_fuzzers@v1
with:
sanitizer: ${{ matrix.sanitizer }}
- name: Run Fuzzers (${{ matrix.sanitizer }})
id: run
uses: google/clusterfuzzlite/actions/run_fuzzers@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
fuzz-seconds: 3600
mode: 'batch'
sanitizer: ${{ matrix.sanitizer }}
19 changes: 19 additions & 0 deletions .github/workflows/cflite_cron.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: ClusterFuzzLite cron tasks
on:
schedule:
- cron: '0 0 * * *'
permissions: read-all
jobs:
Pruning:
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
id: build
uses: google/clusterfuzzlite/actions/build_fuzzers@v1
- name: Run Fuzzers
id: run
uses: google/clusterfuzzlite/actions/run_fuzzers@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
fuzz-seconds: 600
mode: 'prune'
1 change: 1 addition & 0 deletions fuzz/corpus/parser/connect
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~%!$&'()*+,;=:@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-:12345
1 change: 1 addition & 0 deletions fuzz/corpus/parser/connect-ipv6
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~%!$&'()*+,;=:@[abcdefABCDEF0123456789:.%abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789%.-_~]:12345
1 change: 1 addition & 0 deletions fuzz/corpus/parser/example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
https://example.com/
1 change: 1 addition & 0 deletions fuzz/corpus/parser/ipv6
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
https://abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~%!$&'()*+,;=:@[abcdefABCDEF0123456789:.%abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789%.-_~]:12345/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~%!$&'()*+,;=:@/"<>[\]^`{|}?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~%!$&'()*+,;=:@/?"<>[\]^`{|}#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~%!$&'()*+,;=:@/?"<>[\]^`{|}
1 change: 1 addition & 0 deletions fuzz/corpus/parser/long
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
https://abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~%!$&'()*+,;=:@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-:12345/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~%!$&'()*+,;=:@/"<>[\]^`{|}?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~%!$&'()*+,;=:@/?"<>[\]^`{|}#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~%!$&'()*+,;=:@/?"<>[\]^`{|}
72 changes: 72 additions & 0 deletions fuzz/parser.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include "urlparse.h"
#include "http-parser/http_parser.h"

namespace {
/* Copied from https://github.com/nodejs/http-parser */
void dump_url(const uint8_t *url, const urlparse_url *u) {
size_t i;

fprintf(stderr, "\tfield_set: 0x%x, port: %u\n", u->field_set, u->port);
for (i = 0; i < URLPARSE_MAX; i++) {
if ((u->field_set & (1 << i)) == 0) {
fprintf(stderr, "\tfield_data[%zu]: unset\n", i);
continue;
}

fprintf(stderr, "\tfield_data[%zu]: off: %u len: %u part: \"%.*s\"\n", i,
u->field_data[i].off, u->field_data[i].len, u->field_data[i].len,
url + u->field_data[i].off);
}
}
} // namespace

namespace {
int fuzz(const uint8_t *data, size_t size, int is_connect) {
urlparse_url u;
struct http_parser_url hu;
int rv1, rv2;

rv1 = urlparse_parse_url(reinterpret_cast<const char *>(data), size,
is_connect, &u);
memset(&hu, 0, sizeof(hu));
rv2 = http_parser_parse_url(reinterpret_cast<const char *>(data), size,
is_connect, &hu);
if (rv2 != 0) {
rv2 = URLPARSE_ERR_PARSE;
}

if (rv1 != rv2) {
fprintf(
stderr,
"urlparse_parse_url(%d) and http_parser_parse_url(%d) disagree with "
"is_connect = %d\n",
rv1, rv2, is_connect);
return -1;
}

if (rv1 == 0 && memcmp(&hu, &u, sizeof(u)) != 0) {
fprintf(stderr, "is_connect = %d\n", is_connect);
fprintf(stderr, "target http_parser_url:\n");
dump_url(data, reinterpret_cast<urlparse_url *>(&hu));
fprintf(stderr, "result urlparse_url:\n");
dump_url(data, &u);

return -1;
}

return 0;
}
} // namespace

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (fuzz(data, size, /* is_connect = */ 0) != 0 ||
fuzz(data, size, /* is_connect = */ 1) != 0) {
abort();
}

return 0;
}

0 comments on commit ad65582

Please sign in to comment.