Skip to content

Commit

Permalink
[libc] add standalone strtoint/float fuzzers
Browse files Browse the repository at this point in the history
Fuzzing the string to integer and float functions without relying on the
system libc allows for tests to be run in a wider variety of places.

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D143616
  • Loading branch information
michaelrj-google committed Feb 10, 2023
1 parent 79a3803 commit 3a66446
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 0 deletions.
25 changes: 25 additions & 0 deletions libc/fuzzing/stdlib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@ add_libc_fuzzer(
libc.src.stdlib.atof
)

add_libc_fuzzer(
strtofloat_fuzz
SRCS
strtofloat_fuzz.cpp
DEPENDS
libc.src.stdlib.atof
libc.src.stdlib.strtof
libc.src.stdlib.strtod
libc.src.stdlib.strtold
)

add_libc_fuzzer(
strtointeger_differential_fuzz
SRCS
Expand Down Expand Up @@ -49,3 +60,17 @@ add_libc_fuzzer(
COMPILE_OPTIONS
-DLLVM_LIBC_FUZZ_ATOI_CLEANER_INPUT
)

add_libc_fuzzer(
strtointeger_fuzz
SRCS
strtointeger_fuzz.cpp
DEPENDS
libc.src.stdlib.atoi
libc.src.stdlib.atol
libc.src.stdlib.atoll
libc.src.stdlib.strtol
libc.src.stdlib.strtoll
libc.src.stdlib.strtoul
libc.src.stdlib.strtoull
)
50 changes: 50 additions & 0 deletions libc/fuzzing/stdlib/strtofloat_fuzz.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//===-- strtofloat_fuzz.cpp -----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// Fuzzing test for llvm-libc atof implementation.
///
//===----------------------------------------------------------------------===//
#include "src/stdlib/atof.h"
#include "src/stdlib/strtod.h"
#include "src/stdlib/strtof.h"
#include "src/stdlib/strtold.h"
#include <stddef.h>
#include <stdint.h>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
uint8_t *container = new uint8_t[size + 1];
if (!container)
__builtin_trap();
size_t i;

for (i = 0; i < size; ++i)
container[i] = data[i];
container[size] = '\0'; // Add null terminator to container.

const char *str_ptr = reinterpret_cast<const char *>(container);

char *out_ptr = nullptr;

// This fuzzer only checks that the alrogithms didn't read beyond the end of
// the string in container. Combined with sanitizers, this will check that the
// code is not reading memory beyond what's expected. This test does not make
// any attempt to check correctness of the result.
auto volatile atof_output = __llvm_libc::atof(str_ptr);
auto volatile strtof_output = __llvm_libc::strtof(str_ptr, &out_ptr);
if (str_ptr + size < out_ptr)
__builtin_trap();
auto volatile strtod_output = __llvm_libc::strtod(str_ptr, &out_ptr);
if (str_ptr + size < out_ptr)
__builtin_trap();
auto volatile strtold_output = __llvm_libc::strtold(str_ptr, &out_ptr);
if (str_ptr + size < out_ptr)
__builtin_trap();

delete[] container;
return 0;
}
70 changes: 70 additions & 0 deletions libc/fuzzing/stdlib/strtointeger_fuzz.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//===-- strtointeger_fuzz.cpp ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// Fuzzing test for llvm-libc atof implementation.
///
//===----------------------------------------------------------------------===//
#include "src/stdlib/atoi.h"
#include "src/stdlib/atol.h"
#include "src/stdlib/atoll.h"
#include "src/stdlib/strtol.h"
#include "src/stdlib/strtoll.h"
#include "src/stdlib/strtoul.h"
#include "src/stdlib/strtoull.h"
#include <stddef.h>
#include <stdint.h>

// This takes the randomized bytes in data and interprets the first byte as the
// base for the string to integer conversion and the rest of them as a string to
// be passed to the string to integer conversion.
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
size_t container_size = 0;
if (size == 0) {
container_size = 1;
} else {
container_size = size;
}
uint8_t *container = new uint8_t[container_size];
if (!container)
__builtin_trap();

int base = 0;
if (size > 0) {
base = data[0] % 36;
base = base + ((base == 0) ? 0 : 1);
}
for (size_t i = 1; i < size; ++i) {
container[i - 1] = data[i];
}

container[container_size - 1] = '\0'; // Add null terminator to container.

const char *str_ptr = reinterpret_cast<const char *>(container);

char *out_ptr = nullptr;

auto volatile atoi_output = __llvm_libc::atoi(str_ptr);
auto volatile atol_output = __llvm_libc::atol(str_ptr);
auto volatile atoll_output = __llvm_libc::atoll(str_ptr);
auto volatile strtol_output = __llvm_libc::strtol(str_ptr, &out_ptr, base);
if (str_ptr + container_size - 1 < out_ptr)
__builtin_trap();
auto volatile strtoll_output = __llvm_libc::strtoll(str_ptr, &out_ptr, base);
if (str_ptr + container_size - 1 < out_ptr)
__builtin_trap();
auto volatile strtoul_output = __llvm_libc::strtoul(str_ptr, &out_ptr, base);
if (str_ptr + container_size - 1 < out_ptr)
__builtin_trap();
auto volatile strtoull_output =
__llvm_libc::strtoull(str_ptr, &out_ptr, base);
if (str_ptr + container_size - 1 < out_ptr)
__builtin_trap();

delete[] container;
return 0;
}

0 comments on commit 3a66446

Please sign in to comment.