mirror of git://gcc.gnu.org/git/gcc.git
1427 lines
60 KiB
C
1427 lines
60 KiB
C
/* { dg-do compile } */
|
|
/* { dg-options "-std=c99 -Wformat -Wformat-length=1 -ftrack-macro-expansion=0" } */
|
|
/* { dg-require-effective-target int32plus } */
|
|
|
|
/* When debugging, define LINE to the line number of the test case to exercise
|
|
and avoid exercising any of the others. The buffer and objsize macros
|
|
below make use of LINE to avoid warnings for other lines. */
|
|
#ifndef LINE
|
|
# define LINE 0
|
|
#endif
|
|
|
|
#define INT_MAX __INT_MAX__
|
|
|
|
char buffer [256];
|
|
extern char *ptr;
|
|
|
|
/* Evaluate to an array of SIZE characters when non-negative and LINE
|
|
is not set or set to the line the macro is on, or to a pointer to
|
|
an unknown object otherwise. */
|
|
#define buffer(size) \
|
|
(0 <= size && (!LINE || __LINE__ == LINE) \
|
|
? buffer + sizeof buffer - size : ptr)
|
|
|
|
/* Evaluate to SIZE when non-negative and LINE is not set or set to
|
|
the line the macro is on, or to SIZE_MAX otherise. */
|
|
#define objsize(size) \
|
|
(0 <= size && (!LINE || __LINE__ == LINE) \
|
|
? size : __SIZE_MAX__)
|
|
|
|
typedef __SIZE_TYPE__ size_t;
|
|
|
|
#if !__cplusplus
|
|
typedef __WCHAR_TYPE__ wchar_t;
|
|
#endif
|
|
|
|
typedef __WINT_TYPE__ wint_t;
|
|
|
|
typedef unsigned char UChar;
|
|
|
|
const char s0[] = "";
|
|
const char s1[] = "1";
|
|
const char s2[] = "12";
|
|
const char s3[] = "123";
|
|
const char s4[] = "1234";
|
|
const char s5[] = "12345";
|
|
const char s6[] = "123456";
|
|
const char s7[] = "1234567";
|
|
const char s8[] = "12345678";
|
|
|
|
void sink (void*, ...);
|
|
|
|
/* Macro to verify that calls to __builtin_sprintf (i.e., with no size
|
|
argument) issue diagnostics by correctly determining the size of
|
|
the destination buffer. */
|
|
#define T(size, fmt, ...) \
|
|
__builtin_sprintf (buffer (size), fmt, __VA_ARGS__), \
|
|
sink (buffer, ptr);
|
|
|
|
/* Exercise the "%c" and "%lc" directive with constant arguments. */
|
|
|
|
void test_sprintf_c_const (void)
|
|
{
|
|
T (-1, "%c", 0); /* No warning for unknown destination size. */
|
|
T ( 0, "%c", 0); /* { dg-warning ".%c. directive writing 1 byte into a region of size 0" } */
|
|
T ( 1, "%c", 0); /* { dg-warning "writing a terminating nul past the end" } */
|
|
T ( 1, "%c", '1'); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%c", '1');
|
|
T ( 2, "%2c", '1'); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%3c", '1'); /* { dg-warning "into a region" } */
|
|
T ( 2, "%c%c", '1', '2'); /* { dg-warning "nul past the end" } */
|
|
T ( 3, "%c%c", '1', '2');
|
|
|
|
T ( 2, "%1$c%2$c", '1', '2'); /* { dg-warning "does not support %n.|nul past the end" } */
|
|
T ( 3, "%1$c%2$c", '1', '2');
|
|
|
|
/* Verify that a warning is issued for exceeding INT_MAX bytes and
|
|
not otherwise. */
|
|
T (-1, "%*c", INT_MAX - 1, '1');
|
|
T (-1, "%*c", INT_MAX, '1');
|
|
T (-1, "X%*c", INT_MAX - 1, '1');
|
|
T (-1, "X%*c", INT_MAX, '1'); /* { dg-warning "directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
|
|
|
|
T (-1, "%*c%*c", INT_MAX - 1, '1', INT_MAX - 1, '2'); /* { dg-warning "directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
|
|
|
|
T (-1, "%*cX", INT_MAX - 2, '1');
|
|
T (-1, "%*cX", INT_MAX - 1, '1');
|
|
T (-1, "%*cX", INT_MAX, '1'); /* { dg-warning "output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
|
|
}
|
|
|
|
/* Exercise the "%p" directive with constant arguments. */
|
|
|
|
void test_sprintf_p_const (void)
|
|
{
|
|
/* GLIBC and uClibc format null pointers as "(nil)". Sane implementations
|
|
format null pointers as 0 or 0x0 and so the following will only be
|
|
diagnosed on the former targets. */
|
|
T (5, "%p", (void*)0);
|
|
/* { dg-warning "nul past the end" "(nil)" { target *-linux-gnu *-*-uclinux } 96 } */
|
|
|
|
/* The exact output for %p is unspecified by C. Two formats are known:
|
|
same as %tx (for example AIX) and same as %#tx (for example Solaris). */
|
|
T (0, "%p", (void*)0x1); /* { dg-warning ".%p. directive writing . bytes? into a region of size 0" } */
|
|
T (1, "%p", (void*)0x12); /* { dg-warning ".%p. directive writing . bytes? into a region of size 1" } */
|
|
T (2, "%p", (void*)0x123); /* { dg-warning ".%p. directive writing . bytes? into a region of size 2" } */
|
|
|
|
/* GLIBC and uClibc treat the ' ' flag with the "%p" directive the same
|
|
as with signed integer conversions (i.e., it prepends a space). Other
|
|
known implementations ignore it. */
|
|
T (6, "% p", (void*)0x234); /* { dg-warning ". . flag used with .%p." } */
|
|
/* { dg-warning "nul past the end" "Glibc %p" { target *-linux-gnu } 108 } */
|
|
/* { dg-warning "nul past the end" "Generic %p" { target *-*-uclinux } 108 } */
|
|
}
|
|
|
|
/* Verify that no warning is issued for calls that write into a flexible
|
|
array member whose size isn't known. Also verify that calls that use
|
|
a flexible array member as an argument to the "%s" directive do not
|
|
cause a warning. */
|
|
|
|
void test_sprintf_flexarray (void *p, int i)
|
|
{
|
|
struct S
|
|
{
|
|
int n;
|
|
char a [];
|
|
} *s = p;
|
|
|
|
__builtin_sprintf (s->a, "%c", 'x');
|
|
|
|
__builtin_sprintf (s->a, "%s", "");
|
|
__builtin_sprintf (s->a, "%s", "abc");
|
|
__builtin_sprintf (s->a, "abc%sghi", "def");
|
|
|
|
__builtin_sprintf (s->a, "%i", 1234);
|
|
|
|
__builtin_sprintf (buffer (1), "%s", s->a);
|
|
__builtin_sprintf (buffer (1), "%s", s [i].a);
|
|
}
|
|
|
|
/* Same as above but for zero-length arrays. */
|
|
|
|
void test_sprintf_zero_length_array (void *p, int i)
|
|
{
|
|
struct S
|
|
{
|
|
int n;
|
|
char a [0];
|
|
} *s = p;
|
|
|
|
__builtin_sprintf (s->a, "%c", 'x');
|
|
|
|
__builtin_sprintf (s->a, "%s", "");
|
|
__builtin_sprintf (s->a, "%s", "abc");
|
|
__builtin_sprintf (s->a, "abc%sghi", "def");
|
|
|
|
__builtin_sprintf (s->a, "%i", 1234);
|
|
|
|
__builtin_sprintf (buffer (1), "%s", s->a);
|
|
__builtin_sprintf (buffer (1), "%s", s [i].a);
|
|
}
|
|
|
|
/* Verify that the note printed along with the diagnostic mentions
|
|
the correct sizes and refers to the location corresponding to
|
|
the affected directive. */
|
|
|
|
void test_sprintf_note (void)
|
|
{
|
|
#define P __builtin_sprintf
|
|
|
|
/* Diagnostic column numbers are 1-based. */
|
|
|
|
P (buffer (0), /* { dg-message "format output 4 bytes into a destination of size 0" } */
|
|
"%c%s%i", '1', "2", 3); /* { dg-warning "7:.%c. directive writing 1 byte into a region of size 0" } */
|
|
|
|
P (buffer (1), /* { dg-message "format output 6 bytes into a destination of size 1" } */
|
|
"%c%s%i", '1', "23", 45); /* { dg-warning "9:.%s. directive writing 2 bytes into a region of size 0" } */
|
|
|
|
P (buffer (2), /* { dg-message "format output 6 bytes into a destination of size 2" } */
|
|
"%c%s%i", '1', "2", 345); /* { dg-warning "11:.%i. directive writing 3 bytes into a region of size 0" } */
|
|
|
|
/* It would be nice if the caret in the location range for the format
|
|
string below could be made to point at the closing quote of the format
|
|
string, like so:
|
|
sprintf (d, "%c%s%i", '1', "2", 3456);
|
|
~~~~~~^
|
|
Unfortunately, that doesn't work with the current setup. */
|
|
P (buffer (6), /* { dg-message "format output 7 bytes into a destination of size 6" } */
|
|
"%c%s%i", '1', "2", 3456); /* { dg-warning "writing a terminating nul past the end of the destination" } */
|
|
}
|
|
|
|
#undef T
|
|
#define T(size, fmt, ...) \
|
|
__builtin___sprintf_chk (buffer (size), 0, objsize (size), fmt, \
|
|
__VA_ARGS__), sink (buffer, ptr)
|
|
|
|
/* Exercise the "%c" and "%lc" directive with constant arguments. */
|
|
|
|
void test_sprintf_chk_c_const (void)
|
|
{
|
|
T (-1, "%c", 0); /* No warning for unknown destination size. */
|
|
/* Verify the full text of the diagnostic for just the distinct messages
|
|
and use abbreviations in subsequent test cases. */
|
|
T (0, "%c", 0); /* { dg-warning ".%c. directive writing 1 byte into a region of size 0" } */
|
|
T (1, "%c", 0); /* { dg-warning "writing a terminating nul past the end" } */
|
|
T (1, "%c", '1'); /* { dg-warning "nul past the end" } */
|
|
T (2, "%c", '1');
|
|
T (2, "%2c", '1'); /* { dg-warning "nul past the end" } */
|
|
T (2, "%3c", '1'); /* { dg-warning "into a region" } */
|
|
T (2, "%c%c", '1', '2'); /* { dg-warning "nul past the end" } */
|
|
T (3, "%c%c", '1', '2');
|
|
|
|
/* Wide characters. */
|
|
T (0, "%lc", 0); /* { dg-warning "nul past the end" } */
|
|
T (1, "%lc", 0);
|
|
T (1, "%lc%lc", 0, 0);
|
|
T (2, "%lc", 0);
|
|
T (2, "%lc%lc", 0, 0);
|
|
|
|
/* The following could result in as few as no bytes and in as many as
|
|
MB_CUR_MAX, but since the MB_CUR_MAX value is a runtime property
|
|
the write cannot be reliably diagnosed. */
|
|
T (2, "%lc", (wint_t)L'1');
|
|
T (2, "%1lc", (wint_t)L'1');
|
|
/* Writing some unknown number of bytes into a field two characters wide. */
|
|
T (2, "%2lc", (wint_t)L'1'); /* { dg-warning "nul past the end" } */
|
|
|
|
T (3, "%lc%c", (wint_t)L'1', '2');
|
|
/* Here in the best case each argument will format as single character,
|
|
causing the terminating NUL to be written past the end. */
|
|
T (3, "%lc%c%c", (wint_t)L'1', '2', '3'); /* { dg-warning "nul past the end" } */
|
|
T (3, "%lc%lc%c", (wint_t)L'1', (wint_t)L'2', '3'); /* { dg-warning "nul past the end" } */
|
|
}
|
|
|
|
/* Exercise the "%s" and "%ls" directive with constant arguments. */
|
|
|
|
void test_sprintf_chk_s_const (void)
|
|
{
|
|
T (-1, "%*s", 0, ""); /* No warning for unknown destination size. */
|
|
T ( 0, "%*s", 0, ""); /* { dg-warning "nul past the end" } */
|
|
T ( 0, "%-s", ""); /* { dg-warning "nul past the end" } */
|
|
T ( 0, "%*s", 0, s0); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%*s", 0, "");
|
|
T ( 1, "%*s", 0, s0);
|
|
T ( 1, "%*s", 0, "\0");
|
|
T ( 1, "%*s", 0, "1"); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%*s", 0, s1); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%1s", ""); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%1s", s0); /* { dg-warning "nul past the end" } */
|
|
T (-1, "%1s", "1"); /* No warning for unknown destination size. */
|
|
T ( 1, "%*s", 1, ""); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%*s", 1, s0); /* { dg-warning "nul past the end" } */
|
|
T (-1, "%*s", 1, s0); /* No warning for unknown destination size. */
|
|
|
|
T (1, "%.0s", "123");
|
|
T (1, "%.0s", s3);
|
|
T (1, "%.*s", 0, "123");
|
|
T (1, "%.*s", 0, s3);
|
|
T (1, "%.1s", "123"); /* { dg-warning "nul past the end" } */
|
|
T (1, "%.1s", s3); /* { dg-warning "nul past the end" } */
|
|
T (1, "%.*s", 1, "123"); /* { dg-warning "nul past the end" } */
|
|
T (1, "%.*s", 1, s3); /* { dg-warning "nul past the end" } */
|
|
|
|
T (2, "%.*s", 0, "");
|
|
T (2, "%.*s", 0, "1");
|
|
T (2, "%.*s", 0, s1);
|
|
T (2, "%.*s", 0, "1\0");
|
|
T (2, "%.*s", 0, "12");
|
|
T (2, "%.*s", 0, s2);
|
|
|
|
T (2, "%.*s", 1, "");
|
|
T (2, "%.*s", 1, "1");
|
|
T (2, "%.*s", 1, s1);
|
|
T (2, "%.*s", 1, "1\0");
|
|
T (2, "%.*s", 1, "12");
|
|
T (2, "%.*s", 1, s2);
|
|
|
|
T (2, "%.*s", 2, "");
|
|
T (2, "%.*s", 2, "1");
|
|
T (2, "%.*s", 2, s1);
|
|
T (2, "%.*s", 2, "1\0");
|
|
T (2, "%.*s", 2, "12"); /* { dg-warning "nul past the end" } */
|
|
T (2, "%.*s", 2, s2); /* { dg-warning "nul past the end" } */
|
|
|
|
T (2, "%.*s", 3, "");
|
|
T (2, "%.*s", 3, "1");
|
|
T (2, "%.*s", 3, s1);
|
|
T (2, "%.*s", 3, "1\0");
|
|
T (2, "%.*s", 3, "12"); /* { dg-warning "nul past the end" } */
|
|
T (2, "%.*s", 3, "123"); /* { dg-warning "into a region" } */
|
|
T (2, "%.*s", 3, s2); /* { dg-warning "nul past the end" } */
|
|
T (2, "%.*s", 3, s3); /* { dg-warning "into a region" } */
|
|
|
|
T (2, "%*s", 0, "");
|
|
T (2, "%*s", 0, "1");
|
|
T (2, "%*s", 0, s1);
|
|
T (2, "%*s", 0, "1\0");
|
|
T (2, "%*s", 0, "12"); /* { dg-warning "nul past the end" } */
|
|
T (2, "%*s", 0, s2); /* { dg-warning "nul past the end" } */
|
|
|
|
/* Verify that output in excess of INT_MAX bytes is diagnosed even
|
|
when the size of the destination object is unknown. */
|
|
T (-1, "%*s", INT_MAX - 1, "");
|
|
T (-1, "%*s", INT_MAX, "");
|
|
T (-1, "X%*s", INT_MAX, ""); /* { dg-warning "directive output of \[0-9\]+ bytes causes result to exceed .INT_MAX." } */
|
|
|
|
/* Multiple directives. */
|
|
|
|
T (1, "%s%s", "", "");
|
|
T (1, "%s%s", s0, s0);
|
|
T (1, "%s%s", "", "1"); /* { dg-warning "nul past the end" } */
|
|
T (1, "%s%s", s0, s1); /* { dg-warning "nul past the end" } */
|
|
T (1, "%s%s", "1", ""); /* { dg-warning "nul past the end" } */
|
|
T (1, "%s%s", s1, s0); /* { dg-warning "nul past the end" } */
|
|
T (1, "%s%s", "1", "2"); /* { dg-warning "into a region" } */
|
|
T (1, "%s%s", s1, s1); /* { dg-warning "into a region" } */
|
|
|
|
T (2, "%s%s", "", "");
|
|
T (2, "%s%s", "", "1");
|
|
T (2, "%s%s", "1", "");
|
|
T (2, "%s%s", "", "12"); /* { dg-warning "nul past the end" } */
|
|
T (2, "%s%s", "1", "2"); /* { dg-warning "nul past the end" } */
|
|
T (2, "%s%s", "12", "2"); /* { dg-warning "into a region" } */
|
|
T (2, "%s%s", "1", "23"); /* { dg-warning "into a region" } */
|
|
T (2, "%s%s", "12", "3"); /* { dg-warning "into a region" } */
|
|
T (2, "%s%s", "12", "34"); /* { dg-warning "into a region" } */
|
|
|
|
T (2, "_%s", "");
|
|
T (2, "%%%s", "");
|
|
T (2, "%s%%", "");
|
|
T (2, "_%s", "1"); /* { dg-warning "nul past the end" } */
|
|
T (2, "%%%s", "1"); /* { dg-warning "nul past the end" } */
|
|
T (2, "%s%%", "1"); /* { dg-warning "nul past the end" } */
|
|
T (2, "_%s", "12"); /* { dg-warning "into a region" } */
|
|
T (2, "__%s", "1"); /* { dg-warning "into a region" } */
|
|
|
|
T (2, "%1$s%2$s", "12", "3"); /* { dg-warning ".%2.s. directive writing 1 byte into a region of size 0" } */
|
|
T (2, "%1$s%1$s", "12"); /* { dg-warning "does not support|.%1.s. directive writing 2 bytes into a region of size 0" } */
|
|
T (2, "%2$s%1$s", "1", "23"); /* { dg-warning ".%1.s. directive writing 1 byte into a region of size 0" } */
|
|
T (2, "%2$s%2$s", "1", "23"); /* { dg-warning "unused|%2.s. directive writing 2 bytes into a region of size 0" } */
|
|
|
|
T (3, "__%s", "");
|
|
T (3, "__%s", "1"); /* { dg-warning "nul past the end" } */
|
|
T (3, "%s_%s", "", "");
|
|
T (3, "%s_%s", "1", "");
|
|
T (3, "%s_%s", "", "1");
|
|
T (3, "%s_%s", "1", "2"); /* { dg-warning "nul past the end" } */
|
|
|
|
/* Wide strings. */
|
|
T (-1, "%ls", L"");
|
|
T ( 0, "%ls", L""); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%ls", L"");
|
|
T ( 1, "%ls", L"\0");
|
|
T ( 1, "%1ls", L""); /* { dg-warning "nul past the end" } */
|
|
|
|
T (0, "%*ls", 0, L""); /* { dg-warning "nul past the end" } */
|
|
T (1, "%*ls", 0, L"");
|
|
T (1, "%*ls", 0, L"\0");
|
|
T (1, "%*ls", 1, L""); /* { dg-warning "nul past the end" } */
|
|
|
|
T (1, "%ls", L"1"); /* { dg-warning "nul past the end" } */
|
|
T (1, "%.0ls", L"1");
|
|
T (2, "%.0ls", L"1");
|
|
T (2, "%.1ls", L"1");
|
|
T (2, "%.*ls", 1, L"1");
|
|
|
|
/* The "%.2ls" directive below will write at a minimum 1 byte (because
|
|
L"1" is known and can be assumed to convert to at least one multibyte
|
|
character), and at most 2 bytes because of the precision. Since its
|
|
output is explicitly bounded it is diagnosed. */
|
|
T (2, "%.2ls", L"1"); /* { dg-warning "nul past the end" } */
|
|
T (2, "%.*ls", 2, L"1"); /* { dg-warning "nul past the end" } */
|
|
|
|
T (3, "%.0ls", L"1");
|
|
T (3, "%.1ls", L"1");
|
|
T (3, "%.2ls", L"1");
|
|
}
|
|
|
|
/* Exercise the "%hhd", "%hhi", "%hho", "%hhu", and "%hhx" directives
|
|
with constant arguments. */
|
|
|
|
void test_sprintf_chk_hh_const (void)
|
|
{
|
|
T (-1, "%hhd", 0);
|
|
|
|
T (1, "%hhd", 0); /* { dg-warning "nul past the end" } */
|
|
T (1, "%hhd", 1); /* { dg-warning "nul past the end" } */
|
|
T (1, "%hhd", -1); /* { dg-warning "into a region" } */
|
|
T (1, "%+hhd", 0); /* { dg-warning "into a region" } */
|
|
T (1, "%+hhd", 1); /* { dg-warning "into a region" } */
|
|
T (1, "%-hhd", 0); /* { dg-warning "nul past the end" } */
|
|
|
|
T (1, "%hhi", 0); /* { dg-warning "nul past the end" } */
|
|
T (1, "%hhi", 1); /* { dg-warning "nul past the end" } */
|
|
T (1, "%hhi", -1); /* { dg-warning "into a region" } */
|
|
T (1, "%+hhi", 0); /* { dg-warning "into a region" } */
|
|
T (1, "%+hhi", 1); /* { dg-warning "into a region" } */
|
|
T (1, "%-hhi", 0); /* { dg-warning "nul past the end" } */
|
|
|
|
T (2, "%hhi", 0);
|
|
T (2, "%hhi", 1);
|
|
T (2, "%hhi", 9);
|
|
T (2, "% hhi", 9); /* { dg-warning "nul past the end" } */
|
|
T (2, "%+hhi", 9); /* { dg-warning "nul past the end" } */
|
|
T (2, "%-hhi", 9);
|
|
T (2, "%hhi", 10); /* { dg-warning "nul past the end" } */
|
|
T (2, "%hhi", -1); /* { dg-warning "nul past the end" } */
|
|
T (2, "% hhi", -1); /* { dg-warning "nul past the end" } */
|
|
T (2, "%+hhi", -1); /* { dg-warning "nul past the end" } */
|
|
T (2, "%-hhi", -1); /* { dg-warning "nul past the end" } */
|
|
|
|
T (2, "%hho", 0);
|
|
T (2, "%hho", 1);
|
|
T (2, "%hho", 7);
|
|
T (2, "%hho", 010); /* { dg-warning "nul past the end" } */
|
|
T (2, "%hho", 077); /* { dg-warning "nul past the end" } */
|
|
T (2, "%hho", -1); /* { dg-warning "into a region" } */
|
|
|
|
T (2, "%hhx", 0);
|
|
T (2, "%hhX", 1);
|
|
T (2, "%hhx", 7);
|
|
T (2, "%hhX", 8);
|
|
T (2, "%hhx", -1); /* { dg-warning "nul past the end" } */
|
|
T (2, "%hhX", 0xf);
|
|
T (2, "%hhx", 0x10); /* { dg-warning "nul past the end" } */
|
|
T (2, "%hhX", 0xff); /* { dg-warning "nul past the end" } */
|
|
|
|
T (1, "%#hhx", 0); /* { dg-warning "nul past the end" } */
|
|
T (2, "%#hhx", 0);
|
|
T (3, "%#hhx", 1); /* { dg-warning "nul past the end" } */
|
|
|
|
T (4, "%hhd", 255);
|
|
T (4, "%hhd", 256);
|
|
T (4, "%hhd", 0xfff);
|
|
T (4, "%hhd", 0xffff);
|
|
|
|
T (4, "%hhi", 255);
|
|
T (4, "%hhi", 256);
|
|
T (4, "%hhi", 0xfff);
|
|
T (4, "%hhi", 0xffff);
|
|
|
|
T (4, "%hhu", -1);
|
|
T (4, "%hhu", 255);
|
|
T (4, "%hhu", 256);
|
|
T (4, "%hhu", 0xfff);
|
|
T (4, "%hhu", 0xffff);
|
|
|
|
T (4, "%#hhx", 0);
|
|
T (4, "%#hhx", 1);
|
|
T (4, "%#hhx", -1); /* { dg-warning "nul past the end" } */
|
|
T (4, "%#hhx", 0xf);
|
|
T (4, "%#hhx", 0x10); /* { dg-warning "nul past the end" } */
|
|
T (4, "%#hhx", 0xff); /* { dg-warning "nul past the end" } */
|
|
T (4, "%#hhx", 0xfff); /* { dg-warning "nul past the end" } */
|
|
|
|
T (4, "%hhi %hhi", 0, 0);
|
|
T (4, "%hhi %hhi", 9, 9);
|
|
T (4, "%hhi %hhi", 1, 10); /* { dg-warning "nul past the end" } */
|
|
T (4, "%hhi %hhi", 10, 1); /* { dg-warning "nul past the end" } */
|
|
T (4, "%hhi %hhi", 11, 12); /* { dg-warning "into a region" } */
|
|
|
|
T (5, "%0*hhd %0*hhi", 0, 7, 0, 9);
|
|
T (5, "%0*hhd %0*hhi", 1, 7, 1, 9);
|
|
T (5, "%0*hhd %0*hhi", 1, 7, 2, 9);
|
|
T (5, "%0*hhd %0*hhi", 2, 7, 1, 9);
|
|
T (5, "%0*hhd %0*hhi", 2, 7, 2, 9); /* { dg-warning "nul past the end" } */
|
|
T (5, "%0*hhd %0*hhi", 0, 12, 0, 123); /* { dg-warning ".%0\\*hhi. directive writing 3 bytes into a region of size 2" } */
|
|
T (5, "%0*hhd %0*hhi", 1, 12, 1, 123); /* { dg-warning ".%0\\*hhi. directive writing 3 bytes into a region of size 2" } */
|
|
T (5, "%0*hhd %0*hhi", 2, 12, 3, 123); /* { dg-warning ".%0\\*hhi. directive writing 3 bytes into a region of size 2" } */
|
|
|
|
/* FIXME: Move the boundary test cases into a file of their own that's
|
|
exercised only on targets with the matching type limits (otherwise
|
|
they'll fail). */
|
|
#undef MAX
|
|
#define MAX 127
|
|
|
|
#undef MIN
|
|
#define MIN (-MAX -1)
|
|
|
|
T (1, "%hhi", MAX); /* { dg-warning "into a region" } */
|
|
T (1, "%hhi", MIN); /* { dg-warning "into a region" } */
|
|
T (1, "%hhi", MAX + 1); /* { dg-warning "into a region" } */
|
|
|
|
T (2, "%hhi", MAX + 1); /* { dg-warning "into a region" } */
|
|
T (2, "%hhi", MAX + 10); /* { dg-warning "into a region" } */
|
|
T (2, "%hhi", MAX + 100); /* { dg-warning "into a region" } */
|
|
}
|
|
|
|
/* Exercise the "%hhd", "%hi", "%ho", "%hu", and "%hx" directives
|
|
with constant arguments. */
|
|
|
|
void test_sprintf_chk_h_const (void)
|
|
{
|
|
T (1, "%hu", 0); /* { dg-warning "nul past the end" } */
|
|
T (1, "%hu", 1); /* { dg-warning "nul past the end" } */
|
|
T (1, "%hu", -1); /* { dg-warning "into a region" } */
|
|
|
|
T (2, "%hi", 0);
|
|
T (2, "%hi", 1);
|
|
T (2, "%hi", 9);
|
|
T (2, "% hi", 9); /* { dg-warning "nul past the end" } */
|
|
T (2, "%+hi", 9); /* { dg-warning "nul past the end" } */
|
|
T (2, "%-hi", 9);
|
|
T (2, "%hi", 10); /* { dg-warning "nul past the end" } */
|
|
T (2, "%hi", -1); /* { dg-warning "nul past the end" } */
|
|
T (2, "% hi", -2); /* { dg-warning "nul past the end" } */
|
|
T (2, "%+hi", -3); /* { dg-warning "nul past the end" } */
|
|
T (2, "%-hi", -4); /* { dg-warning "nul past the end" } */
|
|
|
|
T (2, "%hu", 0);
|
|
T (2, "%hu", 1);
|
|
T (2, "%hu", 9);
|
|
T (2, "%hu", 10); /* { dg-warning "nul past the end" } */
|
|
T (2, "%hu", -1); /* { dg-warning "into a region" } */
|
|
|
|
T (2, "%ho", 0);
|
|
T (2, "%ho", 1);
|
|
T (2, "%ho", 7);
|
|
T (2, "%ho", 010); /* { dg-warning "nul past the end" } */
|
|
T (2, "%ho", 077); /* { dg-warning "nul past the end" } */
|
|
T (2, "%ho", 0100); /* { dg-warning "into a region" } */
|
|
T (2, "%ho", -1); /* { dg-warning "into a region" } */
|
|
|
|
T (2, "%hx", 0);
|
|
T (2, "%hx", 1);
|
|
T (2, "%hx", 7);
|
|
T (2, "%hx", 0xf);
|
|
T (2, "%hx", 0x10); /* { dg-warning "nul past the end" } */
|
|
T (2, "%hx", 0xff); /* { dg-warning "nul past the end" } */
|
|
T (2, "%hx", 0x100); /* { dg-warning "into a region" } */
|
|
T (2, "%hx", -1); /* { dg-warning "into a region" } */
|
|
|
|
T (3, "% hi", 7);
|
|
T (3, "%+hi", 8);
|
|
T (3, "%-hi", 9);
|
|
T (3, "%hi", 10);
|
|
T (3, "%hi", -1);
|
|
T (3, "% hi", -2);
|
|
T (3, "%+hi", -3);
|
|
T (3, "%-hi", -4);
|
|
|
|
T (5, "%hu", 9999);
|
|
T (5, "%hu", 10000); /* { dg-warning "nul past the end" } */
|
|
T (5, "%hu", 65535); /* { dg-warning "nul past the end" } */
|
|
|
|
T (1, "%#hx", 0); /* { dg-warning "nul past the end" } */
|
|
T (2, "%#hx", 0);
|
|
T (3, "%#hx", 1); /* { dg-warning "nul past the end" } */
|
|
|
|
T (4, "%#hx", 0);
|
|
T (4, "%#hx", 1);
|
|
T (4, "%#hx", 0xf);
|
|
T (4, "%#hx", 0x10); /* { dg-warning "nul past the end" } */
|
|
T (4, "%#hx", 0xff); /* { dg-warning "nul past the end" } */
|
|
T (4, "%#hx", 0x100); /* { dg-warning "into a region" } */
|
|
T (4, "%#hx", -1); /* { dg-warning "into a region" } */
|
|
|
|
#undef MAX
|
|
#define MAX 65535
|
|
|
|
T (1, "%hhu", 0); /* { dg-warning "nul past the end" } */
|
|
T (1, "%hhu", 1); /* { dg-warning "nul past the end" } */
|
|
T (1, "%hhu", -1); /* { dg-warning "into a region" } */
|
|
T (1, "%hhu", MAX); /* { dg-warning "into a region" } */
|
|
T (1, "%hhu", MAX + 1); /* { dg-warning "nul past the end" } */
|
|
}
|
|
|
|
/* Exercise the "%d", "%i", "%o", "%u", and "%x" directives with
|
|
constant arguments. */
|
|
|
|
void test_sprintf_chk_integer_const (void)
|
|
{
|
|
T ( 1, "%i", 0); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%i", 1); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%i", -1); /* { dg-warning "into a region" } */
|
|
T ( 1, "%i_", 1); /* { dg-warning "character ._. at offset 2 past the end" } */
|
|
T ( 1, "_%i", 1); /* { dg-warning "into a region" } */
|
|
T ( 1, "_%i_", 1); /* { dg-warning "into a region" } */
|
|
T ( 1, "%o", 0); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%u", 0); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%x", 0); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%#x", 0); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%x", 1); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%#x", 1); /* { dg-warning "into a region" } */
|
|
|
|
T ( 2, "%i", 0);
|
|
T ( 2, "%i", 1);
|
|
T ( 2, "%i", 9);
|
|
T ( 2, "%i", -1); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%i", 10); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%i_", 0); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "_%i", 0); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "_%i_", 0); /* { dg-warning "character ._. at offset 3 past the end" } */
|
|
T ( 2, "%o", 1);
|
|
T ( 2, "%o", 7);
|
|
T ( 2, "%o", 010); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%o", 0100); /* { dg-warning "into a region" } */
|
|
T ( 2, "%x", 1);
|
|
T ( 2, "%#x", 1); /* { dg-warning "into a region" } */
|
|
T ( 2, "%x", 0xa);
|
|
T ( 2, "%x", 0xf);
|
|
T ( 2, "%x", 0x10); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%x", 0xff); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%x", 0x1ff); /* { dg-warning "into a region" } */
|
|
|
|
T ( 3, "%i", 0);
|
|
T ( 3, "%i", 1);
|
|
T ( 3, "%i", 9);
|
|
T ( 3, "%i", -9);
|
|
T ( 3, "%i", 10);
|
|
T ( 3, "%i", 99);
|
|
T ( 3, "%i", -99); /* { dg-warning "nul past the end" } */
|
|
|
|
/* ~0U is formatted into exactly three bytes as "-1" followed by
|
|
the terminating NUL character. */
|
|
T ( 3, "%+i", ~0U);
|
|
T ( 3, "%-i", ~0U);
|
|
T ( 3, "% i", ~0U);
|
|
|
|
T ( 8, "%8u", 1); /* { dg-warning "nul past the end" } */
|
|
T ( 9, "%8u", 1);
|
|
|
|
T ( 7, "%1$i%2$i%3$i", 1, 23, 456);
|
|
T ( 8, "%1$i%2$i%3$i%1$i", 1, 23, 456);
|
|
T ( 8, "%1$i%2$i%3$i%2$i", 1, 23, 456); /* { dg-warning "nul past the end" } */
|
|
T ( 8, "%1$i%2$i%3$i%3$i", 1, 23, 456); /* { dg-warning "into a region" } */
|
|
|
|
#undef MAX
|
|
#define MAX 2147483647 /* 10 digits. */
|
|
#undef MIN
|
|
#define MIN (-MAX -1) /* Sign plus 10 digits. */
|
|
|
|
T ( 1, "%i", MAX); /* { dg-warning "into a region" } */
|
|
T ( 1, "%i", MIN); /* { dg-warning "into a region" } */
|
|
T ( 2, "%i", MAX); /* { dg-warning "into a region" } */
|
|
T ( 2, "%i", MIN); /* { dg-warning "into a region" } */
|
|
T (10, "%i", 123456789);
|
|
T (10, "%i", -123456789); /* { dg-warning "nul past the end" } */
|
|
T (10, "%i", MAX); /* { dg-warning "nul past the end" } */
|
|
T (10, "%i", MIN); /* { dg-warning "into a region" } */
|
|
|
|
T (11, "%i", MAX);
|
|
T (11, "%i", MIN); /* { dg-warning "nul past the end" } */
|
|
}
|
|
|
|
/* Exercise the "%jd", "%ji", "%jo", "%ju", and "%jx" directives
|
|
for the formatting of intmax_t and uintmax_t values with constant
|
|
arguments. */
|
|
|
|
void test_sprintf_chk_j_const (void)
|
|
{
|
|
#define I(x) ((__INTMAX_TYPE__)x)
|
|
|
|
T ( 1, "%ji", I ( 0)); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%ji", I ( 1)); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%ji", I ( -1)); /* { dg-warning "into a region" } */
|
|
T ( 1, "%ji_", I ( 1)); /* { dg-warning "character ._. at offset 3 past the end" } */
|
|
T ( 1, "_%ji", I ( 1)); /* { dg-warning "into a region" } */
|
|
T ( 1, "_%ji_",I ( 1)); /* { dg-warning "into a region" } */
|
|
T ( 1, "%jo", I ( 0)); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%ju", I ( 0)); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%jx", I ( 0)); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%#jx", I ( 0)); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%jx", I ( 1)); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%#jx", I ( 1)); /* { dg-warning "into a region" } */
|
|
|
|
T ( 2, "%ji", I ( 0));
|
|
T ( 2, "%ji", I ( 1));
|
|
T ( 2, "%ji", I ( 9));
|
|
T ( 2, "%ji", I ( -1)); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%ji", I ( 10)); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%ji_", I ( 0)); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "_%ji", I ( 0)); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "_%ji_",I ( 0)); /* { dg-warning "character ._. at offset 4 past the end" } */
|
|
T ( 2, "%jo", I ( 1));
|
|
T ( 2, "%jo", I ( 7));
|
|
T ( 2, "%jo", I ( 010)); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%jo", I ( 0100)); /* { dg-warning "into a region" } */
|
|
T ( 2, "%jx", I ( 1));
|
|
T ( 2, "%#jx", I ( 1)); /* { dg-warning "into a region" } */
|
|
T ( 2, "%jx", I ( 0xa));
|
|
T ( 2, "%jx", I ( 0xf));
|
|
T ( 2, "%jx", I ( 0x10)); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%jx", I ( 0xff)); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%jx", I (0x1ff)); /* { dg-warning "into a region" } */
|
|
|
|
T ( 3, "%ji", I ( 0));
|
|
T ( 3, "%ji", I ( 1));
|
|
T ( 3, "%ji", I ( 9));
|
|
T ( 3, "%ji", I ( -9));
|
|
T ( 3, "%ji", I ( 10));
|
|
T ( 3, "%ji", I ( 99));
|
|
T ( 3, "%ji", I ( -99)); /* { dg-warning "nul past the end" } */
|
|
|
|
/* ~0 is formatted into exactly three bytes as "-1" followed by
|
|
the terminating NUL character. */
|
|
T ( 3, "%+ji", ~I (0));
|
|
T ( 3, "%-ji", ~I (0));
|
|
T ( 3, "% ji", ~I (0));
|
|
|
|
T ( 8, "%8ju", I (1)); /* { dg-warning "nul past the end" } */
|
|
T ( 9, "%8ju", I (1));
|
|
}
|
|
|
|
/* Exercise the "%ld", "%li", "%lo", "%lu", and "%lx" directives
|
|
with constant arguments. */
|
|
|
|
void test_sprintf_chk_l_const (void)
|
|
{
|
|
T ( 1, "%li", 0L); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%li", 1L); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%li", -1L); /* { dg-warning "into a region" } */
|
|
T ( 1, "%li_", 1L); /* { dg-warning "character ._. at offset 3 past the end" } */
|
|
T ( 1, "_%li", 1L); /* { dg-warning "into a region" } */
|
|
T ( 1, "_%li_", 1L); /* { dg-warning "into a region" } */
|
|
T ( 1, "%lo", 0L); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%lu", 0L); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%lx", 0L); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%#lx", 0L); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%lx", 1L); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%#lx", 1L); /* { dg-warning "into a region" } */
|
|
|
|
T ( 2, "%li", 0L);
|
|
T ( 2, "%li", 1L);
|
|
T ( 2, "%li", 9L);
|
|
T ( 2, "%li", -1L); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%li", 10L); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%li_", 0L); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "_%li", 0L); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "_%li_", 0L); /* { dg-warning "character ._. at offset 4 past the end" } */
|
|
T ( 2, "%lo", 1L);
|
|
T ( 2, "%lo", 7L);
|
|
T ( 2, "%lo", 010L); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%lo", 0100L); /* { dg-warning "into a region" } */
|
|
T ( 2, "%lx", 1L);
|
|
T ( 2, "%#lx", 1L); /* { dg-warning "into a region" } */
|
|
T ( 2, "%lx", 0xaL);
|
|
T ( 2, "%lx", 0xfL);
|
|
T ( 2, "%lx", 0x10L); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%lx", 0xffL); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%lx", 0x1ffL); /* { dg-warning "into a region" } */
|
|
|
|
T ( 3, "%li", 0L);
|
|
T ( 3, "%li", 1L);
|
|
T ( 3, "%li", 9L);
|
|
T ( 3, "%li", -9L);
|
|
T ( 3, "%li", 10L);
|
|
T ( 3, "%li", 99L);
|
|
T ( 3, "%li", -99L); /* { dg-warning "nul past the end" } */
|
|
|
|
/* ~0U is formatted into exactly three bytes as "-1" followed by
|
|
the terminating NUL character. */
|
|
T ( 3, "%+li", ~0LU);
|
|
T ( 3, "%-li", ~0LU);
|
|
T ( 3, "% li", ~0LU);
|
|
|
|
T ( 8, "%8lu", 1L); /* { dg-warning "nul past the end" } */
|
|
T ( 9, "%8lu", 1L);
|
|
}
|
|
|
|
/* Exercise the "%lld", "%lli", "%llo", "%llu", and "%llx" directives
|
|
with constant arguments. */
|
|
|
|
void test_sprintf_chk_ll_const (void)
|
|
{
|
|
T ( 1, "%lli", 0LL); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%lli", 1LL); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%lli", -1LL); /* { dg-warning "into a region" } */
|
|
T ( 1, "%lli_", 1LL); /* { dg-warning "character ._. at offset 4 past the end" } */
|
|
T ( 1, "_%lli", 1LL); /* { dg-warning "into a region" } */
|
|
T ( 1, "_%lli_", 1LL); /* { dg-warning "into a region" } */
|
|
T ( 1, "%llo", 0LL); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%llu", 0LL); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%llx", 0LL); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%#llx", 0LL); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%llx", 1LL); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%#llx", 1LL); /* { dg-warning "into a region" } */
|
|
|
|
T ( 2, "%lli", 0LL);
|
|
T ( 2, "%lli", 1LL);
|
|
T ( 2, "%lli", 9LL);
|
|
T ( 2, "%lli", -1LL); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%lli", 10LL); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%lli_", 0LL); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "_%lli", 0LL); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "_%lli_", 0LL); /* { dg-warning "character ._. at offset 5 past the end" } */
|
|
T ( 2, "%llo", 1LL);
|
|
T ( 2, "%llo", 7LL);
|
|
T ( 2, "%llo", 010LL); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%llo", 0100LL); /* { dg-warning "into a region" } */
|
|
T ( 2, "%llx", 1LL);
|
|
T ( 2, "%#llx", 1LL); /* { dg-warning "into a region" } */
|
|
T ( 2, "%llx", 0xaLL);
|
|
T ( 2, "%llx", 0xfLL);
|
|
T ( 2, "%llx", 0x10LL); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%llx", 0xffLL); /* { dg-warning "nul past the end" } */
|
|
T ( 2, "%llx", 0x1ffLL); /* { dg-warning "into a region" } */
|
|
|
|
T ( 3, "%lli", 0LL);
|
|
T ( 3, "%lli", 1LL);
|
|
T ( 3, "%lli", 9LL);
|
|
T ( 3, "%lli", -9LL);
|
|
T ( 3, "%lli", 10LL);
|
|
T ( 3, "%lli", 99LL);
|
|
T ( 3, "%lli", -99LL); /* { dg-warning "nul past the end" } */
|
|
|
|
/* ~0U is formatted into exactly three bytes as "-1" followed by
|
|
the terminating NUL character. */
|
|
T ( 3, "%+lli", ~0LLU);
|
|
T ( 3, "%-lli", ~0LLU);
|
|
T ( 3, "% lli", ~0LLU);
|
|
|
|
T ( 8, "%8llu", 1LL); /* { dg-warning "nul past the end" } */
|
|
T ( 9, "%8llu", 1LL);
|
|
|
|
/* assume 64-bit long long. */
|
|
#define LLONG_MAX 9223372036854775807LL /* 19 bytes */
|
|
#define LLONG_MIN (-LLONG_MAX - 1) /* 20 bytes */
|
|
|
|
T (18, "%lli", LLONG_MIN); /* { dg-warning "into a region" } */
|
|
T (19, "%lli", LLONG_MIN); /* { dg-warning "into a region" } */
|
|
T (20, "%lli", LLONG_MIN); /* { dg-warning "nul past the end" } */
|
|
T (21, "%lli", LLONG_MIN);
|
|
|
|
T (18, "%lli", LLONG_MAX); /* { dg-warning "into a region" } */
|
|
T (19, "%lli", LLONG_MAX); /* { dg-warning "nul past the end" } */
|
|
T (20, "%lli", LLONG_MAX);
|
|
|
|
T (21, "%llo", -1LL); /* { dg-warning "into a region" } */
|
|
T (22, "%llo", -1LL); /* { dg-warning "nul past the end" } */
|
|
T (23, "%llo", -1LL);
|
|
|
|
T (19, "%llu", -1LL); /* { dg-warning "into a region" } */
|
|
T (20, "%llu", -1LL); /* { dg-warning "nul past the end" } */
|
|
T (21, "%llu", -1LL);
|
|
|
|
T (15, "%llx", -1LL); /* { dg-warning "into a region" } */
|
|
T (16, "%llx", -1LL); /* { dg-warning "nul past the end" } */
|
|
T (17, "%llx", -1LL);
|
|
}
|
|
|
|
void test_sprintf_chk_L_const (void)
|
|
{
|
|
T (-1, "%Li", 0LL);
|
|
T ( 1, "%Li", 0LL); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%Li", 1LL); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%Li", -1LL); /* { dg-warning "into a region" } */
|
|
T ( 1, "%Li_", 1LL); /* { dg-warning "character ._. at offset 3 past the end" } */
|
|
T ( 1, "_%Li", 1LL); /* { dg-warning "into a region" } */
|
|
T ( 1, "_%Li_", 1LL); /* { dg-warning "into a region" } */
|
|
}
|
|
|
|
void test_sprintf_chk_z_const (void)
|
|
{
|
|
T (-1, "%zi", (size_t)0);
|
|
T ( 1, "%zi", (size_t)0); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%zi", (size_t)1); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%zi", (size_t)-1L);/* { dg-warning "into a region" } */
|
|
T ( 1, "%zi_", (size_t)1); /* { dg-warning "character ._. at offset 3 past the end" } */
|
|
T ( 1, "_%zi", (size_t)1); /* { dg-warning "into a region" } */
|
|
T ( 1, "_%zi_", (size_t)1); /* { dg-warning "into a region" } */
|
|
|
|
T ( 2, "%zu", (size_t)1);
|
|
T ( 2, "%zu", (size_t)9);
|
|
T ( 2, "%zu", (size_t)10); /* { dg-warning "nul past the end" } */
|
|
}
|
|
|
|
void test_sprintf_chk_e_const (void)
|
|
{
|
|
T (-1, "%E", 0.0);
|
|
T (-1, "%lE", 0.0);
|
|
|
|
T ( 0, "%E", 0.0); /* { dg-warning "into a region" } */
|
|
T ( 0, "%e", 0.0); /* { dg-warning "into a region" } */
|
|
T ( 1, "%E", 1.0); /* { dg-warning "into a region" } */
|
|
T ( 1, "%e", 1.0); /* { dg-warning "into a region" } */
|
|
T ( 2, "%e", 2.0); /* { dg-warning "into a region" } */
|
|
T ( 3, "%e", 3.0); /* { dg-warning "into a region" } */
|
|
T (12, "%e", 1.2); /* { dg-warning "nul past the end" } */
|
|
T (12, "%e", 12.0); /* { dg-warning "nul past the end" } */
|
|
T (13, "%e", 1.3); /* 1.300000e+00 */
|
|
T (13, "%E", 13.0); /* 1.300000e+01 */
|
|
T (13, "%e", 13.0);
|
|
T (13, "%E", 1.4e+99); /* 1.400000e+99 */
|
|
T (13, "%e", 1.5e+100); /* { dg-warning "nul past the end" } */
|
|
T (14, "%E", 1.6e+101); /* 1.600000E+101 */
|
|
T (14, "%e", -1.7e+102); /* { dg-warning "nul past the end" } */
|
|
T (15, "%E", -1.8e+103); /* -1.800000E+103 */
|
|
|
|
T (16, "%.8e", -1.9e+104); /* { dg-warning "nul past the end" } */
|
|
T (17, "%.8e", -2.0e+105); /* -2.00000000e+105 */
|
|
|
|
T ( 5, "%.0e", 0.0); /* { dg-warning "nul past the end" } */
|
|
T ( 5, "%.0e", 1.0); /* { dg-warning "nul past the end" } */
|
|
T ( 6, "%.0e", 1.0);
|
|
|
|
/* The actual output of the following directives depends on the rounding
|
|
mode. Verify that the warning correctly reflects that. */
|
|
T (12, "%e", 9.999999e+99); /* { dg-warning "directive writing between 12 and 13 bytes" } */
|
|
T (12, "%e", 9.9999994e+99); /* { dg-warning "directive writing between 12 and 13 bytes" } */
|
|
T (12, "%e", 9.9999995e+99); /* { dg-warning "directive writing between 12 and 13 bytes" } */
|
|
T (12, "%e", 9.9999996e+99); /* { dg-warning "directive writing between 12 and 13 bytes" } */
|
|
T (12, "%e", 9.9999997e+99); /* { dg-warning "directive writing between 12 and 13 bytes" } */
|
|
T (12, "%e", 9.9999998e+99); /* { dg-warning "directive writing between 12 and 13 bytes" } */
|
|
|
|
T (12, "%Le", 9.9999994e+99L);/* { dg-warning "directive writing between 12 and 13 bytes" } */
|
|
T (12, "%Le", 9.9999995e+99L);/* { dg-warning "directive writing between 12 and 13 bytes" } */
|
|
T (12, "%Le", 9.9999996e+99L);/* { dg-warning "directive writing between 12 and 13 bytes" } */
|
|
T (12, "%Le", 9.9999997e+99L);/* { dg-warning "directive writing between 12 and 13 bytes" } */
|
|
T (12, "%Le", 9.9999998e+99L);/* { dg-warning "directive writing between 12 and 13 bytes" } */
|
|
T (12, "%Le", 9.9999999e+99L);/* { dg-warning "directive writing between 12 and 13 bytes" } */
|
|
}
|
|
|
|
/* At -Wformat-length level 1 unknown numbers are assumed to have
|
|
the value one, and unknown strings are assumed to have a zero
|
|
length. */
|
|
|
|
void test_sprintf_chk_s_nonconst (int i, const char *s)
|
|
{
|
|
T (-1, "%s", s);
|
|
T ( 0, "%s", s); /* { dg-warning "nul past the end" } */
|
|
T ( 1, "%s", s);
|
|
T ( 1, "%.0s", s);
|
|
T ( 1, "%.1s", s); /* { dg-warning "nul past the end" } */
|
|
|
|
/* The following will definitely write past the end of the buffer,
|
|
but since at level 1 the length of an unknown string argument
|
|
is assumed to be zero, it will write the terminating nul past
|
|
the end (we don't print "past the end" when we're not
|
|
sure which we can't be with an unknown string. */
|
|
T (1, "%1s", s); /* { dg-warning "writing a terminating nul past the end" } */
|
|
}
|
|
|
|
/* Exercise the hh length modifier with all integer specifiers and
|
|
a non-constant argument. */
|
|
|
|
void test_sprintf_chk_hh_nonconst (int a)
|
|
{
|
|
T (-1, "%hhd", a);
|
|
|
|
T (0, "%hhd", a); /* { dg-warning "into a region" } */
|
|
T (0, "%hhi", a); /* { dg-warning "into a region" } */
|
|
T (0, "%hhu", a); /* { dg-warning "into a region" } */
|
|
T (0, "%hhx", a); /* { dg-warning "into a region" } */
|
|
|
|
T (1, "%hhd", a); /* { dg-warning "nul past the end" } */
|
|
T (1, "%hhi", a); /* { dg-warning "nul past the end" } */
|
|
T (1, "%hhu", a); /* { dg-warning "nul past the end" } */
|
|
T (1, "%hhx", a); /* { dg-warning "nul past the end" } */
|
|
|
|
T (1, "% hhd", a); /* { dg-warning "into a region" } */
|
|
T (1, "% hhi", a); /* { dg-warning "into a region" } */
|
|
T (1, "%+hhd", a); /* { dg-warning "into a region" } */
|
|
T (1, "%+hhi", a); /* { dg-warning "into a region" } */
|
|
T (1, "%-hhd", a); /* { dg-warning "nul past the end" } */
|
|
T (1, "%-hhi", a); /* { dg-warning "nul past the end" } */
|
|
|
|
T (2, "%hhd", a);
|
|
T (2, "%hhi", a);
|
|
T (2, "%hho", a);
|
|
T (2, "%hhu", a);
|
|
T (2, "%hhx", a);
|
|
|
|
T (2, "% hhd", a); /* { dg-warning "nul past the end" } */
|
|
T (2, "% hhi", a); /* { dg-warning "nul past the end" } */
|
|
T (2, "% hho", a); /* { dg-warning ". . flag used with .%o." } */
|
|
T (2, "% hhu", a); /* { dg-warning ". . flag used with .%u." } */
|
|
T (2, "% hhx", a); /* { dg-warning ". . flag used with .%x." } */
|
|
|
|
T (2, "#%hho", a); /* { dg-warning "nul past the end" } */
|
|
T (2, "#%hhx", a); /* { dg-warning "nul past the end" } */
|
|
|
|
T (3, "%2hhd", a);
|
|
T (3, "%2hhi", a);
|
|
T (3, "%2hho", a);
|
|
T (3, "%2hhu", a);
|
|
T (3, "%2hhx", a);
|
|
|
|
/* Exercise cases where the type of the actual argument (whose value
|
|
and range are unknown) constrain the size of the output and so
|
|
can be used to avoid what would otherwise be false positives. */
|
|
|
|
T (2, "%hhd", (UChar)a);
|
|
T (2, "%hhi", (UChar)a);
|
|
T (2, "%-hhi", (UChar)a);
|
|
}
|
|
|
|
/* Exercise the h length modifier with all integer specifiers and
|
|
a non-constant argument. */
|
|
|
|
void test_sprintf_chk_h_nonconst (int a)
|
|
{
|
|
T (-1, "%hd", a);
|
|
|
|
T (0, "%hd", a); /* { dg-warning "into a region" } */
|
|
T (0, "%hi", a); /* { dg-warning "into a region" } */
|
|
T (0, "%hu", a); /* { dg-warning "into a region" } */
|
|
T (0, "%hx", a); /* { dg-warning "into a region" } */
|
|
|
|
T (1, "%hd", a); /* { dg-warning "nul past the end" } */
|
|
T (1, "%hi", a); /* { dg-warning "nul past the end" } */
|
|
T (1, "%hu", a); /* { dg-warning "nul past the end" } */
|
|
T (1, "%hx", a); /* { dg-warning "nul past the end" } */
|
|
|
|
T (1, "% hd", a); /* { dg-warning "into a region" } */
|
|
T (1, "% hi", a); /* { dg-warning "into a region" } */
|
|
T (1, "%+hd", a); /* { dg-warning "into a region" } */
|
|
T (1, "%+hi", a); /* { dg-warning "into a region" } */
|
|
T (1, "%-hd", a); /* { dg-warning "nul past the end" } */
|
|
T (1, "%-hi", a); /* { dg-warning "nul past the end" } */
|
|
|
|
T (2, "%hd", a);
|
|
T (2, "%hi", a);
|
|
T (2, "%ho", a);
|
|
T (2, "%hu", a);
|
|
T (2, "%hx", a);
|
|
|
|
T (2, "% hd", a); /* { dg-warning "nul past the end" } */
|
|
T (2, "% hi", a); /* { dg-warning "nul past the end" } */
|
|
T (2, "% ho", a); /* { dg-warning ". . flag used with .%o." } */
|
|
T (2, "% hu", a); /* { dg-warning ". . flag used with .%u." } */
|
|
T (2, "% hx", a); /* { dg-warning ". . flag used with .%x." } */
|
|
|
|
T (2, "#%ho", a); /* { dg-warning "nul past the end" } */
|
|
T (2, "#%hx", a); /* { dg-warning "nul past the end" } */
|
|
|
|
T (3, "%2hd", a);
|
|
T (3, "%2hi", a);
|
|
T (3, "%2ho", a);
|
|
T (3, "%2hu", a);
|
|
T (3, "%2hx", a);
|
|
}
|
|
|
|
/* Exercise all integer specifiers with no modifier and a non-constant
|
|
argument. */
|
|
|
|
void test_sprintf_chk_int_nonconst (int a)
|
|
{
|
|
T (-1, "%d", a);
|
|
|
|
T (0, "%d", a); /* { dg-warning "into a region" } */
|
|
T (0, "%i", a); /* { dg-warning "into a region" } */
|
|
T (0, "%u", a); /* { dg-warning "into a region" } */
|
|
T (0, "%x", a); /* { dg-warning "into a region" } */
|
|
|
|
T (1, "%d", a); /* { dg-warning "nul past the end" } */
|
|
T (1, "%i", a); /* { dg-warning "nul past the end" } */
|
|
T (1, "%u", a); /* { dg-warning "nul past the end" } */
|
|
T (1, "%x", a); /* { dg-warning "nul past the end" } */
|
|
|
|
T (1, "% d", a); /* { dg-warning "into a region" } */
|
|
T (1, "% i", a); /* { dg-warning "into a region" } */
|
|
T (1, "%+d", a); /* { dg-warning "into a region" } */
|
|
T (1, "%+i", a); /* { dg-warning "into a region" } */
|
|
T (1, "%-d", a); /* { dg-warning "nul past the end" } */
|
|
T (1, "%-i", a); /* { dg-warning "nul past the end" } */
|
|
|
|
T (2, "%d", a);
|
|
T (2, "%i", a);
|
|
T (2, "%o", a);
|
|
T (2, "%u", a);
|
|
T (2, "%x", a);
|
|
|
|
T (2, "% d", a); /* { dg-warning "nul past the end" } */
|
|
T (2, "% i", a); /* { dg-warning "nul past the end" } */
|
|
T (2, "% o", a); /* { dg-warning ". . flag used with .%o." } */
|
|
T (2, "% u", a); /* { dg-warning ". . flag used with .%u." } */
|
|
T (2, "% x", a); /* { dg-warning ". . flag used with .%x." } */
|
|
|
|
T (2, "#%o", a); /* { dg-warning "nul past the end" } */
|
|
T (2, "#%x", a); /* { dg-warning "nul past the end" } */
|
|
|
|
T (3, "%2d", a);
|
|
T (3, "%2i", a);
|
|
T (3, "%2o", a);
|
|
T (3, "%2u", a);
|
|
T (3, "%2x", a);
|
|
}
|
|
|
|
void test_sprintf_chk_e_nonconst (double d)
|
|
{
|
|
T (-1, "%E", d);
|
|
T (-1, "%lE", d);
|
|
|
|
T ( 0, "%E", d); /* { dg-warning "writing between 12 and 14 bytes into a region of size 0" } */
|
|
T ( 0, "%e", d); /* { dg-warning "into a region" } */
|
|
T ( 1, "%E", d); /* { dg-warning "into a region" } */
|
|
T ( 1, "%e", d); /* { dg-warning "into a region" } */
|
|
T ( 2, "%e", d); /* { dg-warning "into a region" } */
|
|
T ( 3, "%e", d); /* { dg-warning "into a region" } */
|
|
T (12, "%e", d); /* { dg-warning "past the end" } */
|
|
T (12, "%e", d); /* { dg-warning "past the end" } */
|
|
T (13, "%E", d); /* 1.000000E+00 */
|
|
T (13, "%e", d);
|
|
T (14, "%E", d);
|
|
T (14, "%e", d);
|
|
|
|
T (0, "%+E", d); /* { dg-warning "writing between 13 and 14 bytes into a region of size 0" } */
|
|
T (0, "%-e", d); /* { dg-warning "writing between 12 and 14 bytes into a region of size 0" } */
|
|
T (0, "% E", d); /* { dg-warning "writing between 13 and 14 bytes into a region of size 0" } */
|
|
|
|
/* The range of output of "%.0e" is between 5 and 7 bytes (not counting
|
|
the terminating NUL. */
|
|
T ( 5, "%.0e", d); /* { dg-warning "writing a terminating nul past the end" } */
|
|
T ( 6, "%.0e", d); /* 1e+00 */
|
|
|
|
/* The range of output of "%.1e" is between 7 and 9 bytes (not counting
|
|
the terminating NUL. */
|
|
T ( 7, "%.1e", d); /* { dg-warning "writing a terminating nul past the end" } */
|
|
T ( 8, "%.1e", d);
|
|
}
|
|
|
|
void test_sprintf_chk_f_nonconst (double d)
|
|
{
|
|
T (-1, "%F", d);
|
|
T (-1, "%lF", d);
|
|
|
|
T ( 0, "%F", d); /* { dg-warning "into a region" } */
|
|
T ( 0, "%f", d); /* { dg-warning "into a region" } */
|
|
T ( 1, "%F", d); /* { dg-warning "into a region" } */
|
|
T ( 1, "%f", d); /* { dg-warning "into a region" } */
|
|
T ( 2, "%F", d); /* { dg-warning "into a region" } */
|
|
T ( 2, "%f", d); /* { dg-warning "into a region" } */
|
|
T ( 3, "%F", d); /* { dg-warning "into a region" } */
|
|
T ( 3, "%f", d); /* { dg-warning "into a region" } */
|
|
T ( 4, "%F", d); /* { dg-warning "into a region" } */
|
|
T ( 4, "%f", d); /* { dg-warning "into a region" } */
|
|
T ( 5, "%F", d); /* { dg-warning "into a region" } */
|
|
T ( 5, "%f", d); /* { dg-warning "into a region" } */
|
|
T ( 6, "%F", d); /* { dg-warning "into a region" } */
|
|
T ( 6, "%f", d); /* { dg-warning "into a region" } */
|
|
T ( 7, "%F", d); /* { dg-warning "into a region" } */
|
|
T ( 7, "%f", d); /* { dg-warning "into a region" } */
|
|
T ( 8, "%F", d); /* { dg-warning "nul past the end" } */
|
|
T ( 8, "%f", d); /* { dg-warning "nul past the end" } */
|
|
T ( 9, "%F", d);
|
|
T ( 9, "%f", d);
|
|
}
|
|
|
|
/* Tests for __builtin_vsprintf_chk are the same as those for
|
|
__builtin_sprintf_chk with non-constant arguments. */
|
|
#undef T
|
|
#define T(size, fmt) \
|
|
__builtin___vsprintf_chk (buffer (size), 0, objsize (size), fmt, va)
|
|
|
|
void test_vsprintf_chk_c (__builtin_va_list va)
|
|
{
|
|
T (-1, "%c");
|
|
|
|
/* Verify the full text of the diagnostic for just the distinct messages
|
|
and use abbreviations in subsequent test cases. */
|
|
T (0, "%c"); /* { dg-warning ".%c. directive writing 1 byte into a region of size 0" } */
|
|
T (1, "%c"); /* { dg-warning "writing a terminating nul past the end" } */
|
|
T (1, "%c"); /* { dg-warning "nul past the end" } */
|
|
T (2, "%c");
|
|
T (2, "%2c"); /* { dg-warning "nul past the end" } */
|
|
T (2, "%3c"); /* { dg-warning "into a region" } */
|
|
T (2, "%c%c"); /* { dg-warning "nul past the end" } */
|
|
T (3, "%c%c");
|
|
|
|
/* Wide characters. */
|
|
T (0, "%lc"); /* { dg-warning "nul past the end" } */
|
|
T (1, "%lc");
|
|
T (2, "%lc");
|
|
|
|
/* The following could result in as few as a single byte and in as many
|
|
as MB_CUR_MAX, but since the MB_CUR_MAX value is a runtime property
|
|
the write cannot be reliably diagnosed. */
|
|
T (2, "%lc");
|
|
T (2, "%1lc");
|
|
/* Writing some unknown number of bytes into a field two characters wide. */
|
|
T (2, "%2lc"); /* { dg-warning "nul past the end" } */
|
|
T (2, "%lc%lc");
|
|
|
|
T (3, "%lc%c");
|
|
/* Here in the best case each argument will format as single character,
|
|
causing the terminating NUL to be written past the end. */
|
|
T (3, "%lc%c%c");
|
|
|
|
}
|
|
|
|
void test_vsprintf_chk_int (__builtin_va_list va)
|
|
{
|
|
T (-1, "%d");
|
|
|
|
T (0, "%d"); /* { dg-warning "into a region" } */
|
|
T (0, "%i"); /* { dg-warning "into a region" } */
|
|
T (0, "%u"); /* { dg-warning "into a region" } */
|
|
T (0, "%x"); /* { dg-warning "into a region" } */
|
|
|
|
T (1, "%d"); /* { dg-warning "nul past the end" } */
|
|
T (1, "%i"); /* { dg-warning "nul past the end" } */
|
|
T (1, "%u"); /* { dg-warning "nul past the end" } */
|
|
T (1, "%x"); /* { dg-warning "nul past the end" } */
|
|
|
|
T (1, "% d"); /* { dg-warning "into a region" } */
|
|
T (1, "% i"); /* { dg-warning "into a region" } */
|
|
T (1, "%+d"); /* { dg-warning "into a region" } */
|
|
T (1, "%+i"); /* { dg-warning "into a region" } */
|
|
T (1, "%-d"); /* { dg-warning "nul past the end" } */
|
|
T (1, "%-i"); /* { dg-warning "nul past the end" } */
|
|
|
|
T (2, "%d");
|
|
T (2, "%i");
|
|
T (2, "%o");
|
|
T (2, "%u");
|
|
T (2, "%x");
|
|
|
|
T (2, "% d"); /* { dg-warning "nul past the end" } */
|
|
T (2, "% i"); /* { dg-warning "nul past the end" } */
|
|
T (2, "% o"); /* { dg-warning ". . flag used with .%o." } */
|
|
T (2, "% u"); /* { dg-warning ". . flag used with .%u." } */
|
|
T (2, "% x"); /* { dg-warning ". . flag used with .%x." } */
|
|
|
|
T (2, "#%o"); /* { dg-warning "nul past the end" } */
|
|
T (2, "#%x"); /* { dg-warning "nul past the end" } */
|
|
|
|
T (3, "%2d");
|
|
T (3, "%2i");
|
|
T (3, "%2o");
|
|
T (3, "%2u");
|
|
T (3, "%2x");
|
|
}
|
|
|
|
#undef T
|
|
#define T(size, fmt, ...) \
|
|
__builtin_snprintf (buffer (size), objsize (size), fmt, __VA_ARGS__)
|
|
|
|
void test_snprintf_c_const (void)
|
|
{
|
|
T (-1, "%c", 0); /* { dg-warning "specified destination size \[0-9\]+ too large" } */
|
|
|
|
/* Verify the full text of the diagnostic for just the distinct messages
|
|
and use abbreviations in subsequent test cases. */
|
|
|
|
/* A call to snprintf with a buffer of zero size is a request to determine
|
|
the size of output without writing anything into the destination. No
|
|
warning must be issued. */
|
|
T (0, "%c", 0);
|
|
T (1, "%c", 0); /* { dg-warning "output truncated before the last format character" } */
|
|
T (1, "%c", '1'); /* { dg-warning "output truncated" } */
|
|
T (2, "%c", '1');
|
|
T (2, "%2c", '1'); /* { dg-warning "output truncated" } */
|
|
T (2, "%3c", '1'); /* { dg-warning "directive output truncated" } */
|
|
T (2, "%c%c", '1', '2'); /* { dg-warning "output truncated" } */
|
|
T (3, "%c%c", '1', '2');
|
|
|
|
/* Wide characters. */
|
|
T (0, "%lc", 0);
|
|
T (1, "%lc", 0);
|
|
T (2, "%lc", 0);
|
|
|
|
/* The following could result in as few as a single byte and in as many
|
|
as MB_CUR_MAX, but since the MB_CUR_MAX value is a runtime property
|
|
the write cannot be reliably diagnosed. */
|
|
T (2, "%lc", (wint_t)L'1');
|
|
T (2, "%1lc", (wint_t)L'1');
|
|
/* Writing at least 1 characted into a field two characters wide. */
|
|
T (2, "%2lc", (wint_t)L'1'); /* { dg-warning "output truncated before the last format character" } */
|
|
|
|
T (3, "%lc%c", (wint_t)'1', '2');
|
|
/* Here in the best case each argument will format as single character,
|
|
causing the output to be truncated just before the terminating NUL
|
|
(i.e., cutting off the '3'). */
|
|
T (3, "%lc%c%c", (wint_t)'1', '2', '3'); /* { dg-warning "output truncated" } */
|
|
T (3, "%lc%lc%c", (wint_t)'1', (wint_t)'2', '3'); /* { dg-warning "output truncated" } */
|
|
}
|
|
|
|
#undef T
|
|
#define T(size, fmt, ...) \
|
|
__builtin___snprintf_chk (buffer (size), objsize (size), \
|
|
0, objsize (size), fmt, __VA_ARGS__)
|
|
|
|
void test_snprintf_chk_c_const (void)
|
|
{
|
|
/* Verify that specifying a size of the destination buffer that's
|
|
bigger than its actual size (normally determined and passed to
|
|
the function by __builtin_object_size) is diagnosed. */
|
|
__builtin___snprintf_chk (buffer, 3, 0, 2, " "); /* { dg-warning "always overflow|specified size 3 exceeds the size 2 of the destination" } */
|
|
|
|
T (-1, "%c", 0); /* { dg-warning "specified destination size \[^ \]* too large" } */
|
|
|
|
T (0, "%c", 0);
|
|
T (0, "%c%c", 0, 0);
|
|
T (0, "%c_%c", 0, 0);
|
|
T (0, "_%c_%c", 0, 0);
|
|
|
|
T (1, "%c", 0); /* { dg-warning "output truncated before the last format character" } */
|
|
T (1, "%c", '1'); /* { dg-warning "output truncated" } */
|
|
T (2, "%c", '1');
|
|
T (2, "%2c", '1'); /* { dg-warning "output truncated" } */
|
|
T (2, "%3c", '1'); /* { dg-warning "directive output truncated" } */
|
|
T (2, "%c%c", '1', '2'); /* { dg-warning "output truncated before the last format character" } */
|
|
T (3, "%c%c", '1', '2');
|
|
T (3, "%c_%c", '1', '2'); /* { dg-warning "output truncated" } */
|
|
|
|
/* Wide characters. */
|
|
T (0, "%lc", 0);
|
|
T (1, "%lc", 0);
|
|
T (2, "%lc", 0);
|
|
|
|
/* The following could result in as few as a single byte and in as many
|
|
as MB_CUR_MAX, but since the MB_CUR_MAX value is a runtime property
|
|
the write cannot be reliably diagnosed. */
|
|
T (2, "%lc", (wint_t)L'1');
|
|
T (2, "%1lc", (wint_t)L'1');
|
|
/* Writing at least 1 characted into a field two characters wide. */
|
|
T (2, "%2lc", (wint_t)'1'); /* { dg-warning "output truncated before the last format character" } */
|
|
|
|
T (3, "%lc%c", (wint_t)'1', '2');
|
|
/* Here in the best case each argument will format as single character,
|
|
causing the output to be truncated just before the terminating NUL
|
|
(i.e., cutting off the '3'). */
|
|
T (3, "%lc%c%c", (wint_t)'1', '2', '3'); /* { dg-warning "output truncated" } */
|
|
T (3, "%lc%lc%c", (wint_t)'1', (wint_t)'2', '3'); /* { dg-warning "output truncated" } */
|
|
}
|
|
|
|
/* Macro to verify that calls to __builtin_vsprintf (i.e., with no size
|
|
argument) issue diagnostics by correctly determining the size of
|
|
the destination buffer. */
|
|
#undef T
|
|
#define T(size, fmt) \
|
|
__builtin_vsprintf (buffer (size), fmt, va)
|
|
|
|
void test_vsprintf_s (__builtin_va_list va)
|
|
{
|
|
T (-1, "%s");
|
|
|
|
T (0, "%s"); /* { dg-warning "writing a terminating nul past the end" } */
|
|
T (1, "%s");
|
|
T (1, "%1s"); /* { dg-warning "writing a terminating nul past the end" } */
|
|
|
|
T (2, "%s%s");
|
|
T (2, "%s%s_");
|
|
T (2, "%s_%s");
|
|
T (2, "_%s%s");
|
|
T (2, "_%s_%s"); /* { dg-warning "writing a terminating nul past the end" } */
|
|
}
|
|
|
|
/* Exercise all integer specifiers with no modifier and a non-constant
|
|
argument. */
|
|
|
|
void test_vsprintf_int (__builtin_va_list va)
|
|
{
|
|
T (-1, "%d");
|
|
|
|
T (0, "%d"); /* { dg-warning "into a region" } */
|
|
T (0, "%i"); /* { dg-warning "into a region" } */
|
|
T (0, "%u"); /* { dg-warning "into a region" } */
|
|
T (0, "%x"); /* { dg-warning "into a region" } */
|
|
|
|
T (1, "%d"); /* { dg-warning "nul past the end" } */
|
|
T (1, "%i"); /* { dg-warning "nul past the end" } */
|
|
T (1, "%u"); /* { dg-warning "nul past the end" } */
|
|
T (1, "%x"); /* { dg-warning "nul past the end" } */
|
|
|
|
T (1, "% d"); /* { dg-warning "into a region" } */
|
|
T (1, "% i"); /* { dg-warning "into a region" } */
|
|
T (1, "%+d"); /* { dg-warning "into a region" } */
|
|
T (1, "%+i"); /* { dg-warning "into a region" } */
|
|
T (1, "%-d"); /* { dg-warning "nul past the end" } */
|
|
T (1, "%-i"); /* { dg-warning "nul past the end" } */
|
|
|
|
T (2, "%d");
|
|
T (2, "%i");
|
|
T (2, "%o");
|
|
T (2, "%u");
|
|
T (2, "%x");
|
|
|
|
T (2, "% d"); /* { dg-warning "nul past the end" } */
|
|
T (2, "% i"); /* { dg-warning "nul past the end" } */
|
|
T (2, "% o"); /* { dg-warning ". . flag used with .%o." } */
|
|
T (2, "% u"); /* { dg-warning ". . flag used with .%u." } */
|
|
T (2, "% x"); /* { dg-warning ". . flag used with .%x." } */
|
|
|
|
T (2, "#%o"); /* { dg-warning "nul past the end" } */
|
|
T (2, "#%x"); /* { dg-warning "nul past the end" } */
|
|
|
|
T (3, "%2d");
|
|
T (3, "%2i");
|
|
T (3, "%2o");
|
|
T (3, "%2u");
|
|
T (3, "%2x");
|
|
}
|
|
|
|
#undef T
|
|
#define T(size, fmt) \
|
|
__builtin_vsnprintf (buffer (size), objsize (size), fmt, va)
|
|
|
|
void test_vsnprintf_s (__builtin_va_list va)
|
|
{
|
|
T (-1, "%s"); /* { dg-warning "specified destination size \[^ \]* too large" } */
|
|
|
|
T (0, "%s");
|
|
T (1, "%s");
|
|
T (1, "%1s"); /* { dg-warning "output truncated before the last format character" } */
|
|
|
|
T (2, "%s%s");
|
|
T (2, "%s%s_");
|
|
T (2, "%s_%s");
|
|
T (2, "_%s%s");
|
|
T (2, "_%s_%s"); /* { dg-warning "output truncated before the last format character" } */
|
|
}
|
|
|
|
#undef T
|
|
#define T(size, fmt) \
|
|
__builtin___vsnprintf_chk (buffer (size), objsize (size), \
|
|
0, objsize (size), fmt, va)
|
|
|
|
void test_vsnprintf_chk_s (__builtin_va_list va)
|
|
{
|
|
/* Verify that specifying a size of the destination buffer that's
|
|
bigger than its actual size (normally determined and passed to
|
|
the function by __builtin_object_size) is diagnosed. */
|
|
__builtin___snprintf_chk (buffer, 123, 0, 122, " "); /* { dg-warning "always overflow|specified size 123 exceeds the size 122 of the destination object" } */
|
|
|
|
__builtin___snprintf_chk (buffer, __SIZE_MAX__, 0, 2, " "); /* { dg-warning "always overflow|destination size .\[0-9\]+. too large" } */
|
|
|
|
T (0, "%s");
|
|
T (1, "%s");
|
|
T (1, "%1s"); /* { dg-warning "output truncated before the last format character" } */
|
|
|
|
T (2, "%s%s");
|
|
T (2, "%s%s_");
|
|
T (2, "%s_%s");
|
|
T (2, "_%s%s");
|
|
T (2, "_%s_%s"); /* { dg-warning "output truncated before the last format character" } */
|
|
}
|