15540765bScgyurgyik //===-- strcmp_fuzz.cpp ---------------------------------------------------===//
25540765bScgyurgyik //
35540765bScgyurgyik // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45540765bScgyurgyik // See https://llvm.org/LICENSE.txt for license information.
55540765bScgyurgyik // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65540765bScgyurgyik //
75540765bScgyurgyik //===----------------------------------------------------------------------===//
85540765bScgyurgyik ///
95540765bScgyurgyik /// Fuzzing test for llvm-libc strcmp implementation.
105540765bScgyurgyik ///
115540765bScgyurgyik //===----------------------------------------------------------------------===//
125540765bScgyurgyik #include "src/string/strcmp.h"
13*f1c67192SSimon Pilgrim #include <stddef.h>
145540765bScgyurgyik #include <stdint.h>
155540765bScgyurgyik 
165540765bScgyurgyik extern "C" int LLVMFuzzerTestTwoInputs(const uint8_t *data1, size_t size1,
175540765bScgyurgyik                                        const uint8_t *data2, size_t size2) {
185540765bScgyurgyik   // Verify each data source contains at least one character.
195540765bScgyurgyik   if (!size1 || !size2)
205540765bScgyurgyik     return 0;
215540765bScgyurgyik   // Verify that the final character is the null terminator.
225540765bScgyurgyik   if (data1[size1 - 1] != '\0' || data2[size2 - 1] != '\0')
235540765bScgyurgyik     return 0;
245540765bScgyurgyik 
255540765bScgyurgyik   const char *s1 = reinterpret_cast<const char *>(data1);
265540765bScgyurgyik   const char *s2 = reinterpret_cast<const char *>(data2);
275540765bScgyurgyik 
284ffe2b24Scgyurgyik   const size_t minimum_size = size1 < size2 ? size1 : size2;
295540765bScgyurgyik 
305540765bScgyurgyik   // Iterate through until either the minimum size is hit,
315540765bScgyurgyik   // a character is the null terminator, or the first set
325540765bScgyurgyik   // of differed bytes between s1 and s2 are found.
335540765bScgyurgyik   // No bytes following a null byte should be compared.
345540765bScgyurgyik   size_t i;
354ffe2b24Scgyurgyik   for (i = 0; i < minimum_size; ++i) {
364ffe2b24Scgyurgyik     if (!s1[i] || s1[i] != s2[i])
374ffe2b24Scgyurgyik       break;
384ffe2b24Scgyurgyik   }
395540765bScgyurgyik 
405540765bScgyurgyik   int expected_result = s1[i] - s2[i];
415540765bScgyurgyik   int actual_result = __llvm_libc::strcmp(s1, s2);
425540765bScgyurgyik 
435540765bScgyurgyik   // The expected result should be the difference between the first non-equal
445540765bScgyurgyik   // characters of s1 and s2. If all characters are equal, the expected result
455540765bScgyurgyik   // should be '\0' - '\0' = 0.
465540765bScgyurgyik   if (expected_result != actual_result)
475540765bScgyurgyik     __builtin_trap();
485540765bScgyurgyik 
495540765bScgyurgyik   // Verify reversed operands. This should be the negated value of the previous
505540765bScgyurgyik   // result, except of course if the previous result was zero.
515540765bScgyurgyik   expected_result = s2[i] - s1[i];
525540765bScgyurgyik   actual_result = __llvm_libc::strcmp(s2, s1);
535540765bScgyurgyik   if (expected_result != actual_result)
545540765bScgyurgyik     __builtin_trap();
555540765bScgyurgyik 
565540765bScgyurgyik   return 0;
575540765bScgyurgyik }
58