| 1 | // RUN: %check_clang_tidy --match-partial-fixes %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 | |
| 14 | void 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 | |
| 20 | void good_memchr_1(char *pos, const char *src) { |
| 21 | pos = strchr(src, '\0'); |
| 22 | } |
| 23 | |
| 24 | void 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 | |
| 30 | void good_memchr_2(char *pos) { |
| 31 | pos = strchr("foobar" , '\0'); |
| 32 | } |
| 33 | |
| 34 | void 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 | |
| 42 | void good_memmove(const char *src) { |
| 43 | char dst[14]; |
| 44 | memmove_s(dst, 13, src, strlen(src) + 1); |
| 45 | } |
| 46 | |
| 47 | void 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 | |
| 53 | void good_memmove_s_1(char *dest, const char *src) { |
| 54 | memmove_s(dest, 13, src, strlen(src) + 1); |
| 55 | } |
| 56 | |
| 57 | void 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 | |
| 65 | void good_strerror_s(int errno) { |
| 66 | char dst[14]; |
| 67 | strerror_s(dst, strlen(strerror(errno)) + 1, errno); |
| 68 | } |
| 69 | |
| 70 | int 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 | |
| 76 | int 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 | |
| 82 | int good_strncmp_1_2(char *str4, const char *str5) { |
| 83 | return strncmp(str4, str5, strlen(str4)); |
| 84 | } |
| 85 | |
| 86 | int 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 | |
| 92 | int good_strncmp_3(char *str7) { |
| 93 | return strncmp(str7, "string" , 6); |
| 94 | } |
| 95 | |
| 96 | void 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 | |
| 106 | void 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 | |
| 112 | void 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 | |
| 120 | void good_strxfrm_2() { |
| 121 | char long_destination_array_name2[17]; |
| 122 | strxfrm(long_destination_array_name2, "long_source_name" , 17); |
| 123 | } |
| 124 | |