114 lines · c
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,debug.ExprInspection -verify %s2// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,debug.ExprInspection -verify %s3// XFAIL: *4 5// This file is for tests that may eventually go into string.c, or may be6// deleted outright. At one point these tests passed, but only because we7// weren't correctly modelling the behavior of the relevant string functions.8// The tests aren't incorrect, but require the analyzer to be smarter about9// conjured values than it currently is.10 11//===----------------------------------------------------------------------===12// Declarations13//===----------------------------------------------------------------------===14 15// Some functions are so similar to each other that they follow the same code16// path, such as memcpy and __memcpy_chk, or memcmp and bcmp. If VARIANT is17// defined, make sure to use the variants instead to make sure they are still18// checked by the analyzer.19 20// Some functions are implemented as builtins. These should be #defined as21// BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined.22 23// Functions that have variants and are also available as builtins should be24// declared carefully! See memcpy() for an example.25 26#ifdef USE_BUILTINS27# define BUILTIN(f) __builtin_ ## f28#else /* USE_BUILTINS */29# define BUILTIN(f) f30#endif /* USE_BUILTINS */31 32#define NULL 033typedef typeof(sizeof(int)) size_t;34 35void clang_analyzer_eval(int);36 37//===----------------------------------------------------------------------===38// strnlen()39//===----------------------------------------------------------------------===40 41#define strnlen BUILTIN(strnlen)42size_t strnlen(const char *s, size_t maxlen);43 44void strnlen_liveness(const char *x) {45 if (strnlen(x, 10) < 5)46 return;47 clang_analyzer_eval(strnlen(x, 10) < 5); // expected-warning{{FALSE}}48}49 50void strnlen_subregion() {51 struct two_stringsn { char a[2], b[2]; };52 extern void use_two_stringsn(struct two_stringsn *);53 54 struct two_stringsn z;55 use_two_stringsn(&z);56 57 size_t a = strnlen(z.a, 10);58 z.b[0] = 5;59 size_t b = strnlen(z.a, 10);60 if (a == 0)61 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}62 63 use_two_stringsn(&z);64 65 size_t c = strnlen(z.a, 10);66 if (a == 0)67 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}68}69 70extern void use_stringn(char *);71void strnlen_argument(char *x) {72 size_t a = strnlen(x, 10);73 size_t b = strnlen(x, 10);74 if (a == 0)75 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}76 77 use_stringn(x);78 79 size_t c = strnlen(x, 10);80 if (a == 0)81 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}82}83 84extern char global_strn[];85void strnlen_global() {86 size_t a = strnlen(global_strn, 10);87 size_t b = strnlen(global_strn, 10);88 if (a == 0)89 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}90 91 // Call a function with unknown effects, which should invalidate globals.92 use_stringn(0);93 94 size_t c = strnlen(global_strn, 10);95 if (a == 0)96 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}97}98 99void strnlen_indirect(char *x) {100 size_t a = strnlen(x, 10);101 char *p = x;102 char **p2 = &p;103 size_t b = strnlen(x, 10);104 if (a == 0)105 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}106 107 extern void use_stringn_ptr(char*const*);108 use_stringn_ptr(p2);109 110 size_t c = strnlen(x, 10);111 if (a == 0)112 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}113}114