1// RUN: %check_clang_tidy %s bugprone-not-null-terminated-result %t -- \
2// RUN: -- -std=c11 -I %S/Inputs/not-null-terminated-result
3
4#include "not-null-terminated-result-c.h"
5
6#define __STDC_LIB_EXT1__ 1
7#define __STDC_WANT_LIB_EXT1__ 1
8
9#define SRC_LENGTH 3
10#define SRC "foo"
11
12//===----------------------------------------------------------------------===//
13// False positive suppression.
14//===----------------------------------------------------------------------===//
15
16void good_memcpy_known_src(void) {
17 char dest[13];
18 char src[] = "foobar";
19 memcpy(dest, src, sizeof(src));
20}
21
22void good_memcpy_null_terminated(const char *src) {
23 char dest[13];
24 const int length = strlen(src);
25 memcpy(dest, src, length);
26 dest[length] = '\0';
27}
28
29void good_memcpy_proper_length(const char *src) {
30 char *dest = 0;
31 int length = strlen(src) + 1;
32 dest = (char *)malloc(length);
33 memcpy(dest, src, length);
34}
35
36void may_bad_memcpy_unknown_length(const char *src, int length) {
37 char dest[13];
38 memcpy(dest, src, length);
39}
40
41void may_bad_memcpy_const_length(const char *src) {
42 char dest[13];
43 memcpy(dest, src, 12);
44}
45
46//===----------------------------------------------------------------------===//
47// Special cases.
48//===----------------------------------------------------------------------===//
49
50void bad_memcpy_unknown_dest(char *dest01, const char *src) {
51 memcpy(dest01, src, strlen(src));
52 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
53 // CHECK-FIXES: strcpy(dest01, src);
54}
55
56void good_memcpy_unknown_dest(char *dst01, const char *src) {
57 strcpy(dst01, src);
58}
59
60void bad_memcpy_variable_array(int dest_length) {
61 char dest02[dest_length + 1];
62 memcpy(dest02, "foobarbazqux", strlen("foobarbazqux"));
63 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
64 // CHECK-FIXES: strcpy(dest02, "foobarbazqux");
65}
66
67void good_memcpy_variable_array(int dest_length) {
68 char dst02[dest_length + 1];
69 strcpy(dst02, "foobarbazqux");
70}
71
72void bad_memcpy_equal_src_length_and_length(void) {
73 char dest03[13];
74 const char *src = "foobarbazqux";
75 memcpy(dest03, src, 12);
76 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
77 // CHECK-FIXES: strcpy(dest03, src);
78}
79
80void good_memcpy_equal_src_length_and_length(void) {
81 char dst03[13];
82 const char *src = "foobarbazqux";
83 strcpy(dst03, src);
84}
85
86void bad_memcpy_dest_size_overflows(const char *src) {
87 const int length = strlen(src);
88 char *dest04 = (char *)malloc(length);
89 memcpy(dest04, src, length);
90 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
91 // CHECK-FIXES: char *dest04 = (char *)malloc(length + 1);
92 // CHECK-FIXES-NEXT: strcpy(dest04, src);
93}
94
95void good_memcpy_dest_size_overflows(const char *src) {
96 const int length = strlen(src);
97 char *dst04 = (char *)malloc(length + 1);
98 strcpy(dst04, src);
99}
100
101void bad_memcpy_macro(void) {
102 char dest05[SRC_LENGTH];
103 memcpy(dest05, SRC, SRC_LENGTH);
104 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memcpy' is not null-terminated [bugprone-not-null-terminated-result]
105 // CHECK-FIXES: char dest05[SRC_LENGTH + 1];
106 // CHECK-FIXES-NEXT: strcpy(dest05, SRC);
107}
108
109void good_memcpy_macro(void) {
110 char dst05[SRC_LENGTH + 1];
111 strcpy(dst05, SRC);
112}
113

source code of clang-tools-extra/test/clang-tidy/checkers/bugprone/not-null-terminated-result-memcpy-safe-other.c