[libc-commits] [PATCH] D149359: [libc] add exception to atof differential fuzz

Michael Jones via Phabricator via libc-commits libc-commits at lists.llvm.org
Thu Apr 27 10:45:22 PDT 2023


michaelrj created this revision.
michaelrj added reviewers: sivachandra, lntue.
Herald added subscribers: libc-commits, ecnelises, tschuett.
Herald added projects: libc-project, All.
michaelrj requested review of this revision.

The differential fuzzer for atof found a bug in glibc's handling of
hexadecimal rounding. Since we can't easily update glibc and we want to
avoid false positives when running the fuzzer, I've added an exception
to skip all hexadecimal subnormal cases.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D149359

Files:
  libc/fuzzing/stdlib/atof_differential_fuzz.cpp


Index: libc/fuzzing/stdlib/atof_differential_fuzz.cpp
===================================================================
--- libc/fuzzing/stdlib/atof_differential_fuzz.cpp
+++ libc/fuzzing/stdlib/atof_differential_fuzz.cpp
@@ -16,6 +16,41 @@
 
 #include "fuzzing/stdlib/StringParserOutputDiff.h"
 
+// TODO: Remove this once glibc fixes hex subnormal rounding. See
+// https://sourceware.org/bugzilla/show_bug.cgi?id=30220
+#define LLVM_LIBC_FUZZER_GLIBC_HEX_SUBNORMAL_ERR
+#ifdef LLVM_LIBC_FUZZER_GLIBC_HEX_SUBNORMAL_ERR
+#include <ctype.h>
+constexpr double MIN_NORMAL = 0x1p-1022;
+
+bool has_hex_prefix(const uint8_t *str) {
+  size_t index = 0;
+
+  // Skip over leading whitespace
+  while (isspace(str[index])) {
+    ++index;
+  }
+  // Skip over sign
+  if (str[index] == '-' || str[index] == '+') {
+    ++index;
+  }
+  return str[index] == '0' && (tolower(str[index + 1])) == 'x';
+}
+
+bool should_be_skipped(const uint8_t *str) {
+  double init_result = __llvm_libc::atof(reinterpret_cast<const char *>(str));
+  if (init_result < 0) {
+    init_result = -init_result;
+  }
+  if (init_result < MIN_NORMAL && init_result != 0) {
+    return has_hex_prefix(str);
+  }
+  return false;
+}
+#else
+bool should_be_skipped(const uint8_t *) { return false; }
+#endif // LLVM_LIBC_FUZZER_GLIBC_HEX_SUBNORMAL_ERR
+
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   uint8_t *container = new uint8_t[size + 1];
   if (!container)
@@ -26,7 +61,10 @@
     container[i] = data[i];
   container[size] = '\0'; // Add null terminator to container.
 
-  StringParserOutputDiff<double>(&__llvm_libc::atof, &::atof, container, size);
+  if (!should_be_skipped(container)) {
+    StringParserOutputDiff<double>(&__llvm_libc::atof, &::atof, container,
+                                   size);
+  }
   delete[] container;
   return 0;
 }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D149359.517640.patch
Type: text/x-patch
Size: 1861 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libc-commits/attachments/20230427/806ebe6f/attachment.bin>


More information about the libc-commits mailing list