brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.9 KiB · 765dcbc Raw
251 lines · cpp
1// RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage \2// RUN:            -verify %s3// 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 %s7// RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage-in-libc-call \8// RUN:            -verify %s -DTEST_STD_NS9 10typedef struct {} FILE;11typedef unsigned int size_t;12 13#ifdef TEST_STD_NS14namespace std {15#endif16 17void memcpy();18void __asan_memcpy();19void strcpy();20void strcpy_s();21void wcscpy_s();22unsigned strlen( const char* str );23int fprintf( FILE* stream, const char* format, ... );24int printf( const char* format, ... );25int sprintf( char* buffer, const char* format, ... );26int swprintf( char* buffer, const char* format, ... );27int snprintf( char* buffer, unsigned buf_size, const char* format, ... );28int snwprintf( char* buffer, unsigned buf_size, const char* format, ... );29int snwprintf_s( char* buffer, unsigned buf_size, const char* format, ... );30int vsnprintf( char* buffer, unsigned buf_size, const char* format, ... );31int sscanf_s(const char * buffer, const char * format, ...);32int sscanf(const char * buffer, const char * format, ... );33int wprintf(const wchar_t* format, ... );34int __asan_printf();35 36#ifdef TEST_STD_NS37} //namespace std38using namespace std;39#endif40 41namespace std {42  template< class InputIt, class OutputIt >43  OutputIt copy( InputIt first, InputIt last,44		 OutputIt d_first );45 46  struct iterator{};47  template<typename T>48  struct span {49    T * ptr;50    T * data();51    unsigned size_bytes();52    unsigned size();53    iterator begin() const noexcept;54    iterator end() const noexcept;55  };56 57  template<typename T>58  struct basic_string {59    T* p;60    T *c_str();61    T *data();62    unsigned size_bytes();63    unsigned size();64  };65 66  typedef basic_string<char> string;67  typedef basic_string<wchar_t> wstring;68 69  template<typename T>70  struct basic_string_view {71    T *c_str() const noexcept;72    T *data()  const noexcept;73    unsigned size();74    const T* begin() const noexcept;75    const T* end() const noexcept;76  };77 78  typedef basic_string_view<char> string_view;79  typedef basic_string_view<wchar_t> wstring_view;80}81 82void f(char * p, char * q, std::span<char> s, std::span<char> s2) {83  typedef FILE * _Nullable aligned_file_ptr_t __attribute__((align_value(64)));84  typedef char * _Nullable aligned_char_ptr_t __attribute__((align_value(64)));85  aligned_file_ptr_t fp;86  aligned_char_ptr_t cp;87 88  memcpy();                   // expected-warning{{function 'memcpy' is unsafe}}89  __builtin_memcpy(p, q, 64); // expected-warning{{function '__builtin_memcpy' is unsafe}}90  __builtin___memcpy_chk(p, q, 8, 64);  // expected-warning{{function '__builtin___memcpy_chk' is unsafe}}91  __asan_memcpy();                      // expected-warning{{function '__asan_memcpy' is unsafe}}92  strcpy();                   // expected-warning{{function 'strcpy' is unsafe}}93  strcpy_s();                 // expected-warning{{function 'strcpy_s' is unsafe}}94  wcscpy_s();                 // expected-warning{{function 'wcscpy_s' is unsafe}}95#ifdef TEST_STD_NS96  std::strcpy();              // expected-warning{{function 'strcpy' is unsafe}}97  std::memcpy();              // expected-warning{{function 'memcpy' is unsafe}}98#endif99 100  /* Test printfs */101  fprintf((FILE*)p, "%s%d", p, *p);  // expected-warning{{function 'fprintf' is unsafe}} expected-note{{string argument is not guaranteed to be null-terminated}}102  printf("%s%d", // expected-warning{{function 'printf' is unsafe}}103	 p,    // expected-note{{string argument is not guaranteed to be null-terminated}} note attached to the unsafe argument104	 *p);105  printf(cp, p, *p); // expected-warning{{function 'printf' is unsafe}} // expected-note{{string argument is not guaranteed to be null-terminated}}106  sprintf(q, "%s%d", "hello", *p); // expected-warning{{function 'sprintf' is unsafe}} expected-note{{change to 'snprintf' for explicit bounds checking}}107  swprintf(q, "%s%d", "hello", *p); // expected-warning{{function 'swprintf' is unsafe}} expected-note{{change to 'snprintf' for explicit bounds checking}}108  snprintf(q, 10, "%s%d", "hello", *p); // expected-warning{{function 'snprintf' is unsafe}} expected-note{{buffer pointer and size may not match}}109  snprintf(cp, 10, "%s%d", "hello", *p); // expected-warning{{function 'snprintf' is unsafe}} expected-note{{buffer pointer and size may not match}}110  snprintf(s.data(), s2.size(), "%s%d", "hello", *p); // expected-warning{{function 'snprintf' is unsafe}} expected-note{{buffer pointer and size may not match}}111  snwprintf(s.data(), s2.size(), "%s%d", "hello", *p); // expected-warning{{function 'snwprintf' is unsafe}} expected-note{{buffer pointer and size may not match}}112  snwprintf_s(                      // expected-warning{{function 'snwprintf_s' is unsafe}}113	      s.data(),             // expected-note{{buffer pointer and size may not match}} // note attached to the buffer114	      s2.size(),115	      "%s%d", "hello", *p);116  vsnprintf(s.data(), s.size_bytes(), "%s%d", "hello", *p); // expected-warning{{function 'vsnprintf' is unsafe}} expected-note{{'va_list' is unsafe}}117  sscanf(p, "%s%d", "hello", *p);    // expected-warning{{function 'sscanf' is unsafe}}118  sscanf_s(p, "%s%d", "hello", *p);  // expected-warning{{function 'sscanf_s' is unsafe}}119  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}}120  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}}121  wprintf(L"hello %s", p); // expected-warning{{function 'wprintf' is unsafe}} expected-note{{string argument is not guaranteed to be null-terminated}}122 123 124  char a[10], b[11];125  int c[10];126  std::wstring WS;127 128  snprintf(a, sizeof(b), "%s", __PRETTY_FUNCTION__);         // expected-warning{{function 'snprintf' is unsafe}} expected-note{{buffer pointer and size may not match}}129  snprintf((char*)c, sizeof(c), "%s", __PRETTY_FUNCTION__);  // expected-warning{{function 'snprintf' is unsafe}} expected-note{{buffer pointer and size may not match}}130  fprintf((FILE*)p, "%P%d%p%i hello world %32s", *p, *p, p, *p, "hello"); // no warn131  fprintf(fp, "%P%d%p%i hello world %32s", *p, *p, p, *p, "hello"); // no warn132  printf("%s%d", "hello", *p); // no warn133  snprintf(s.data(), s.size_bytes(), "%s%d", "hello", *p); // no warn134  snprintf(s.data(), s.size_bytes(), "%s%d", __PRETTY_FUNCTION__, *p); // no warn135  snwprintf(s.data(), s.size_bytes(), "%s%d", __PRETTY_FUNCTION__, *p); // no warn136  snwprintf_s(s.data(), s.size_bytes(), "%s%d", __PRETTY_FUNCTION__, *p); // no warn137  wprintf(L"hello %ls", L"world"); // no warn138  wprintf(L"hello %ls", WS.c_str()); // no warn139  strlen("hello");// no warn140  __asan_printf();// a printf but no argument, so no warn141}142 143void safe_examples(std::string s1, int *p) {144  snprintf(s1.data(), s1.size_bytes(), "%s%d%s%p%s", __PRETTY_FUNCTION__, *p, "hello", p, s1.c_str()); // no warn145  snprintf(s1.data(), s1.size_bytes(), s1.c_str(), __PRETTY_FUNCTION__, *p, "hello", s1.c_str());      // no warn146  printf("%s%d%s%p%s", __PRETTY_FUNCTION__, *p, "hello", p, s1.c_str());              // no warn147  printf(s1.c_str(), __PRETTY_FUNCTION__, *p, "hello", s1.c_str());                   // no warn148  fprintf((FILE*)0, "%s%d%s%p%s", __PRETTY_FUNCTION__, *p, "hello", p, s1.c_str());   // no warn149  fprintf((FILE*)0, s1.c_str(), __PRETTY_FUNCTION__, *p, "hello", s1.c_str());        // no warn150 151  char a[10];152  char c = 'c';153 154  snprintf(a, sizeof a, "%s%d%s%p%s", __PRETTY_FUNCTION__, *p, "hello", s1.c_str());         // no warn155  snprintf(a, sizeof(decltype(a)), "%s%d%s%p%s", __PRETTY_FUNCTION__, *p, "hello", s1.c_str());          // no warn156  snprintf(a, 10, "%s%d%s%p%s", __PRETTY_FUNCTION__, *p, "hello", s1.c_str());                // no warn157  snprintf(&c, 1, "%s%d%s%p%s", __PRETTY_FUNCTION__, *p, "hello", s1.c_str());                // no warn158  snprintf(nullptr, 0, "%s%d%s%p%s", __PRETTY_FUNCTION__, *p, "hello", s1.c_str());           // no warn159}160 161void test_sarg_precision(std::string Str, std::string_view Sv, std::wstring_view WSv,162			 std::span<char> SpC, std::span<int> SpI) {163  printf("%.*s");164  printf("%.*s", (int)Str.size(), Str.data());165  printf("%.*s", (int)Str.size_bytes(), Str.data());166  printf("%.*s", (int)Sv.size(), Sv.data());167  printf("%.*s", (int)SpC.size(), SpC.data());168  printf("%.*s", SpC.size(), SpC.data());169  printf("%.*ls", WSv.size(), WSv.data());170  printf("%.*s", SpC.data());  // no warn because `SpC.data()` is passed to the precision while the actually string pointer is not given171 172  printf("%.*s", SpI.size(), SpI.data()); // expected-warning {{function 'printf' is unsafe}} expected-note{{string argument is not guaranteed to be null-terminated}}173  printf("%.*s", SpI.size(), SpC.data()); // expected-warning {{function 'printf' is unsafe}} expected-note{{string argument is not guaranteed to be null-terminated}}174  printf("%.*s", WSv.size(), WSv.data()); // expected-warning {{function 'printf' is unsafe}} expected-note{{string argument is not guaranteed to be null-terminated}}175 176  char a[10];177  int  b[10];178 179  printf("%.10s", a);180  printf("%.11s", a); // expected-warning {{function 'printf' is unsafe}} expected-note{{string argument is not guaranteed to be null-terminated}}181  printf("%.10s", b); // expected-warning {{function 'printf' is unsafe}} expected-note{{string argument is not guaranteed to be null-terminated}}182}183 184 185void g(char *begin, char *end, char *p, std::span<char> s) {186  std::copy(begin, end, p); // no warn187  std::copy(s.begin(), s.end(), s.begin()); // no warn188}189 190// warning gets turned off191void ff(char * p, char * q, std::span<char> s, std::span<char> s2) {192#pragma clang diagnostic push193#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"194  memcpy();195  __builtin_memcpy(p, q, 64);196  __builtin___memcpy_chk(p, q, 8, 64);197  __asan_memcpy();198  strcpy();199#ifdef TEST_STD_NS200  std::strcpy();201  std::memcpy();202#endif203  strcpy_s();204  wcscpy_s();205#pragma clang diagnostic pop206}207 208 209 210// functions not in global scope or std:: namespace are not libc211// functions regardless of their names:212struct StrBuff213{214  void strcpy();215  void strcpy(char* dst);216  void memcpy(void *dst, const void *src, size_t size);217};218 219namespace NS {220  void strcpy();221  void strcpy(char* dst);222  void memcpy(void *dst, const void *src, size_t size);223}224 225namespace std {226  // class methods even in std namespace cannot be libc functions:227  struct LibC228  {229    void strcpy();230    void strcpy(char* dst);231    void memcpy(void *dst, const void *src, size_t size);232  };233}234 235void test(StrBuff& str)236{237  char buff[64];238  str.strcpy();239  str.strcpy(buff);240  str.memcpy(buff, buff, 64);241  NS::strcpy();242  NS::strcpy(buff);243  NS::memcpy(buff, buff, 64);244 245  std::LibC LibC;246 247  LibC.strcpy();248  LibC.strcpy(buff);249  LibC.memcpy(buff, buff, 64);250}251