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
6void path_sensitive_unknown_length(char *position, const char *src) {
7 int length;
8 length = strlen(src);
9 position = (char *)memchr(src, '\0', length);
10}
11
12void bad_memchr(char *position, const char *src) {
13 int length = strlen(src);
14 position = (char *)memchr(src, '\0', length);
15 // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: the length is too short to include the null terminator [bugprone-not-null-terminated-result]
16 // CHECK-FIXES: position = strchr(src, '\0');
17}
18
19void good_memchr(char *pos, const char *src) {
20 pos = strchr(src, '\0');
21}
22
23void bad_strerror_s(int errno) {
24 char dest[13];
25 int length = strlen(strerror(errno));
26 strerror_s(dest, length, errno);
27 // 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]
28 // CHECK-FIXES: char dest[14];
29 // CHECK-FIXES-NEXT: int length = strlen(strerror(errno));
30 // CHECK-FIXES-NEXT: strerror_s(dest, length + 1, errno);
31}
32
33void good_strerror_s(int errno) {
34 char dst[14];
35 int length = strlen(strerror(errno));
36 strerror_s(dst, length + 1, errno);
37}
38
39int bad_strncmp_1(char *str1, const char *str2) {
40 int length = strlen(str1) + 1;
41 return strncmp(str1, str2, length);
42 // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
43 // CHECK-FIXES: strncmp(str1, str2, length - 1);
44}
45
46int good_strncmp_1(char *str1, const char *str2) {
47 int length = strlen(str1) + 1;
48 return strncmp(str1, str2, length - 1);
49}
50
51int bad_strncmp_2(char *str2) {
52 return strncmp(str2, "foobar", (strlen("foobar") + 1));
53 // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
54 // CHECK-FIXES: strncmp(str2, "foobar", (strlen("foobar")));
55}
56
57int bad_strncmp_3(char *str3) {
58 return strncmp(str3, "foobar", 1 + strlen("foobar"));
59 // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: comparison length is too long and might lead to a buffer overflow [bugprone-not-null-terminated-result]
60 // CHECK-FIXES: strncmp(str3, "foobar", strlen("foobar"));
61}
62
63int good_strncmp_2_3(char *str) {
64 return strncmp(str, "foobar", strlen("foobar"));
65}
66
67void bad_strxfrm(const char *long_source_name) {
68 char long_destination_name[13];
69 int very_long_length_definition_name = strlen(long_source_name);
70 strxfrm(long_destination_name, long_source_name,
71 very_long_length_definition_name);
72 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: the result from calling 'strxfrm' is not null-terminated [bugprone-not-null-terminated-result]
73 // CHECK-FIXES: char long_destination_name[14];
74 // CHECK-FIXES-NEXT: int very_long_length_definition_name = strlen(long_source_name);
75 // CHECK-FIXES-NEXT: strxfrm(long_destination_name, long_source_name,
76 // CHECK-FIXES-NEXT: very_long_length_definition_name + 1);
77}
78
79void good_strxfrm(const char *long_source_name) {
80 char long_destination_name[14];
81 int very_long_length_definition_name = strlen(long_source_name);
82 strxfrm(long_destination_name, long_source_name,
83 very_long_length_definition_name + 1);
84}
85

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