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// FIXME: Something wrong with the APInt un/signed conversion on Windows:
5// in 'strncmp(str6, "string", 7);' it tries to inject '4294967302' as length.
6
7// UNSUPPORTED: system-windows
8
9#include "not-null-terminated-result-c.h"
10
11#define __STDC_LIB_EXT1__ 1
12#define __STDC_WANT_LIB_EXT1__ 1
13
14void bad_memchr_1(char *position, const char *src) {
15 position = (char *)memchr(src, '\0', strlen(src));
16 // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: the length is too short to include the null terminator [bugprone-not-null-terminated-result]
17 // CHECK-FIXES: position = strchr(src, '\0');
18}
19
20void good_memchr_1(char *pos, const char *src) {
21 pos = strchr(src, '\0');
22}
23
24void bad_memchr_2(char *position) {
25 position = (char *)memchr("foobar", '\0', 6);
26 // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: the length is too short to include the null terminator [bugprone-not-null-terminated-result]
27 // CHECK-FIXES: position = strchr("foobar", '\0');
28}
29
30void good_memchr_2(char *pos) {
31 pos = strchr("foobar", '\0');
32}
33
34void bad_memmove(const char *src) {
35 char dest[13];
36 memmove(dest, src, strlen(src));
37 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memmove' is not null-terminated [bugprone-not-null-terminated-result]
38 // CHECK-FIXES: char dest[14];
39 // CHECK-FIXES-NEXT: memmove_s(dest, 14, src, strlen(src) + 1);
40}
41
42void good_memmove(const char *src) {
43 char dst[14];
44 memmove_s(dst, 13, src, strlen(src) + 1);
45}
46
47void bad_memmove_s(char *dest, const char *src) {
48 memmove_s(dest, 13, src, strlen(src));
49 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'memmove_s' is not null-terminated [bugprone-not-null-terminated-result]
50 // CHECK-FIXES: memmove_s(dest, 13, src, strlen(src) + 1);
51}
52
53void good_memmove_s_1(char *dest, const char *src) {
54 memmove_s(dest, 13, src, strlen(src) + 1);
55}
56
57void bad_strerror_s(int errno) {
58 char dest[13];
59 strerror_s(dest, strlen(strerror(errno)), errno);
60 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'strerror_s' is not null-terminated and missing the last character of the error message [bugprone-not-null-terminated-result]
61 // CHECK-FIXES: char dest[14];
62 // CHECK-FIXES-NEXT: strerror_s(dest, strlen(strerror(errno)) + 1, errno);
63}
64
65void good_strerror_s(int errno) {
66 char dst[14];
67 strerror_s(dst, strlen(strerror(errno)) + 1, errno);
68}
69
70int bad_strncmp_1(char *str0, const char *str1) {
71 return strncmp(str0, str1, (strlen(str0) + 1));
72 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
73 // CHECK-FIXES: strncmp(str0, str1, (strlen(str0)));
74}
75
76int bad_strncmp_2(char *str2, const char *str3) {
77 return strncmp(str2, str3, 1 + strlen(str2));
78 // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
79 // CHECK-FIXES: strncmp(str2, str3, strlen(str2));
80}
81
82int good_strncmp_1_2(char *str4, const char *str5) {
83 return strncmp(str4, str5, strlen(str4));
84}
85
86int bad_strncmp_3(char *str6) {
87 return strncmp(str6, "string", 7);
88 // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
89 // CHECK-FIXES: strncmp(str6, "string", 6);
90}
91
92int good_strncmp_3(char *str7) {
93 return strncmp(str7, "string", 6);
94}
95
96void bad_strxfrm_1(const char *long_source_name) {
97 char long_destination_array_name[13];
98 strxfrm(long_destination_array_name, long_source_name,
99 strlen(long_source_name));
100 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: the result from calling 'strxfrm' is not null-terminated [bugprone-not-null-terminated-result]
101 // CHECK-FIXES: char long_destination_array_name[14];
102 // CHECK-FIXES-NEXT: strxfrm(long_destination_array_name, long_source_name,
103 // CHECK-FIXES-NEXT: strlen(long_source_name) + 1);
104}
105
106void good_strxfrm_1(const char *long_source_name) {
107 char long_destination_array_name[14];
108 strxfrm(long_destination_array_name, long_source_name,
109 strlen(long_source_name) + 1);
110}
111
112void bad_strxfrm_2() {
113 char long_destination_array_name1[16];
114 strxfrm(long_destination_array_name1, "long_source_name", 16);
115 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the result from calling 'strxfrm' is not null-terminated [bugprone-not-null-terminated-result]
116 // CHECK-FIXES: char long_destination_array_name1[17];
117 // CHECK-FIXES: strxfrm(long_destination_array_name1, "long_source_name", 17);
118}
119
120void good_strxfrm_2() {
121 char long_destination_array_name2[17];
122 strxfrm(long_destination_array_name2, "long_source_name", 17);
123}
124

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