Skip to content

Commit 87c0160

Browse files
[libc] add atof, strtof and strtod
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
1 parent 684b626 commit 87c0160

24 files changed

+2301
-0
lines changed

libc/config/linux/x86_64/entrypoints.txt

+3
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ set(TARGET_LIBC_ENTRYPOINTS
5656
# stdlib.h entrypoints
5757
libc.src.stdlib.abs
5858
libc.src.stdlib.atoi
59+
libc.src.stdlib.atof
5960
libc.src.stdlib.atol
6061
libc.src.stdlib.atoll
6162
libc.src.stdlib.bsearch
@@ -65,6 +66,8 @@ set(TARGET_LIBC_ENTRYPOINTS
6566
libc.src.stdlib.llabs
6667
libc.src.stdlib.lldiv
6768
libc.src.stdlib.qsort
69+
libc.src.stdlib.strtod
70+
libc.src.stdlib.strtof
6871
libc.src.stdlib.strtol
6972
libc.src.stdlib.strtoll
7073
libc.src.stdlib.strtoul

libc/fuzzing/stdlib/CMakeLists.txt

+10
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,13 @@ add_libc_fuzzer(
66
libc.src.stdlib.qsort
77
)
88

9+
add_libc_fuzzer(
10+
atof_fuzz
11+
SRCS
12+
atof_fuzz.cpp
13+
HDRS
14+
StringParserOutputDiff.h
15+
DEPENDS
16+
libc.src.stdlib.atof
17+
)
18+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===-- Template to diff single-input-single-output functions ---*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_FUZZING_STDLIB_STRING_PARSER_OUTPUT_DIFF_H
10+
#define LLVM_LIBC_FUZZING_STDLIB_STRING_PARSER_OUTPUT_DIFF_H
11+
12+
#include "fuzzing/math/Compare.h"
13+
14+
#include <stddef.h>
15+
#include <stdint.h>
16+
17+
template <typename T> using StringInputSingleOutputFunc = T (*)(const char *);
18+
19+
template <typename T>
20+
void StringParserOutputDiff(StringInputSingleOutputFunc<T> func1,
21+
StringInputSingleOutputFunc<T> func2,
22+
const uint8_t *data, size_t size) {
23+
if (size < sizeof(T))
24+
return;
25+
26+
const char *x = reinterpret_cast<const char *>(data);
27+
28+
T result1 = func1(x);
29+
T result2 = func2(x);
30+
31+
if (!ValuesEqual(result1, result2))
32+
__builtin_trap();
33+
}
34+
35+
#endif // LLVM_LIBC_FUZZING_STDLIB_STRING_PARSER_OUTPUT_DIFF_H

libc/fuzzing/stdlib/atof_fuzz.cpp

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//===-- atof_fuzz.cpp -----------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
///
9+
/// Fuzzing test for llvm-libc atof implementation.
10+
///
11+
//===----------------------------------------------------------------------===//
12+
#include "src/stdlib/atof.h"
13+
#include <stddef.h>
14+
#include <stdint.h>
15+
#include <stdlib.h>
16+
17+
#include "fuzzing/stdlib/StringParserOutputDiff.h"
18+
19+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
20+
uint8_t *container = new uint8_t[size + 1];
21+
if (!container)
22+
__builtin_trap();
23+
size_t i;
24+
25+
for (i = 0; i < size; ++i)
26+
container[i] = data[i];
27+
container[size] = '\0'; // Add null terminator to container.
28+
29+
StringParserOutputDiff<double>(&__llvm_libc::atof, &::atof, container, size);
30+
delete[] container;
31+
return 0;
32+
}

libc/spec/stdc.td

+3
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,7 @@ def StdC : StandardSpec<"stdc"> {
495495
FunctionSpec<"labs", RetValSpec<LongType>, [ArgSpec<LongType>]>,
496496
FunctionSpec<"llabs", RetValSpec<LongLongType>, [ArgSpec<LongLongType>]>,
497497

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

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

509+
FunctionSpec<"strtod", RetValSpec<DoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>,
510+
FunctionSpec<"strtof", RetValSpec<FloatType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>,
508511
FunctionSpec<"strtol", RetValSpec<LongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
509512
FunctionSpec<"strtoll", RetValSpec<LongLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,
510513
FunctionSpec<"strtoul", RetValSpec<UnsignedLongType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>, ArgSpec<IntType>]>,

libc/src/__support/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@ add_header_library(
2323
str_conv_utils
2424
HDRS
2525
str_conv_utils.h
26+
str_to_float.h
2627
DEPENDS
2728
.ctype_utils
2829
.high_precision_decimal
2930
libc.include.errno
3031
libc.src.errno.__errno_location
3132
libc.utils.CPP.standalone_cpp
33+
libc.src.__support.FPUtil.fputil
3234
)
3335

3436
add_header_library(

0 commit comments

Comments
 (0)