This commit is contained in:
DavidKorczynski 2025-02-26 00:46:33 +01:00 committed by GitHub
commit 1d5bbee73a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 227 additions and 0 deletions

View File

@ -0,0 +1,6 @@
FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update && apt-get install -y make autoconf automake libtool
COPY . $SRC/libuv
COPY .clusterfuzzlite/build.sh $SRC/build.sh
WORKDIR $SRC/libuv

View File

@ -0,0 +1,16 @@
# ClusterFuzzLite set up
This folder contains a fuzzing set for [ClusterFuzzLite](https://google.github.io/clusterfuzzlite).
To reproduce this set up the way ClusterFuzzLite does it (by way of [OSS-Fuzz](https://github.com/google/oss-fuzz)) you can do:
```sh
git clone https://github.com/google/oss-fuzz
git clone https://github.com/libuv/libuv
cd libuv
# Build the fuzzers in .clusterfuzzlite
python3 ../oss-fuzz/infra/helper.py build_fuzzers --external $PWD
# Run the fuzzer for 10 seconds
python3 ../oss-fuzz/infra/helper.py run_fuzzer --external $PWD libuv_fuzzer -- -max_total_time=10
```

25
.clusterfuzzlite/build.sh Normal file
View File

@ -0,0 +1,25 @@
#!/bin/bash -eu
# Supply build instructions
# Use the following environment variables to build the code
# $CXX: c++ compiler
# $CC: c compiler
# CFLAGS: compiler flags for C files
# CXXFLAGS: compiler flags for CPP files
# LIB_FUZZING_ENGINE: linker flag for fuzzing harnesses
# When run multiple times locally leftover files may be present in shared
# OUT folder. Clear these in case.
rm -f $OUT/test_file*
sh autogen.sh
./configure
make -j2
make install
find . -name "*.a"
# Copy all fuzzer executables to $OUT/
$CC $CFLAGS $LIB_FUZZING_ENGINE \
$SRC/libuv/.clusterfuzzlite/libuv_fuzzer.c \
-o $OUT/libuv_fuzzer \
-I$SRC/libuv/include \
$SRC/libuv/.libs/libuv.a

View File

@ -0,0 +1,149 @@
/* Copyright libuv contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "../src/idna.c"
#include "uv.h"
static uv_loop_t* loop;
static void dummy_cb(uv_fs_t* req) { (void)req; }
void test_idna(char *payload, size_t size) {
char de[256];
uv__idna_toascii(payload, payload + size, de, de + 256);
uv_wtf8_length_as_utf16(payload);
}
void test_file_ops_1(const uint8_t* data, size_t size) {
char read_buf[256];
uv_fs_t open_req1;
uv_fs_t write_req;
uv_buf_t iov;
uv_fs_t close_req;
uv_fs_t read_req;
unlink("test_file");
uv_fs_open(NULL, &open_req1, "test_file", UV_FS_O_WRONLY | UV_FS_O_CREAT,
S_IWUSR | S_IRUSR, NULL);
uv_fs_req_cleanup(&open_req1);
iov = uv_buf_init((char*)data, size);
uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL);
uv_fs_req_cleanup(&write_req);
/* Close after writing */
uv_fs_close(NULL, &close_req, open_req1.result, NULL);
uv_fs_req_cleanup(&close_req);
/* Open again to read */
uv_fs_open(NULL, &open_req1, "test_file", UV_FS_O_WRONLY | UV_FS_O_CREAT,
S_IWUSR | S_IRUSR, NULL);
uv_fs_req_cleanup(&open_req1);
iov = uv_buf_init(read_buf, sizeof(read_buf));
uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL);
uv_fs_req_cleanup(&read_req);
uv_fs_close(NULL, &close_req, open_req1.result, NULL);
uv_fs_req_cleanup(&close_req);
unlink("test_file");
}
void test_file_ops_2(const uint8_t* data, size_t size) {
uv_buf_t iov;
uv_fs_t open_req1;
uv_fs_t write_req;
uv_fs_t copy_req;
uv_fs_t close_req;
uv_fs_open(NULL, &open_req1, "test_file", UV_FS_O_WRONLY | UV_FS_O_CREAT,
S_IWUSR | S_IRUSR, NULL);
uv_fs_req_cleanup(&open_req1);
iov = uv_buf_init(data, size);
uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL);
uv_fs_req_cleanup(&write_req);
uv_fs_copyfile(NULL, &copy_req, "test_file", "test_file2", 0, NULL);
uv_fs_req_cleanup(&copy_req);
uv_fs_close(NULL, &close_req, open_req1.result, NULL);
uv_fs_req_cleanup(&close_req);
uv_fs_req_cleanup(&copy_req);
}
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size == 0)
return 0;
uint8_t decider = data[0] % 7;
data++;
size--;
/* Allocate a null-terminated string that can be used in various fuzz
* operations.
*/
char* new_str = malloc(size + 1);
if (new_str == NULL)
return 0;
memcpy(new_str, data, size);
new_str[size] = '\0';
/* Perform a single fuzz operation and use the fuzz data to decide
* which it should be.
*/
if (decider == 0) {
uv_fs_t req;
loop = uv_default_loop();
uv_fs_realpath(loop, &req, new_str, dummy_cb);
uv_run(loop, UV_RUN_DEFAULT);
uv_fs_req_cleanup(&req);
} else if (decider == 1) {
struct sockaddr_in addr;
uv_ip4_addr(new_str, 9123, &addr);
} else if (decider == 2) {
struct sockaddr_in6 addr;
uv_ip6_addr(new_str, 9123, &addr);
} else if (decider == 3) {
test_file_ops_1(data, size);
} else if (decider == 4) {
test_file_ops_2(data, size);
} else if (decider == 5) {
test_idna(new_str, size);
} else {
uv_fs_t req;
loop = uv_default_loop();
uv_fs_open(NULL, &req, new_str, UV_FS_O_RDONLY, 0, NULL);
uv_run(loop, UV_RUN_DEFAULT);
uv_fs_req_cleanup(&req);
}
free(new_str);
return 0;
}

View File

@ -0,0 +1 @@
language: c

30
.github/workflows/cflite_pr.yml vendored Normal file
View File

@ -0,0 +1,30 @@
name: ClusterFuzzLite PR fuzzing
on:
workflow_dispatch:
pull_request:
branches: [ v1.x ]
permissions: read-all
jobs:
PR:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
sanitizer: [address]
steps:
- name: Build Fuzzers (${{ matrix.sanitizer }})
id: build
uses: google/clusterfuzzlite/actions/build_fuzzers@v1
with:
sanitizer: ${{ matrix.sanitizer }}
language: c
bad-build-check: false
- name: Run Fuzzers (${{ matrix.sanitizer }})
id: run
uses: google/clusterfuzzlite/actions/run_fuzzers@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
fuzz-seconds: 100
mode: 'code-change'
report-unreproducible-crashes: false
sanitizer: ${{ matrix.sanitizer }}