Skip to content

Commit

Permalink
[libc] add atof, strtof and strtod
Browse files Browse the repository at this point in the history
Add the string to floating point conversion functions.
Long doubles aren't supported yet, but floats and doubles are. The
primary algorithm used is the Eisel-Lemire ParseNumberF64 algorithm,
with the Simple Decimal Conversion algorithm as backup.

Links for more information on the algorithms:

Number Parsing at a Gigabyte per Second, Software: Practice and
Experience 51 (8), 2021 (https://arxiv.org/abs/2101.11408)
https://nigeltao.github.io/blog/2020/eisel-lemire.html
https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html

Differential Revision: https://reviews.llvm.org/D109261
  • Loading branch information
michaelrj-google committed Oct 18, 2021
1 parent 684b626 commit 87c0160
Show file tree
Hide file tree
Showing 24 changed files with 2,301 additions and 0 deletions.
3 changes: 3 additions & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ set(TARGET_LIBC_ENTRYPOINTS
# stdlib.h entrypoints
libc.src.stdlib.abs
libc.src.stdlib.atoi
libc.src.stdlib.atof
libc.src.stdlib.atol
libc.src.stdlib.atoll
libc.src.stdlib.bsearch
Expand All @@ -65,6 +66,8 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.stdlib.llabs
libc.src.stdlib.lldiv
libc.src.stdlib.qsort
libc.src.stdlib.strtod
libc.src.stdlib.strtof
libc.src.stdlib.strtol
libc.src.stdlib.strtoll
libc.src.stdlib.strtoul
Expand Down
10 changes: 10 additions & 0 deletions libc/fuzzing/stdlib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,13 @@ add_libc_fuzzer(
libc.src.stdlib.qsort
)

add_libc_fuzzer(
atof_fuzz
SRCS
atof_fuzz.cpp
HDRS
StringParserOutputDiff.h
DEPENDS
libc.src.stdlib.atof
)

35 changes: 35 additions & 0 deletions libc/fuzzing/stdlib/StringParserOutputDiff.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//===-- Template to diff single-input-single-output functions ---*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_FUZZING_STDLIB_STRING_PARSER_OUTPUT_DIFF_H
#define LLVM_LIBC_FUZZING_STDLIB_STRING_PARSER_OUTPUT_DIFF_H

#include "fuzzing/math/Compare.h"

#include <stddef.h>
#include <stdint.h>

template <typename T> using StringInputSingleOutputFunc = T (*)(const char *);

template <typename T>
void StringParserOutputDiff(StringInputSingleOutputFunc<T> func1,
StringInputSingleOutputFunc<T> func2,
const uint8_t *data, size_t size) {
if (size < sizeof(T))
return;

const char *x = reinterpret_cast<const char *>(data);

T result1 = func1(x);
T result2 = func2(x);

if (!ValuesEqual(result1, result2))
__builtin_trap();
}

#endif // LLVM_LIBC_FUZZING_STDLIB_STRING_PARSER_OUTPUT_DIFF_H
32 changes: 32 additions & 0 deletions libc/fuzzing/stdlib/atof_fuzz.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//===-- atof_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 <stddef.h>
#include <stdint.h>
#include <stdlib.h>

#include "fuzzing/stdlib/StringParserOutputDiff.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.

StringParserOutputDiff<double>(&__llvm_libc::atof, &::atof, container, size);
delete[] container;
return 0;
}
3 changes: 3 additions & 0 deletions libc/spec/stdc.td
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"labs", RetValSpec<LongType>, [ArgSpec<LongType>]>,
FunctionSpec<"llabs", RetValSpec<LongLongType>, [ArgSpec<LongLongType>]>,

FunctionSpec<"atof", RetValSpec<DoubleType>, [ArgSpec<ConstCharRestrictedPtr>]>,
FunctionSpec<"atoi", RetValSpec<IntType>, [ArgSpec<ConstCharPtr>]>,
FunctionSpec<"atol", RetValSpec<LongType>, [ArgSpec<ConstCharPtr>]>,
FunctionSpec<"atoll", RetValSpec<LongLongType>, [ArgSpec<ConstCharPtr>]>,
Expand All @@ -505,6 +506,8 @@ def StdC : StandardSpec<"stdc"> {

FunctionSpec<"qsort", RetValSpec<VoidType>, [ArgSpec<VoidPtr>, ArgSpec<SizeTType>, ArgSpec<SizeTType>, ArgSpec<QSortCompareT>]>,

FunctionSpec<"strtod", RetValSpec<DoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>,
FunctionSpec<"strtof", RetValSpec<FloatType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>,
FunctionSpec<"strtol", RetValSpec<LongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
FunctionSpec<"strtoll", RetValSpec<LongLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
FunctionSpec<"strtoul", RetValSpec<UnsignedLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
Expand Down
2 changes: 2 additions & 0 deletions libc/src/__support/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ add_header_library(
str_conv_utils
HDRS
str_conv_utils.h
str_to_float.h
DEPENDS
.ctype_utils
.high_precision_decimal
libc.include.errno
libc.src.errno.__errno_location
libc.utils.CPP.standalone_cpp
libc.src.__support.FPUtil.fputil
)

add_header_library(
Expand Down
Loading

0 comments on commit 87c0160

Please sign in to comment.