(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
analyzer/
stdarg-1.c
       1  /* { dg-additional-options "-fno-analyzer-suppress-followups" } */
       2  
       3  #include "analyzer-decls.h"
       4  
       5  /* Unpacking a va_list.  */
       6  
       7  static void __attribute__((noinline))
       8  __analyzer_called_by_test_1 (int placeholder, ...)
       9  {
      10    const char *s;
      11    int i;
      12    char c;
      13    
      14    __builtin_va_list ap;
      15    __builtin_va_start (ap, placeholder);
      16  
      17    s = __builtin_va_arg (ap, char *);
      18    __analyzer_eval (s[0] == 'f'); /* { dg-warning "TRUE" } */
      19  
      20    i = __builtin_va_arg (ap, int);
      21    __analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
      22  
      23    c = (char)__builtin_va_arg (ap, int);
      24    __analyzer_eval (c == '@'); /* { dg-warning "TRUE" } */
      25  
      26    __builtin_va_end (ap);
      27  }
      28  
      29  void test_1 (void)
      30  {
      31    __analyzer_called_by_test_1 (42, "foo", 1066, '@');
      32  }
      33  
      34  /* Unpacking a va_list passed from an intermediate function.  */
      35  
      36  static void __attribute__((noinline))
      37  __analyzer_test_2_inner (__builtin_va_list ap)
      38  {
      39    const char *s;
      40    int i;
      41    char c;
      42    
      43    s = __builtin_va_arg (ap, char *);
      44    __analyzer_eval (s[0] == 'f'); /* { dg-warning "TRUE" } */
      45  
      46    i = __builtin_va_arg (ap, int);
      47    __analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
      48  
      49    c = (char)__builtin_va_arg (ap, int);
      50    __analyzer_eval (c == '@'); /* { dg-warning "TRUE" } */
      51  }
      52  
      53  static void __attribute__((noinline))
      54  __analyzer_test_2_middle (int placeholder, ...)
      55  {
      56    __builtin_va_list ap;
      57    __builtin_va_start (ap, placeholder);
      58    __analyzer_test_2_inner (ap);
      59    __builtin_va_end (ap);
      60  }
      61  
      62  void test_2 (void)
      63  {
      64    __analyzer_test_2_middle (42, "foo", 1066, '@');
      65  }
      66  
      67  /* Not enough args.  */
      68  
      69  static void __attribute__((noinline))
      70  __analyzer_called_by_test_not_enough_args (int placeholder, ...)
      71  {
      72    const char *s;
      73    int i;
      74    
      75    __builtin_va_list ap;
      76    __builtin_va_start (ap, placeholder);
      77  
      78    s = __builtin_va_arg (ap, char *);
      79    __analyzer_eval (s[0] == 'f'); /* { dg-warning "TRUE" } */
      80  
      81    i = __builtin_va_arg (ap, int); /* { dg-warning "'ap' has no more arguments \\(1 consumed\\) \\\[CWE-685\\\]" } */
      82  
      83    __builtin_va_end (ap);
      84  }
      85  
      86  void test_not_enough_args (void)
      87  {
      88    __analyzer_called_by_test_not_enough_args (42, "foo");
      89  }
      90  
      91  /* Not enough args, with an intermediate function.  */
      92  
      93  static void __attribute__((noinline))
      94  __analyzer_test_not_enough_args_2_inner (__builtin_va_list ap)
      95  {
      96    const char *s;
      97    int i;
      98    
      99    s = __builtin_va_arg (ap, char *);
     100    __analyzer_eval (s[0] == 'f'); /* { dg-warning "TRUE" } */
     101  
     102    i = __builtin_va_arg (ap, int); /* { dg-warning "'ap' has no more arguments \\(1 consumed\\)" } */
     103  }
     104  
     105  static void __attribute__((noinline))
     106  __analyzer_test_not_enough_args_2_middle (int placeholder, ...)
     107  {
     108    __builtin_va_list ap;
     109    __builtin_va_start (ap, placeholder);
     110    __analyzer_test_not_enough_args_2_inner (ap);
     111    __builtin_va_end (ap);
     112  }
     113  
     114  void test_not_enough_args_2 (void)
     115  {
     116    __analyzer_test_not_enough_args_2_middle (42, "foo");
     117  }
     118  
     119  /* Excess args (not a problem).  */
     120  
     121  static void __attribute__((noinline))
     122  __analyzer_called_by_test_excess_args (int placeholder, ...)
     123  {
     124    const char *s;
     125    
     126    __builtin_va_list ap;
     127    __builtin_va_start (ap, placeholder);
     128  
     129    s = __builtin_va_arg (ap, char *);
     130    __analyzer_eval (s[0] == 'f'); /* { dg-warning "TRUE" } */
     131  
     132    __builtin_va_end (ap);
     133  }
     134  
     135  void test_excess_args (void)
     136  {
     137    __analyzer_called_by_test_excess_args (42, "foo", "bar");
     138  }
     139  
     140  /* Missing va_start.  */
     141  
     142  void test_missing_va_start (int placeholder, ...)
     143  {
     144    __builtin_va_list ap; /* { dg-message "region created on stack here" } */
     145    int i = __builtin_va_arg (ap, int); /* { dg-warning "use of uninitialized value 'ap'" } */
     146  }
     147  
     148  /* Missing va_end.  */
     149  
     150  void test_missing_va_end (int placeholder, ...)
     151  {
     152    int i;
     153    __builtin_va_list ap;
     154    __builtin_va_start (ap, placeholder); /* { dg-message "\\(1\\) 'va_start' called here" } */
     155    i = __builtin_va_arg (ap, int);
     156  } /* { dg-warning "missing call to 'va_end'" "warning" } */
     157  /* { dg-message "\\(2\\) missing call to 'va_end' to match 'va_start' at \\(1\\)" "final event" { target *-*-* } .-1 } */
     158  
     159  /* Missing va_end due to error-handling.  */
     160  
     161  int test_missing_va_end_2 (int placeholder, ...)
     162  {
     163    int i, j;
     164    __builtin_va_list ap;
     165    __builtin_va_start (ap, placeholder); /* { dg-message "\\(1\\) 'va_start' called here" } */
     166    i = __builtin_va_arg (ap, int);
     167    if (i == 42)
     168      {
     169        __builtin_va_end (ap);
     170        return -1;
     171      }
     172    j = __builtin_va_arg (ap, int);
     173    if (j == 1066) /* { dg-message "branch" } */
     174      return -1; /* { dg-message "here" } */
     175    __builtin_va_end (ap);
     176    return 0;
     177  } /* { dg-warning "missing call to 'va_end'" "warning" } */
     178  
     179  /* va_arg after va_end.  */
     180  
     181  void test_va_arg_after_va_end (int placeholder, ...)
     182  {
     183    int i;
     184    __builtin_va_list ap;
     185    __builtin_va_start (ap, placeholder);
     186    __builtin_va_end (ap); /* { dg-message "'va_end' called here" } */
     187    i = __builtin_va_arg (ap, int); /* { dg-warning "'va_arg' after 'va_end'" } */
     188  }
     189  
     190  /* Type mismatch: expect int, but passed a char *.  */
     191  
     192  static void __attribute__((noinline))
     193  __analyzer_called_by_test_type_mismatch_1 (int placeholder, ...)
     194  {
     195    int i;
     196    
     197    __builtin_va_list ap;
     198    __builtin_va_start (ap, placeholder);
     199  
     200    i = __builtin_va_arg (ap, int); /* { dg-warning "'va_arg' expected 'int' but received '\[^\n\r\]*' for variadic argument 1 of 'ap' \\\[CWE-686\\\]" } */
     201  
     202    __builtin_va_end (ap);
     203  }
     204  
     205  void test_type_mismatch_1 (void)
     206  {
     207    __analyzer_called_by_test_type_mismatch_1 (42, "foo");
     208  }
     209  
     210  /* Type mismatch: expect char *, but passed an int.  */
     211  
     212  static void __attribute__((noinline))
     213  __analyzer_called_by_test_type_mismatch_2 (int placeholder, ...)
     214  {
     215    const char *str;
     216    
     217    __builtin_va_list ap;
     218    __builtin_va_start (ap, placeholder);
     219  
     220    str = __builtin_va_arg (ap, const char *); /* { dg-warning "'va_arg' expected 'const char \\*' but received 'int' for variadic argument 1" } */
     221  
     222    __builtin_va_end (ap);
     223  }
     224  
     225  void test_type_mismatch_2 (void)
     226  {
     227    __analyzer_called_by_test_type_mismatch_2 (42, 1066);
     228  }
     229  
     230  /* As above, but with an intermediate function.  */
     231  
     232  static void __attribute__((noinline))
     233  __analyzer_test_type_mismatch_3_inner (__builtin_va_list ap)
     234  {
     235    const char *str;
     236    
     237    str = __builtin_va_arg (ap, const char *); /* { dg-warning "'va_arg' expected 'const char \\*' but received 'int' for variadic argument 1 of 'ap'" } */
     238  }
     239  
     240  static void __attribute__((noinline))
     241  __analyzer_test_type_mismatch_3_middle (int placeholder, ...)
     242  {
     243    __builtin_va_list ap;
     244    __builtin_va_start (ap, placeholder);
     245  
     246    __analyzer_test_type_mismatch_3_inner (ap);
     247  
     248    __builtin_va_end (ap);
     249  }
     250  
     251  void test_type_mismatch_3 (void)
     252  {
     253    __analyzer_test_type_mismatch_3_middle (42, 1066);
     254  }
     255  
     256  /* Multiple traversals of the args.  */
     257  
     258  static void __attribute__((noinline))
     259  __analyzer_called_by_test_multiple_traversals (int placeholder, ...)
     260  {
     261    __builtin_va_list ap;
     262  
     263    /* First traversal.  */
     264    {
     265      int i, j;
     266  
     267      __builtin_va_start (ap, placeholder);
     268  
     269      i = __builtin_va_arg (ap, int);
     270      __analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
     271  
     272      j = __builtin_va_arg (ap, int);
     273      __analyzer_eval (j == 42); /* { dg-warning "TRUE" } */
     274  
     275      __builtin_va_end (ap);
     276    }
     277  
     278    /* Second traversal.  */
     279    {
     280      int i, j;
     281  
     282      __builtin_va_start (ap, placeholder);
     283  
     284      i = __builtin_va_arg (ap, int);
     285      __analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
     286  
     287      j = __builtin_va_arg (ap, int);
     288      __analyzer_eval (j == 42); /* { dg-warning "TRUE" } */
     289  
     290      __builtin_va_end (ap);
     291    }
     292  }
     293  
     294  void test_multiple_traversals (void)
     295  {
     296    __analyzer_called_by_test_multiple_traversals (0, 1066, 42);
     297  }
     298  
     299  /* Multiple traversals, using va_copy.  */
     300  
     301  static void __attribute__((noinline))
     302  __analyzer_called_by_test_multiple_traversals_2 (int placeholder, ...)
     303  {
     304    int i, j;
     305    __builtin_va_list args1;
     306    __builtin_va_list args2;
     307  
     308    __builtin_va_start (args1, placeholder);
     309    __builtin_va_copy (args2, args1);
     310  
     311    /* First traversal.  */
     312    i = __builtin_va_arg (args1, int);
     313    __analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
     314    j = __builtin_va_arg (args1, int);
     315    __analyzer_eval (j == 42); /* { dg-warning "TRUE" } */
     316    __builtin_va_end (args1);
     317  
     318    /* Traversal of copy.  */
     319    i = __builtin_va_arg (args2, int);
     320    __analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
     321    j = __builtin_va_arg (args2, int);
     322    __analyzer_eval (j == 42); /* { dg-warning "TRUE" } */
     323    __builtin_va_end (args2);
     324  }
     325  
     326  void test_multiple_traversals_2 (void)
     327  {
     328    __analyzer_called_by_test_multiple_traversals_2 (0, 1066, 42);
     329  }
     330  
     331  /* Multiple traversals, using va_copy after a va_arg.  */
     332  
     333  static void __attribute__((noinline))
     334  __analyzer_called_by_test_multiple_traversals_3 (int placeholder, ...)
     335  {
     336    int i, j;
     337    __builtin_va_list args1;
     338    __builtin_va_list args2;
     339  
     340    __builtin_va_start (args1, placeholder);
     341  
     342    /* First traversal.  */
     343    i = __builtin_va_arg (args1, int);
     344    __analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
     345  
     346    /* va_copy after the first va_arg. */
     347    __builtin_va_copy (args2, args1);
     348  
     349    j = __builtin_va_arg (args1, int);
     350    __analyzer_eval (j == 42); /* { dg-warning "TRUE" } */
     351    __builtin_va_end (args1);
     352  
     353    /* Traversal of copy.  */
     354    j = __builtin_va_arg (args2, int);
     355    __analyzer_eval (j == 42); /* { dg-warning "TRUE" } */
     356    __builtin_va_end (args2);
     357  }
     358  
     359  void test_multiple_traversals_3 (void)
     360  {
     361    __analyzer_called_by_test_multiple_traversals_3 (0, 1066, 42);
     362  }
     363  
     364  /* va_copy after va_end.  */
     365  
     366  void test_va_copy_after_va_end (int placeholder, ...)
     367  {
     368    __builtin_va_list ap1, ap2;
     369    __builtin_va_start (ap1, placeholder);
     370    __builtin_va_end (ap1); /* { dg-message "'va_end' called here" } */
     371    __builtin_va_copy (ap2, ap1); /* { dg-warning "'va_copy' after 'va_end'" } */
     372    __builtin_va_end (ap2);
     373  }
     374  
     375  /* leak of va_copy.  */
     376  
     377  void test_leak_of_va_copy (int placeholder, ...)
     378  {
     379    __builtin_va_list ap1, ap2;
     380    __builtin_va_start (ap1, placeholder);
     381    __builtin_va_copy (ap2, ap1); /* { dg-message "'va_copy' called here" } */
     382    __builtin_va_end (ap1);
     383  } /* { dg-warning "missing call to 'va_end'" "warning" } */
     384    /* { dg-message "missing call to 'va_end' to match 'va_copy' at \\(1\\)" "final event" { target *-*-* } .-1 } */
     385  
     386  /* double va_end.  */
     387  
     388  void test_double_va_end (int placeholder, ...)
     389  {
     390    __builtin_va_list ap;
     391    __builtin_va_start (ap, placeholder);
     392    __builtin_va_end (ap); /* { dg-message "'va_end' called here" } */
     393    __builtin_va_end (ap); /* { dg-warning "'va_end' after 'va_end'" } */
     394  }
     395  
     396  /* double va_start.  */
     397  
     398  void test_double_va_start (int placeholder, ...)
     399  {
     400    int i;
     401    __builtin_va_list ap;
     402    __builtin_va_start (ap, placeholder); /* { dg-message "'va_start' called here" } */
     403    __builtin_va_start (ap, placeholder);  /* { dg-warning "missing call to 'va_end'" "warning" } */
     404    /* { dg-message "missing call to 'va_end' to match 'va_start' at \\(1\\)" "final event" { target *-*-* } .-1 } */
     405    __builtin_va_end (ap);
     406  }
     407  
     408  /* va_copy before va_start.  */
     409  
     410  void test_va_copy_before_va_start (int placeholder, ...)
     411  {
     412    __builtin_va_list ap1; /* { dg-message "region created on stack here" } */
     413    __builtin_va_list ap2;
     414    __builtin_va_copy (ap2, ap1); /* { dg-warning "use of uninitialized value 'ap1'" } */
     415    __builtin_va_end (ap2);
     416  }
     417  
     418  /* Verify that we complain about uses of a va_list after the function 
     419     in which va_start was called has returned.  */
     420  
     421  __builtin_va_list global_ap;
     422  
     423  static void __attribute__((noinline))
     424  __analyzer_called_by_test_va_arg_after_return (int placeholder, ...)
     425  {
     426    __builtin_va_start (global_ap, placeholder);
     427    __builtin_va_end (global_ap);
     428  }
     429  
     430  void test_va_arg_after_return (void)
     431  {
     432    int i;
     433    __analyzer_called_by_test_va_arg_after_return (42, 1066);
     434    i = __builtin_va_arg (global_ap, int); /* { dg-warning "dereferencing pointer 'global_ap' to within stale stack frame" } */
     435  }
     436  
     437  void pr107349 (void)
     438  {
     439    __builtin_va_list x,y;
     440    __builtin_va_copy(x,y); /* { dg-warning "use of uninitialized value 'y'" } */
     441  } /* { dg-warning "missing call to 'va_end'" } */