blob: e55f10de66be10bb843c7af39f65f5f09c50f85f [file] [log] [blame]
/* As per stdarg-1.c, but using the ms_abi versions of the builtins. */
/* { dg-do compile { target { x86_64-*-* && lp64 } } } */
#include "analyzer-decls.h"
/* Unpacking a va_list. */
static void __attribute__((noinline))
__analyzer_called_by_test_1 (int placeholder, ...)
{
const char *s;
int i;
char c;
__builtin_ms_va_list ap;
__builtin_ms_va_start (ap, placeholder);
s = __builtin_va_arg (ap, char *);
__analyzer_eval (s[0] == 'f'); /* { dg-warning "TRUE" } */
i = __builtin_va_arg (ap, int);
__analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
c = (char)__builtin_va_arg (ap, int);
__analyzer_eval (c == '@'); /* { dg-warning "TRUE" } */
__builtin_ms_va_end (ap);
}
void test_1 (void)
{
__analyzer_called_by_test_1 (42, "foo", 1066, '@');
}
/* Unpacking a va_list passed from an intermediate function. */
static void __attribute__((noinline))
__analyzer_test_2_inner (__builtin_ms_va_list ap)
{
const char *s;
int i;
char c;
s = __builtin_va_arg (ap, char *);
__analyzer_eval (s[0] == 'f'); /* { dg-warning "TRUE" } */
i = __builtin_va_arg (ap, int);
__analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
c = (char)__builtin_va_arg (ap, int);
__analyzer_eval (c == '@'); /* { dg-warning "TRUE" } */
}
static void __attribute__((noinline))
__analyzer_test_2_middle (int placeholder, ...)
{
__builtin_ms_va_list ap;
__builtin_ms_va_start (ap, placeholder);
__analyzer_test_2_inner (ap);
__builtin_ms_va_end (ap);
}
void test_2 (void)
{
__analyzer_test_2_middle (42, "foo", 1066, '@');
}
/* Not enough args. */
static void __attribute__((noinline))
__analyzer_called_by_test_not_enough_args (int placeholder, ...)
{
const char *s;
int i;
__builtin_ms_va_list ap;
__builtin_ms_va_start (ap, placeholder);
s = __builtin_va_arg (ap, char *);
__analyzer_eval (s[0] == 'f'); /* { dg-warning "TRUE" } */
i = __builtin_va_arg (ap, int); /* { dg-warning "'ap' has no more arguments \\(1 consumed\\) \\\[CWE-685\\\]" } */
__builtin_ms_va_end (ap);
}
void test_not_enough_args (void)
{
__analyzer_called_by_test_not_enough_args (42, "foo");
}
/* Not enough args, with an intermediate function. */
static void __attribute__((noinline))
__analyzer_test_not_enough_args_2_inner (__builtin_ms_va_list ap)
{
const char *s;
int i;
s = __builtin_va_arg (ap, char *);
__analyzer_eval (s[0] == 'f'); /* { dg-warning "TRUE" } */
i = __builtin_va_arg (ap, int); /* { dg-warning "'ap' has no more arguments \\(1 consumed\\)" } */
}
static void __attribute__((noinline))
__analyzer_test_not_enough_args_2_middle (int placeholder, ...)
{
__builtin_ms_va_list ap;
__builtin_ms_va_start (ap, placeholder);
__analyzer_test_not_enough_args_2_inner (ap);
__builtin_ms_va_end (ap);
}
void test_not_enough_args_2 (void)
{
__analyzer_test_not_enough_args_2_middle (42, "foo");
}
/* Excess args (not a problem). */
static void __attribute__((noinline))
__analyzer_called_by_test_excess_args (int placeholder, ...)
{
const char *s;
__builtin_ms_va_list ap;
__builtin_ms_va_start (ap, placeholder);
s = __builtin_va_arg (ap, char *);
__analyzer_eval (s[0] == 'f'); /* { dg-warning "TRUE" } */
__builtin_ms_va_end (ap);
}
void test_excess_args (void)
{
__analyzer_called_by_test_excess_args (42, "foo", "bar");
}
/* Missing va_start. */
void test_missing_va_start (int placeholder, ...)
{
__builtin_ms_va_list ap; /* { dg-message "region created on stack here" } */
int i = __builtin_va_arg (ap, int); /* { dg-warning "use of uninitialized value 'ap'" } */
}
/* Missing va_end. */
void test_missing_va_end (int placeholder, ...)
{
int i;
__builtin_ms_va_list ap;
__builtin_ms_va_start (ap, placeholder); /* { dg-message "\\(1\\) 'va_start' called here" } */
i = __builtin_va_arg (ap, int);
} /* { dg-warning "missing call to 'va_end'" "warning" } */
/* { dg-message "\\(2\\) missing call to 'va_end' to match 'va_start' at \\(1\\)" "final event" { target *-*-* } .-1 } */
/* Missing va_end due to error-handling. */
int test_missing_va_end_2 (int placeholder, ...)
{
int i, j;
__builtin_ms_va_list ap;
__builtin_ms_va_start (ap, placeholder); /* { dg-message "\\(1\\) 'va_start' called here" } */
i = __builtin_va_arg (ap, int);
if (i == 42)
{
__builtin_ms_va_end (ap);
return -1;
}
j = __builtin_va_arg (ap, int);
if (j == 1066) /* { dg-message "branch" } */
return -1; /* { dg-message "here" } */
__builtin_ms_va_end (ap);
return 0;
} /* { dg-warning "missing call to 'va_end'" "warning" } */
/* va_arg after va_end. */
void test_va_arg_after_va_end (int placeholder, ...)
{
int i;
__builtin_ms_va_list ap;
__builtin_ms_va_start (ap, placeholder);
__builtin_ms_va_end (ap); /* { dg-message "'va_end' called here" } */
i = __builtin_va_arg (ap, int); /* { dg-warning "'va_arg' after 'va_end'" } */
}
/* Type mismatch: expect int, but passed a char *. */
static void __attribute__((noinline))
__analyzer_called_by_test_type_mismatch_1 (int placeholder, ...)
{
int i;
__builtin_ms_va_list ap;
__builtin_ms_va_start (ap, placeholder);
i = __builtin_va_arg (ap, int); /* { dg-warning "'va_arg' expected 'int' but received '\[^\n\r\]*' for variadic argument 1 of 'ap' \\\[CWE-686\\\]" } */
__builtin_ms_va_end (ap);
}
void test_type_mismatch_1 (void)
{
__analyzer_called_by_test_type_mismatch_1 (42, "foo");
}
/* Type mismatch: expect char *, but passed an int. */
static void __attribute__((noinline))
__analyzer_called_by_test_type_mismatch_2 (int placeholder, ...)
{
const char *str;
__builtin_ms_va_list ap;
__builtin_ms_va_start (ap, placeholder);
str = __builtin_va_arg (ap, const char *); /* { dg-warning "'va_arg' expected 'const char \\*' but received 'int' for variadic argument 1" } */
__builtin_ms_va_end (ap);
}
void test_type_mismatch_2 (void)
{
__analyzer_called_by_test_type_mismatch_2 (42, 1066);
}
/* As above, but with an intermediate function. */
static void __attribute__((noinline))
__analyzer_test_type_mismatch_3_inner (__builtin_ms_va_list ap)
{
const char *str;
str = __builtin_va_arg (ap, const char *); /* { dg-warning "'va_arg' expected 'const char \\*' but received 'int' for variadic argument 1 of 'ap'" } */
}
static void __attribute__((noinline))
__analyzer_test_type_mismatch_3_middle (int placeholder, ...)
{
__builtin_ms_va_list ap;
__builtin_ms_va_start (ap, placeholder);
__analyzer_test_type_mismatch_3_inner (ap);
__builtin_ms_va_end (ap);
}
void test_type_mismatch_3 (void)
{
__analyzer_test_type_mismatch_3_middle (42, 1066);
}
/* Multiple traversals of the args. */
static void __attribute__((noinline))
__analyzer_called_by_test_multiple_traversals (int placeholder, ...)
{
__builtin_ms_va_list ap;
/* First traversal. */
{
int i, j;
__builtin_ms_va_start (ap, placeholder);
i = __builtin_va_arg (ap, int);
__analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
j = __builtin_va_arg (ap, int);
__analyzer_eval (j == 42); /* { dg-warning "TRUE" } */
__builtin_ms_va_end (ap);
}
/* Second traversal. */
{
int i, j;
__builtin_ms_va_start (ap, placeholder);
i = __builtin_va_arg (ap, int);
__analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
j = __builtin_va_arg (ap, int);
__analyzer_eval (j == 42); /* { dg-warning "TRUE" } */
__builtin_ms_va_end (ap);
}
}
void test_multiple_traversals (void)
{
__analyzer_called_by_test_multiple_traversals (0, 1066, 42);
}
/* Multiple traversals, using va_copy. */
static void __attribute__((noinline))
__analyzer_called_by_test_multiple_traversals_2 (int placeholder, ...)
{
int i, j;
__builtin_ms_va_list args1;
__builtin_ms_va_list args2;
__builtin_ms_va_start (args1, placeholder);
__builtin_ms_va_copy (args2, args1);
/* First traversal. */
i = __builtin_va_arg (args1, int);
__analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
j = __builtin_va_arg (args1, int);
__analyzer_eval (j == 42); /* { dg-warning "TRUE" } */
__builtin_ms_va_end (args1);
/* Traversal of copy. */
i = __builtin_va_arg (args2, int);
__analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
j = __builtin_va_arg (args2, int);
__analyzer_eval (j == 42); /* { dg-warning "TRUE" } */
__builtin_ms_va_end (args2);
}
void test_multiple_traversals_2 (void)
{
__analyzer_called_by_test_multiple_traversals_2 (0, 1066, 42);
}
/* Multiple traversals, using va_copy after a va_arg. */
static void __attribute__((noinline))
__analyzer_called_by_test_multiple_traversals_3 (int placeholder, ...)
{
int i, j;
__builtin_ms_va_list args1;
__builtin_ms_va_list args2;
__builtin_ms_va_start (args1, placeholder);
/* First traversal. */
i = __builtin_va_arg (args1, int);
__analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
/* va_copy after the first va_arg. */
__builtin_ms_va_copy (args2, args1);
j = __builtin_va_arg (args1, int);
__analyzer_eval (j == 42); /* { dg-warning "TRUE" } */
__builtin_ms_va_end (args1);
/* Traversal of copy. */
j = __builtin_va_arg (args2, int);
__analyzer_eval (j == 42); /* { dg-warning "TRUE" } */
__builtin_ms_va_end (args2);
}
void test_multiple_traversals_3 (void)
{
__analyzer_called_by_test_multiple_traversals_3 (0, 1066, 42);
}
/* va_copy after va_end. */
void test_va_copy_after_va_end (int placeholder, ...)
{
__builtin_ms_va_list ap1, ap2;
__builtin_ms_va_start (ap1, placeholder);
__builtin_ms_va_end (ap1); /* { dg-message "'va_end' called here" } */
__builtin_ms_va_copy (ap2, ap1); /* { dg-warning "'va_copy' after 'va_end'" } */
__builtin_ms_va_end (ap2);
}
/* leak of va_copy. */
void test_leak_of_va_copy (int placeholder, ...)
{
__builtin_ms_va_list ap1, ap2;
__builtin_ms_va_start (ap1, placeholder);
__builtin_ms_va_copy (ap2, ap1); /* { dg-message "'va_copy' called here" } */
__builtin_ms_va_end (ap1);
} /* { dg-warning "missing call to 'va_end'" "warning" } */
/* { dg-message "missing call to 'va_end' to match 'va_copy' at \\(1\\)" "final event" { target *-*-* } .-1 } */
/* double va_end. */
void test_double_va_end (int placeholder, ...)
{
__builtin_ms_va_list ap;
__builtin_ms_va_start (ap, placeholder);
__builtin_ms_va_end (ap); /* { dg-message "'va_end' called here" } */
__builtin_ms_va_end (ap); /* { dg-warning "'va_end' after 'va_end'" } */
}
/* double va_start. */
void test_double_va_start (int placeholder, ...)
{
int i;
__builtin_ms_va_list ap;
__builtin_ms_va_start (ap, placeholder); /* { dg-message "'va_start' called here" } */
__builtin_ms_va_start (ap, placeholder); /* { dg-warning "missing call to 'va_end'" "warning" } */
/* { dg-message "missing call to 'va_end' to match 'va_start' at \\(1\\)" "final event" { target *-*-* } .-1 } */
__builtin_ms_va_end (ap);
}
/* va_copy before va_start. */
void test_va_copy_before_va_start (int placeholder, ...)
{
__builtin_ms_va_list ap1; /* { dg-message "region created on stack here" } */
__builtin_ms_va_list ap2;
__builtin_ms_va_copy (ap2, ap1); /* { dg-warning "use of uninitialized value 'ap1'" } */
__builtin_ms_va_end (ap2);
}
/* Verify that we complain about uses of a va_list after the function
in which va_start was called has returned. */
__builtin_ms_va_list global_ap;
static void __attribute__((noinline))
__analyzer_called_by_test_va_arg_after_return (int placeholder, ...)
{
__builtin_ms_va_start (global_ap, placeholder);
__builtin_ms_va_end (global_ap);
}
void test_va_arg_after_return (void)
{
int i;
__analyzer_called_by_test_va_arg_after_return (42, 1066);
i = __builtin_va_arg (global_ap, int); /* { dg-warning "dereferencing pointer 'global_ap' to within stale stack frame" } */
}
void pr107349 (void)
{
__builtin_ms_va_list x,y;
__builtin_ms_va_copy(x,y); /* { dg-warning "use of uninitialized value 'y'" } */
} /* { dg-warning "missing call to 'va_end'" } */