[libc-commits] [PATCH] D82247: [libc] Add fuzz test for strcmp.

Chris Gyurgyik via Phabricator via libc-commits libc-commits at lists.llvm.org
Fri Jun 19 17:24:02 PDT 2020


cgyurgyik created this revision.
cgyurgyik added reviewers: sivachandra, PaulkaToast.
cgyurgyik added a project: libc-project.
Herald added subscribers: libc-commits, ecnelises, tschuett, mgorny.

Adds a fuzz test for string comparison.

This takes in two strings with associated lengths.
Verifies each string contains at least one character, and that the last character is the null terminator.
Then, finds the first instance where one of the following does not hold:

1. i < min(size1, size2)
2. s1[i] == s2[i]
3. s1[i] != '\0'

The result of strcmp is then compared to the value of the difference between s1[i] and s2[i]. For thoroughness, the operands are reversed and also checked.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D82247

Files:
  libc/fuzzing/string/CMakeLists.txt
  libc/fuzzing/string/strcmp_fuzz.cpp


Index: libc/fuzzing/string/strcmp_fuzz.cpp
===================================================================
--- /dev/null
+++ libc/fuzzing/string/strcmp_fuzz.cpp
@@ -0,0 +1,55 @@
+//===-- strcmp_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 strcmp implementation.
+///
+//===----------------------------------------------------------------------===//
+#include "src/string/strcmp.h"
+#include <algorithm>
+#include <stdint.h>
+
+extern "C" int LLVMFuzzerTestTwoInputs(const uint8_t *data1, size_t size1,
+                                       const uint8_t *data2, size_t size2) {
+  // Verify each data source contains at least one character.
+  if (!size1 || !size2)
+    return 0;
+  // Verify that the final character is the null terminator.
+  if (data1[size1 - 1] != '\0' || data2[size2 - 1] != '\0')
+    return 0;
+
+  const char *s1 = reinterpret_cast<const char *>(data1);
+  const char *s2 = reinterpret_cast<const char *>(data2);
+
+  const size_t minimum_size = std::min(size1, size2);
+
+  // Iterate through until either the minimum size is hit,
+  // a character is the null terminator, or the first set
+  // of differed bytes between s1 and s2 are found.
+  // No bytes following a null byte should be compared.
+  size_t i;
+  for (i = 0; i < minimum_size && s1[i] && s1[i] == s2[i]; ++i)
+    ;
+
+  int expected_result = s1[i] - s2[i];
+  int actual_result = __llvm_libc::strcmp(s1, s2);
+
+  // The expected result should be the difference between the first non-equal
+  // characters of s1 and s2. If all characters are equal, the expected result
+  // should be '\0' - '\0' = 0.
+  if (expected_result != actual_result)
+    __builtin_trap();
+
+  // Verify reversed operands. This should be the negated value of the previous
+  // result, except of course if the previous result was zero.
+  expected_result = s2[i] - s1[i];
+  actual_result = __llvm_libc::strcmp(s2, s1);
+  if (expected_result != actual_result)
+    __builtin_trap();
+
+  return 0;
+}
Index: libc/fuzzing/string/CMakeLists.txt
===================================================================
--- libc/fuzzing/string/CMakeLists.txt
+++ libc/fuzzing/string/CMakeLists.txt
@@ -7,3 +7,11 @@
     libc.src.string.strcpy
     libc.src.string.strlen
 )
+
+add_libc_fuzzer(
+  strcmp_fuzz
+  SRCS
+    strcmp_fuzz.cpp
+  DEPENDS
+    libc.src.string.strcmp
+)


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D82247.272215.patch
Type: text/x-patch
Size: 2705 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libc-commits/attachments/20200620/e646c850/attachment.bin>


More information about the libc-commits mailing list