brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.5 KiB · 0b817dd Raw
373 lines · c
1// Check the basic reporting/warning and the application of constraints.2// RUN: %clang_analyze_cc1 %s \3// RUN:   -analyzer-checker=core \4// RUN:   -analyzer-checker=unix.StdCLibraryFunctions \5// RUN:   -analyzer-config unix.StdCLibraryFunctions:ModelPOSIX=true \6// RUN:   -analyzer-checker=debug.StdCLibraryFunctionsTester \7// RUN:   -analyzer-checker=debug.ExprInspection \8// RUN:   -triple x86_64-unknown-linux-gnu \9// RUN:   -verify=report10 11// Check the bugpath related to the reports.12// RUN: %clang_analyze_cc1 %s \13// RUN:   -analyzer-checker=core \14// RUN:   -analyzer-checker=unix.StdCLibraryFunctions \15// RUN:   -analyzer-config unix.StdCLibraryFunctions:ModelPOSIX=true \16// RUN:   -analyzer-checker=debug.StdCLibraryFunctionsTester \17// RUN:   -analyzer-checker=debug.ExprInspection \18// RUN:   -triple x86_64-unknown-linux-gnu \19// RUN:   -analyzer-output=text \20// RUN:   -verify=bugpath21 22#include "Inputs/std-c-library-functions-POSIX.h"23 24void clang_analyzer_eval(int);25void clang_analyzer_warnIfReached();26 27int glob;28 29void test_alnum_concrete(int v) {30  int ret = isalnum(256); // \31  // report-warning{{The 1st argument to 'isalnum' is 256 but should be an unsigned char value or EOF}} \32  // bugpath-warning{{The 1st argument to 'isalnum' is 256 but should be an unsigned char value or EOF}} \33  // bugpath-note{{The 1st argument to 'isalnum' is 256 but should be an unsigned char value or EOF}}34  (void)ret;35}36 37void test_alnum_symbolic(int x) {38  int ret = isalnum(x);39  (void)ret;40 41  clang_analyzer_eval(EOF <= x && x <= 255); // \42  // report-warning{{TRUE}} \43  // bugpath-warning{{TRUE}} \44  // bugpath-note{{TRUE}} \45  // bugpath-note{{Left side of '&&' is true}} \46  // bugpath-note{{'x' is <= 255}}47}48 49void test_alnum_symbolic2(int x) {50  if (x > 255) { // \51    // bugpath-note{{Assuming 'x' is > 255}} \52    // bugpath-note{{Taking true branch}}53 54    int ret = isalnum(x); // \55    // report-warning{{The 1st argument to 'isalnum' is >= 256 but should be an unsigned char value or EOF}} \56    // bugpath-warning{{The 1st argument to 'isalnum' is >= 256 but should be an unsigned char value or EOF}} \57    // bugpath-note{{The 1st argument to 'isalnum' is >= 256 but should be an unsigned char value or EOF}}58 59    (void)ret;60  }61}62 63void test_toupper_concrete(int v) {64  int ret = toupper(256); // \65  // report-warning{{The 1st argument to 'toupper' is 256 but should be an unsigned char value or EOF}} \66  // bugpath-warning{{The 1st argument to 'toupper' is 256 but should be an unsigned char value or EOF}} \67  // bugpath-note{{The 1st argument to 'toupper' is 256 but should be an unsigned char value or EOF}}68  (void)ret;69}70 71void test_toupper_symbolic(int x) {72  int ret = toupper(x);73  (void)ret;74 75  clang_analyzer_eval(EOF <= x && x <= 255); // \76  // report-warning{{TRUE}} \77  // bugpath-warning{{TRUE}} \78  // bugpath-note{{TRUE}} \79  // bugpath-note{{Left side of '&&' is true}} \80  // bugpath-note{{'x' is <= 255}}81}82 83void test_toupper_symbolic2(int x) {84  if (x > 255) { // \85    // bugpath-note{{Assuming 'x' is > 255}} \86    // bugpath-note{{Taking true branch}}87 88    int ret = toupper(x); // \89    // report-warning{{The 1st argument to 'toupper' is >= 256 but should be an unsigned char value or EOF}} \90    // bugpath-warning{{The 1st argument to 'toupper' is >= 256 but should be an unsigned char value or EOF}} \91    // bugpath-note{{The 1st argument to 'toupper' is >= 256 but should be an unsigned char value or EOF}}92 93    (void)ret;94  }95}96 97void test_tolower_concrete(int v) {98  int ret = tolower(256); // \99  // report-warning{{The 1st argument to 'tolower' is 256 but should be an unsigned char value or EOF}} \100  // bugpath-warning{{The 1st argument to 'tolower' is 256 but should be an unsigned char value or EOF}} \101  // bugpath-note{{The 1st argument to 'tolower' is 256 but should be an unsigned char value or EOF}}102  (void)ret;103}104 105void test_tolower_symbolic(int x) {106  int ret = tolower(x);107  (void)ret;108 109  clang_analyzer_eval(EOF <= x && x <= 255); // \110  // report-warning{{TRUE}} \111  // bugpath-warning{{TRUE}} \112  // bugpath-note{{TRUE}} \113  // bugpath-note{{Left side of '&&' is true}} \114  // bugpath-note{{'x' is <= 255}}115}116 117void test_tolower_symbolic2(int x) {118  if (x > 255) { // \119    // bugpath-note{{Assuming 'x' is > 255}} \120    // bugpath-note{{Taking true branch}}121 122    int ret = tolower(x); // \123    // report-warning{{The 1st argument to 'tolower' is >= 256 but should be an unsigned char value or EOF}} \124    // bugpath-warning{{The 1st argument to 'tolower' is >= 256 but should be an unsigned char value or EOF}} \125    // bugpath-note{{The 1st argument to 'tolower' is >= 256 but should be an unsigned char value or EOF}}126 127    (void)ret;128  }129}130 131void test_toascii_concrete(int v) {132  int ret = toascii(256); // \133  // report-warning{{The 1st argument to 'toascii' is 256 but should be an unsigned char value or EOF}} \134  // bugpath-warning{{The 1st argument to 'toascii' is 256 but should be an unsigned char value or EOF}} \135  // bugpath-note{{The 1st argument to 'toascii' is 256 but should be an unsigned char value or EOF}}136  (void)ret;137}138 139void test_toascii_symbolic(int x) {140  int ret = toascii(x);141  (void)ret;142 143  clang_analyzer_eval(EOF <= x && x <= 255); // \144  // report-warning{{TRUE}} \145  // bugpath-warning{{TRUE}} \146  // bugpath-note{{TRUE}} \147  // bugpath-note{{Left side of '&&' is true}} \148  // bugpath-note{{'x' is <= 255}}149}150 151void test_toascii_symbolic2(int x) {152  if (x > 255) { // \153    // bugpath-note{{Assuming 'x' is > 255}} \154    // bugpath-note{{Taking true branch}}155 156    int ret = toascii(x); // \157    // report-warning{{The 1st argument to 'toascii' is >= 256 but should be an unsigned char value or EOF}} \158    // bugpath-warning{{The 1st argument to 'toascii' is >= 256 but should be an unsigned char value or EOF}} \159    // bugpath-note{{The 1st argument to 'toascii' is >= 256 but should be an unsigned char value or EOF}}160 161    (void)ret;162  }163}164 165void test_notnull_concrete(FILE *fp) {166  fread(0, sizeof(int), 10, fp); // \167  // report-warning{{The 1st argument to 'fread' is NULL but should not be NULL}} \168  // bugpath-warning{{The 1st argument to 'fread' is NULL but should not be NULL}} \169  // bugpath-note{{The 1st argument to 'fread' is NULL but should not be NULL}}170}171void test_notnull_symbolic(FILE *fp, int *buf) {172  fread(buf, sizeof(int), 10, fp);173  clang_analyzer_eval(buf != 0); // \174  // report-warning{{TRUE}} \175  // bugpath-warning{{TRUE}} \176  // bugpath-note{{TRUE}} \177  // bugpath-note{{'buf' is not equal to null}}178}179void test_notnull_symbolic2(FILE *fp, int *buf) {180  if (!buf)                          // bugpath-note{{Assuming 'buf' is null}} \181            // bugpath-note{{Taking true branch}}182    fread(buf, sizeof(int), 10, fp); // \183    // report-warning{{The 1st argument to 'fread' is NULL but should not be NULL}} \184    // bugpath-warning{{The 1st argument to 'fread' is NULL but should not be NULL}} \185    // bugpath-note{{The 1st argument to 'fread' is NULL but should not be NULL}}186}187 188int __not_null_buffer(void *, int, int);189 190void test_notnull_buffer_1(void *buf) {191  __not_null_buffer(buf, 0, 1);192  clang_analyzer_eval(buf != 0); // \193  // report-warning{{TRUE}} \194  // bugpath-warning{{TRUE}} \195  // report-warning{{FALSE}} \196  // bugpath-warning{{FALSE}} \197  // bugpath-note{{TRUE}} \198  // bugpath-note{{FALSE}} \199  // bugpath-note{{Assuming 'buf' is equal to null}} \200  // bugpath-note{{Assuming 'buf' is not equal to null}}201}202 203void test_notnull_buffer_2(void *buf) {204  __not_null_buffer(buf, 1, 0);205  clang_analyzer_eval(buf != 0); // \206  // report-warning{{TRUE}} \207  // bugpath-warning{{TRUE}} \208  // report-warning{{FALSE}} \209  // bugpath-warning{{FALSE}} \210  // bugpath-note{{TRUE}} \211  // bugpath-note{{FALSE}} \212  // bugpath-note{{Assuming 'buf' is equal to null}} \213  // bugpath-note{{Assuming 'buf' is not equal to null}}214}215 216void test_notnull_buffer_3(void *buf) {217  __not_null_buffer(buf, 1, 1);218  clang_analyzer_eval(buf != 0); // \219  // report-warning{{TRUE}} \220  // bugpath-warning{{TRUE}} \221  // bugpath-note{{TRUE}} \222  // bugpath-note{{'buf' is not equal to null}}223}224 225void test_no_node_after_bug(FILE *fp, size_t size, size_t n, void *buf) {226  if (fp) // \227  // bugpath-note{{Assuming 'fp' is null}} \228  // bugpath-note{{Taking false branch}}229    return;230  size_t ret = fread(buf, size, n, fp); // \231  // report-warning{{The 4th argument to 'fread' is NULL but should not be NULL}} \232  // bugpath-warning{{The 4th argument to 'fread' is NULL but should not be NULL}} \233  // bugpath-note{{The 4th argument to 'fread' is NULL but should not be NULL}}234  clang_analyzer_warnIfReached(); // not reachable235}236 237// This is one test case for the ARR38-C SEI-CERT rule.238void ARR38_C_F(FILE *file) {239  enum { BUFFER_SIZE = 1024 };240  wchar_t wbuf[BUFFER_SIZE]; // bugpath-note{{'wbuf' initialized here}}241 242  const size_t size = sizeof(*wbuf);   // bugpath-note{{'size' initialized to}}243  const size_t nitems = sizeof(wbuf);  // bugpath-note{{'nitems' initialized to}}244 245  // The 3rd parameter should be the number of elements to read, not246  // the size in bytes.247  fread(wbuf, size, nitems, file); // \248  // report-warning{{The 1st argument to 'fread' is a buffer with size 4096 but should be a buffer with size equal to or greater than the value of the 2nd argument (which is 4) times the 3rd argument (which is 4096)}} \249  // bugpath-warning{{The 1st argument to 'fread' is a buffer with size 4096 but should be a buffer with size equal to or greater than the value of the 2nd argument (which is 4) times the 3rd argument (which is 4096)}} \250  // bugpath-note{{The 1st argument to 'fread' is a buffer with size 4096 but should be a buffer with size equal to or greater than the value of the 2nd argument (which is 4) times the 3rd argument (which is 4096)}}251}252 253int __two_constrained_args(int, int);254void test_constraints_on_multiple_args(int x, int y) {255  // State split should not happen here. I.e. x == 1 should not be evaluated256  // FALSE.257  __two_constrained_args(x, y);258  //NOTE! Because of the second `clang_analyzer_eval` call we have two bug259  clang_analyzer_eval(x == 1); // \260  // report-warning{{TRUE}} \261  // bugpath-warning{{TRUE}} \262  // bugpath-note{{TRUE}}263  clang_analyzer_eval(y == 1); // \264  // report-warning{{TRUE}} \265  // bugpath-warning{{TRUE}} \266  // bugpath-note{{TRUE}}267}268 269int __arg_constrained_twice(int);270void test_multiple_constraints_on_same_arg(int x) {271  __arg_constrained_twice(x);272  clang_analyzer_eval(x < 1 || x > 2); // \273  // report-warning{{TRUE}} \274  // bugpath-warning{{TRUE}} \275  // bugpath-note{{TRUE}} \276  // bugpath-note{{Assuming 'x' is < 1}} \277  // bugpath-note{{Left side of '||' is true}}278}279 280int __variadic(void *stream, const char *format, ...);281void test_arg_constraint_on_variadic_fun(void) {282  __variadic(0, "%d%d", 1, 2); // \283  // report-warning{{The 1st argument to '__variadic' is NULL but should not be NULL}} \284  // bugpath-warning{{The 1st argument to '__variadic' is NULL but should not be NULL}} \285  // bugpath-note{{The 1st argument to '__variadic' is NULL but should not be NULL}}286}287 288int __buf_size_arg_constraint(const void *, size_t);289void test_buf_size_concrete(void) {290  char buf[3];                       // bugpath-note{{'buf' initialized here}}291  __buf_size_arg_constraint(buf, 4); // \292  // report-warning{{The 1st argument to '__buf_size_arg_constraint' is a buffer with size 3 but should be a buffer with size equal to or greater than the value of the 2nd argument (which is 4)}} \293  // bugpath-warning{{The 1st argument to '__buf_size_arg_constraint' is a buffer with size 3 but should be a buffer with size equal to or greater than the value of the 2nd argument (which is 4)}} \294  // bugpath-note{{The 1st argument to '__buf_size_arg_constraint' is a buffer with size 3 but should be a buffer with size equal to or greater than the value of the 2nd argument (which is 4)}}295}296void test_buf_size_symbolic(int s) {297  char buf[3];298  __buf_size_arg_constraint(buf, s);299  clang_analyzer_eval(s <= 3); // \300  // report-warning{{TRUE}} \301  // bugpath-warning{{TRUE}} \302  // bugpath-note{{TRUE}} \303  // bugpath-note{{'s' is <= 3}}304}305void test_buf_size_symbolic_and_offset(int s) {306  char buf[3];307  __buf_size_arg_constraint(buf + 1, s);308  clang_analyzer_eval(s <= 2); // \309  // report-warning{{TRUE}} \310  // bugpath-warning{{TRUE}} \311  // bugpath-note{{TRUE}} \312  // bugpath-note{{'s' is <= 2}}313}314 315int __buf_size_arg_constraint_mul(const void *, size_t, size_t);316void test_buf_size_concrete_with_multiplication(void) {317  short buf[3];                                         // bugpath-note{{'buf' initialized here}}318  __buf_size_arg_constraint_mul(buf, 4, sizeof(short)); // \319  // report-warning{{The 1st argument to '__buf_size_arg_constraint_mul' is a buffer with size 6 but should be a buffer with size equal to or greater than the value of the 2nd argument (which is 4) times the 3rd argument (which is 2)}} \320  // bugpath-warning{{The 1st argument to '__buf_size_arg_constraint_mul' is a buffer with size 6 but should be a buffer with size equal to or greater than the value of the 2nd argument (which is 4) times the 3rd argument (which is 2)}} \321  // bugpath-note{{The 1st argument to '__buf_size_arg_constraint_mul' is a buffer with size 6 but should be a buffer with size equal to or greater than the value of the 2nd argument (which is 4) times the 3rd argument (which is 2)}}322}323void test_buf_size_symbolic_with_multiplication(size_t s) {324  short buf[3];325  __buf_size_arg_constraint_mul(buf, s, sizeof(short));326  clang_analyzer_eval(s * sizeof(short) <= 6); // \327  // report-warning{{TRUE}} \328  // bugpath-warning{{TRUE}} \329  // bugpath-note{{TRUE}}330}331void test_buf_size_symbolic_and_offset_with_multiplication(size_t s) {332  short buf[3];333  __buf_size_arg_constraint_mul(buf + 1, s, sizeof(short));334  clang_analyzer_eval(s * sizeof(short) <= 4); // \335  // report-warning{{TRUE}} \336  // bugpath-warning{{TRUE}} \337  // bugpath-note{{TRUE}}338}339 340// The minimum buffer size for this function is set to 10.341int __buf_size_arg_constraint_concrete(const void *);342void test_min_buf_size(void) {343  char buf[9];// bugpath-note{{'buf' initialized here}}344  __buf_size_arg_constraint_concrete(buf); // \345  // report-warning{{The 1st argument to '__buf_size_arg_constraint_concrete' is a buffer with size 9 but should be a buffer with size equal to or greater than 10}} \346  // bugpath-warning{{The 1st argument to '__buf_size_arg_constraint_concrete' is a buffer with size 9 but should be a buffer with size equal to or greater than 10}} \347  // bugpath-note{{The 1st argument to '__buf_size_arg_constraint_concrete' is a buffer with size 9 but should be a buffer with size equal to or greater than 10}}348}349 350void test_file_fd_at_functions() {351  (void)linkat(-22, "from", AT_FDCWD, "to", 0); // \352  // report-warning{{The 1st argument to 'linkat' is -22 but should be a valid file descriptor or AT_FDCWD}} \353  // bugpath-warning{{The 1st argument to 'linkat' is -22 but should be a valid file descriptor or AT_FDCWD}} \354  // bugpath-note{{The 1st argument to 'linkat' is -22 but should be a valid file descriptor or AT_FDCWD}}355 356  // no warning for these functions if the AT_FDCWD value is used357  (void)openat(AT_FDCWD, "path", 0);358  (void)linkat(AT_FDCWD, "from", AT_FDCWD, "to", 0);359  (void)faccessat(AT_FDCWD, "path", 0, 0);360  (void)symlinkat("oldpath", AT_FDCWD, "newpath");361  (void)mkdirat(AT_FDCWD, "path", 0);362  (void)mknodat(AT_FDCWD, "path", 0, 0);363  (void)fchmodat(AT_FDCWD, "path", 0, 0);364  (void)fchownat(AT_FDCWD, "path", 0, 0, 0);365  (void)linkat(AT_FDCWD, "oldpath", AT_FDCWD, "newpath", 0);366  (void)unlinkat(AT_FDCWD, "newpath", 0);367  struct stat St;368  (void)fstatat(AT_FDCWD, "newpath", &St, 0);369  char Buf[10];370  (void)readlinkat(AT_FDCWD, "newpath", Buf, 10);371  (void)renameat(AT_FDCWD, "oldpath", AT_FDCWD, "newpath");372}373