//===-- strnlen_s_differential_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 // //===----------------------------------------------------------------------===// /// /// Differential fuzz test for llvm-libc strnlen_s implementation. /// //===----------------------------------------------------------------------===// #define __STDC_WANT_LIB_EXT1__ 1 #include "src/string/strnlen_s.h" #include #include extern "C" size_t LLVMFuzzerMutate(uint8_t *data, size_t size, size_t max_size); extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *data, size_t size, size_t max_size, unsigned int /*seed*/) { // The buffer is constructed as follows: // data = max_len (size_t) + null-terminated string if (max_size < sizeof(size_t) + 1) return size; do { size = LLVMFuzzerMutate(data, size, max_size); } while (size < sizeof(size_t) + 1); data[size - 1] = '\0'; return size; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < sizeof(size_t) + 1) return 0; size_t max_len; ::memcpy(&max_len, data, sizeof(size_t)); data += sizeof(size_t); // If Annex K is not available in the system's C library, we compare against // strnlen instead. We can assume this is valid because in the case where the // input string is not null, the two functions must have identical semantics. #ifdef __STDC_LIB_EXT1__ size_t ref = ::strnlen_s(reinterpret_cast(data), max_len); #else size_t ref = ::strnlen(reinterpret_cast(data), max_len); #endif size_t impl = LIBC_NAMESPACE::strnlen_s(reinterpret_cast(data), max_len); if (ref != impl) __builtin_trap(); return 0; }