1 // RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage \ 2 // RUN: -verify %s 3 // RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage \ 4 // RUN: -verify %s -x objective-c++ 5 // RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage-in-libc-call \ 6 // RUN: -verify %s 7 8 typedef struct {} FILE; 9 void memcpy(); 10 void __asan_memcpy(); 11 void strcpy(); 12 void strcpy_s(); 13 void wcscpy_s(); 14 unsigned strlen( const char* str ); 15 int fprintf( FILE* stream, const char* format, ... ); 16 int printf( const char* format, ... ); 17 int sprintf( char* buffer, const char* format, ... ); 18 int swprintf( char* buffer, const char* format, ... ); 19 int snprintf( char* buffer, unsigned buf_size, const char* format, ... ); 20 int snwprintf( char* buffer, unsigned buf_size, const char* format, ... ); 21 int snwprintf_s( char* buffer, unsigned buf_size, const char* format, ... ); 22 int vsnprintf( char* buffer, unsigned buf_size, const char* format, ... ); 23 int sscanf_s(const char * buffer, const char * format, ...); 24 int sscanf(const char * buffer, const char * format, ... ); 25 int wprintf(const wchar_t* format, ... ); 26 int __asan_printf(); 27 28 namespace std { 29 template< class InputIt, class OutputIt > 30 OutputIt copy( InputIt first, InputIt last, 31 OutputIt d_first ); 32 33 struct iterator{}; 34 template<typename T> 35 struct span { 36 T * ptr; 37 T * data(); 38 unsigned size_bytes(); 39 unsigned size(); 40 iterator begin() const noexcept; 41 iterator end() const noexcept; 42 }; 43 44 template<typename T> 45 struct basic_string { 46 T* p; 47 T *c_str(); 48 T *data(); 49 unsigned size_bytes(); 50 }; 51 52 typedef basic_string<char> string; 53 typedef basic_string<wchar_t> wstring; 54 55 // C function under std: 56 void memcpy(); 57 void strcpy(); 58 } 59 60 void f(char * p, char * q, std::span<char> s, std::span<char> s2) { 61 typedef FILE * _Nullable aligned_file_ptr_t __attribute__((align_value(64))); 62 typedef char * _Nullable aligned_char_ptr_t __attribute__((align_value(64))); 63 aligned_file_ptr_t fp; 64 aligned_char_ptr_t cp; 65 66 memcpy(); // expected-warning{{function 'memcpy' is unsafe}} 67 std::memcpy(); // expected-warning{{function 'memcpy' is unsafe}} 68 __builtin_memcpy(p, q, 64); // expected-warning{{function '__builtin_memcpy' is unsafe}} 69 __builtin___memcpy_chk(p, q, 8, 64); // expected-warning{{function '__builtin___memcpy_chk' is unsafe}} 70 __asan_memcpy(); // expected-warning{{function '__asan_memcpy' is unsafe}} 71 strcpy(); // expected-warning{{function 'strcpy' is unsafe}} 72 std::strcpy(); // expected-warning{{function 'strcpy' is unsafe}} 73 strcpy_s(); // expected-warning{{function 'strcpy_s' is unsafe}} 74 wcscpy_s(); // expected-warning{{function 'wcscpy_s' is unsafe}} 75 76 /* Test printfs */ 77 fprintf((FILE*)p, "%s%d", p, *p); // expected-warning{{function 'fprintf' is unsafe}} expected-note{{string argument is not guaranteed to be null-terminated}} 78 printf("%s%d", // expected-warning{{function 'printf' is unsafe}} 79 p, // expected-note{{string argument is not guaranteed to be null-terminated}} note attached to the unsafe argument 80 *p); 81 printf(cp, p, *p); // expected-warning{{function 'printf' is unsafe}} // expected-note{{string argument is not guaranteed to be null-terminated}} 82 sprintf(q, "%s%d", "hello", *p); // expected-warning{{function 'sprintf' is unsafe}} expected-note{{change to 'snprintf' for explicit bounds checking}} 83 swprintf(q, "%s%d", "hello", *p); // expected-warning{{function 'swprintf' is unsafe}} expected-note{{change to 'snprintf' for explicit bounds checking}} 84 snprintf(q, 10, "%s%d", "hello", *p); // expected-warning{{function 'snprintf' is unsafe}} expected-note{{buffer pointer and size may not match}} 85 snprintf(cp, 10, "%s%d", "hello", *p); // expected-warning{{function 'snprintf' is unsafe}} expected-note{{buffer pointer and size may not match}} 86 snprintf(s.data(), s2.size(), "%s%d", "hello", *p); // expected-warning{{function 'snprintf' is unsafe}} expected-note{{buffer pointer and size may not match}} 87 snwprintf(s.data(), s2.size(), "%s%d", "hello", *p); // expected-warning{{function 'snwprintf' is unsafe}} expected-note{{buffer pointer and size may not match}} 88 snwprintf_s( // expected-warning{{function 'snwprintf_s' is unsafe}} 89 s.data(), // expected-note{{buffer pointer and size may not match}} // note attached to the buffer 90 s2.size(), 91 "%s%d", "hello", *p); 92 vsnprintf(s.data(), s.size_bytes(), "%s%d", "hello", *p); // expected-warning{{function 'vsnprintf' is unsafe}} expected-note{{'va_list' is unsafe}} 93 sscanf(p, "%s%d", "hello", *p); // expected-warning{{function 'sscanf' is unsafe}} 94 sscanf_s(p, "%s%d", "hello", *p); // expected-warning{{function 'sscanf_s' is unsafe}} 95 fprintf((FILE*)p, "%P%d%p%i hello world %32s", *p, *p, p, *p, p); // expected-warning{{function 'fprintf' is unsafe}} expected-note{{string argument is not guaranteed to be null-terminated}} 96 fprintf(fp, "%P%d%p%i hello world %32s", *p, *p, p, *p, p); // expected-warning{{function 'fprintf' is unsafe}} expected-note{{string argument is not guaranteed to be null-terminated}} 97 wprintf(L"hello %s", p); // expected-warning{{function 'wprintf' is unsafe}} expected-note{{string argument is not guaranteed to be null-terminated}} 98 99 100 char a[10], b[11]; 101 int c[10]; 102 std::wstring WS; 103 104 snprintf(a, sizeof(b), "%s", __PRETTY_FUNCTION__); // expected-warning{{function 'snprintf' is unsafe}} expected-note{{buffer pointer and size may not match}} 105 snprintf((char*)c, sizeof(c), "%s", __PRETTY_FUNCTION__); // expected-warning{{function 'snprintf' is unsafe}} expected-note{{buffer pointer and size may not match}} 106 fprintf((FILE*)p, "%P%d%p%i hello world %32s", *p, *p, p, *p, "hello"); // no warn 107 fprintf(fp, "%P%d%p%i hello world %32s", *p, *p, p, *p, "hello"); // no warn 108 printf("%s%d", "hello", *p); // no warn 109 snprintf(s.data(), s.size_bytes(), "%s%d", "hello", *p); // no warn 110 snprintf(s.data(), s.size_bytes(), "%s%d", __PRETTY_FUNCTION__, *p); // no warn 111 snwprintf(s.data(), s.size_bytes(), "%s%d", __PRETTY_FUNCTION__, *p); // no warn 112 snwprintf_s(s.data(), s.size_bytes(), "%s%d", __PRETTY_FUNCTION__, *p); // no warn 113 wprintf(L"hello %ls", L"world"); // no warn 114 wprintf(L"hello %ls", WS.c_str()); // no warn 115 strlen("hello");// no warn 116 __asan_printf();// a printf but no argument, so no warn 117 } 118 119 void safe_examples(std::string s1, int *p) { 120 snprintf(s1.data(), s1.size_bytes(), "%s%d%s%p%s", __PRETTY_FUNCTION__, *p, "hello", p, s1.c_str()); // no warn 121 snprintf(s1.data(), s1.size_bytes(), s1.c_str(), __PRETTY_FUNCTION__, *p, "hello", s1.c_str()); // no warn 122 printf("%s%d%s%p%s", __PRETTY_FUNCTION__, *p, "hello", p, s1.c_str()); // no warn 123 printf(s1.c_str(), __PRETTY_FUNCTION__, *p, "hello", s1.c_str()); // no warn 124 fprintf((FILE*)0, "%s%d%s%p%s", __PRETTY_FUNCTION__, *p, "hello", p, s1.c_str()); // no warn 125 fprintf((FILE*)0, s1.c_str(), __PRETTY_FUNCTION__, *p, "hello", s1.c_str()); // no warn 126 127 char a[10]; 128 129 snprintf(a, sizeof a, "%s%d%s%p%s", __PRETTY_FUNCTION__, *p, "hello", s1.c_str()); // no warn 130 snprintf(a, sizeof(decltype(a)), "%s%d%s%p%s", __PRETTY_FUNCTION__, *p, "hello", s1.c_str()); // no warn 131 snprintf(a, 10, "%s%d%s%p%s", __PRETTY_FUNCTION__, *p, "hello", s1.c_str()); // no warn 132 } 133 134 135 void g(char *begin, char *end, char *p, std::span<char> s) { 136 std::copy(begin, end, p); // no warn 137 std::copy(s.begin(), s.end(), s.begin()); // no warn 138 } 139 140 // warning gets turned off 141 void ff(char * p, char * q, std::span<char> s, std::span<char> s2) { 142 #pragma clang diagnostic push 143 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call" 144 memcpy(); 145 std::memcpy(); 146 __builtin_memcpy(p, q, 64); 147 __builtin___memcpy_chk(p, q, 8, 64); 148 __asan_memcpy(); 149 strcpy(); 150 std::strcpy(); 151 strcpy_s(); 152 wcscpy_s(); 153 #pragma clang diagnostic pop 154 } 155