1*5540765bScgyurgyik //===-- strcmp_fuzz.cpp ---------------------------------------------------===//
2*5540765bScgyurgyik //
3*5540765bScgyurgyik // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*5540765bScgyurgyik // See https://llvm.org/LICENSE.txt for license information.
5*5540765bScgyurgyik // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*5540765bScgyurgyik //
7*5540765bScgyurgyik //===----------------------------------------------------------------------===//
8*5540765bScgyurgyik ///
9*5540765bScgyurgyik /// Fuzzing test for llvm-libc strcmp implementation.
10*5540765bScgyurgyik ///
11*5540765bScgyurgyik //===----------------------------------------------------------------------===//
12*5540765bScgyurgyik #include "src/string/strcmp.h"
13*5540765bScgyurgyik #include <algorithm>
14*5540765bScgyurgyik #include <stdint.h>
15*5540765bScgyurgyik 
16*5540765bScgyurgyik extern "C" int LLVMFuzzerTestTwoInputs(const uint8_t *data1, size_t size1,
17*5540765bScgyurgyik                                        const uint8_t *data2, size_t size2) {
18*5540765bScgyurgyik   // Verify each data source contains at least one character.
19*5540765bScgyurgyik   if (!size1 || !size2)
20*5540765bScgyurgyik     return 0;
21*5540765bScgyurgyik   // Verify that the final character is the null terminator.
22*5540765bScgyurgyik   if (data1[size1 - 1] != '\0' || data2[size2 - 1] != '\0')
23*5540765bScgyurgyik     return 0;
24*5540765bScgyurgyik 
25*5540765bScgyurgyik   const char *s1 = reinterpret_cast<const char *>(data1);
26*5540765bScgyurgyik   const char *s2 = reinterpret_cast<const char *>(data2);
27*5540765bScgyurgyik 
28*5540765bScgyurgyik   const size_t minimum_size = std::min(size1, size2);
29*5540765bScgyurgyik 
30*5540765bScgyurgyik   // Iterate through until either the minimum size is hit,
31*5540765bScgyurgyik   // a character is the null terminator, or the first set
32*5540765bScgyurgyik   // of differed bytes between s1 and s2 are found.
33*5540765bScgyurgyik   // No bytes following a null byte should be compared.
34*5540765bScgyurgyik   size_t i;
35*5540765bScgyurgyik   for (i = 0; i < minimum_size && s1[i] && s1[i] == s2[i]; ++i)
36*5540765bScgyurgyik     ;
37*5540765bScgyurgyik 
38*5540765bScgyurgyik   int expected_result = s1[i] - s2[i];
39*5540765bScgyurgyik   int actual_result = __llvm_libc::strcmp(s1, s2);
40*5540765bScgyurgyik 
41*5540765bScgyurgyik   // The expected result should be the difference between the first non-equal
42*5540765bScgyurgyik   // characters of s1 and s2. If all characters are equal, the expected result
43*5540765bScgyurgyik   // should be '\0' - '\0' = 0.
44*5540765bScgyurgyik   if (expected_result != actual_result)
45*5540765bScgyurgyik     __builtin_trap();
46*5540765bScgyurgyik 
47*5540765bScgyurgyik   // Verify reversed operands. This should be the negated value of the previous
48*5540765bScgyurgyik   // result, except of course if the previous result was zero.
49*5540765bScgyurgyik   expected_result = s2[i] - s1[i];
50*5540765bScgyurgyik   actual_result = __llvm_libc::strcmp(s2, s1);
51*5540765bScgyurgyik   if (expected_result != actual_result)
52*5540765bScgyurgyik     __builtin_trap();
53*5540765bScgyurgyik 
54*5540765bScgyurgyik   return 0;
55*5540765bScgyurgyik }
56