Skip to content

Commit 1ee93ac

Browse files
authored
[libc] Add memcmp / bcmp fuzzers (#77741)
1 parent 77f2ccb commit 1ee93ac

File tree

4 files changed

+129
-0
lines changed

4 files changed

+129
-0
lines changed

libc/fuzzing/string/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,19 @@ add_libc_fuzzer(
2424
libc.src.string.strstr
2525
libc.src.string.strlen
2626
)
27+
28+
add_libc_fuzzer(
29+
memcmp_fuzz
30+
SRCS
31+
memcmp_fuzz.cpp
32+
DEPENDS
33+
libc.src.string.memcmp
34+
)
35+
36+
add_libc_fuzzer(
37+
bcmp_fuzz
38+
SRCS
39+
bcmp_fuzz.cpp
40+
DEPENDS
41+
libc.src.string.bcmp
42+
)

libc/fuzzing/string/bcmp_fuzz.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//===-- bcmp_fuzz.cpp ---------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
///
9+
/// Fuzzing test for llvm-libc bcmp implementation.
10+
///
11+
//===----------------------------------------------------------------------===//
12+
#include "src/string/bcmp.h"
13+
#include <stddef.h>
14+
#include <stdint.h>
15+
#include <stdio.h>
16+
#include <string.h>
17+
18+
static int reference_bcmp(const void *pa, const void *pb, size_t count)
19+
__attribute__((no_builtin)) {
20+
const auto *a = reinterpret_cast<const unsigned char *>(pa);
21+
const auto *b = reinterpret_cast<const unsigned char *>(pb);
22+
for (size_t i = 0; i < count; ++i, ++a, ++b)
23+
if (*a != *b)
24+
return 1;
25+
return 0;
26+
}
27+
28+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
29+
const auto normalize = [](int value) -> int {
30+
if (value == 0)
31+
return 0;
32+
return 1;
33+
};
34+
// We ignore the last byte is size is odd.
35+
const auto count = size / 2;
36+
const char *a = reinterpret_cast<const char *>(data);
37+
const char *b = reinterpret_cast<const char *>(data) + count;
38+
const int actual = LIBC_NAMESPACE::bcmp(a, b, count);
39+
const int reference = reference_bcmp(a, b, count);
40+
if (normalize(actual) == normalize(reference))
41+
return 0;
42+
const auto print = [](const char *msg, const char *buffer, size_t size) {
43+
printf("%s\"", msg);
44+
for (size_t i = 0; i < size; ++i)
45+
printf("\\x%02x", (uint8_t)buffer[i]);
46+
printf("\"\n");
47+
};
48+
printf("count : %zu\n", count);
49+
print("a : ", a, count);
50+
print("b : ", b, count);
51+
printf("expected : %d\n", reference);
52+
printf("actual : %d\n", actual);
53+
__builtin_trap();
54+
}

libc/fuzzing/string/memcmp_fuzz.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//===-- memcmp_fuzz.cpp ---------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
///
9+
/// Fuzzing test for llvm-libc memcmp implementation.
10+
///
11+
//===----------------------------------------------------------------------===//
12+
#include "src/string/memcmp.h"
13+
#include <stddef.h>
14+
#include <stdint.h>
15+
#include <stdio.h>
16+
#include <string.h>
17+
18+
static int reference_memcmp(const void *pa, const void *pb, size_t count)
19+
__attribute__((no_builtin)) {
20+
const auto *a = reinterpret_cast<const unsigned char *>(pa);
21+
const auto *b = reinterpret_cast<const unsigned char *>(pb);
22+
for (size_t i = 0; i < count; ++i, ++a, ++b) {
23+
if (*a < *b)
24+
return -1;
25+
else if (*a > *b)
26+
return 1;
27+
}
28+
return 0;
29+
}
30+
31+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
32+
const auto sign = [](int value) -> int {
33+
if (value < 0)
34+
return -1;
35+
if (value > 0)
36+
return 1;
37+
return 0;
38+
};
39+
// We ignore the last byte is size is odd.
40+
const auto count = size / 2;
41+
const char *a = reinterpret_cast<const char *>(data);
42+
const char *b = reinterpret_cast<const char *>(data) + count;
43+
const int actual = LIBC_NAMESPACE::memcmp(a, b, count);
44+
const int reference = reference_memcmp(a, b, count);
45+
if (sign(actual) == sign(reference))
46+
return 0;
47+
const auto print = [](const char *msg, const char *buffer, size_t size) {
48+
printf("%s\"", msg);
49+
for (size_t i = 0; i < size; ++i)
50+
printf("\\x%02x", (uint8_t)buffer[i]);
51+
printf("\"\n");
52+
};
53+
printf("count : %zu\n", count);
54+
print("a : ", a, count);
55+
print("b : ", b, count);
56+
printf("expected : %d\n", reference);
57+
printf("actual : %d\n", actual);
58+
__builtin_trap();
59+
}
Binary file not shown.

0 commit comments

Comments
 (0)