1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
/* PR middle-end/85602 - -Wsizeof-pointer-memaccess for strncat with size
of source
{ dg-do compile }
{ dg-options "-O2 -Wno-array-bounds -Wsizeof-pointer-memaccess -Wstringop-truncation -ftrack-macro-expansion=0" } */
#include "../gcc.dg/range.h"
typedef __SIZE_TYPE__ size_t;
#if __cplusplus
extern "C" {
#endif
char* strcpy (char*, const char*);
size_t strlen (const char*);
char* strncat (char*, const char*, __SIZE_TYPE__);
char* strncpy (char*, const char*, __SIZE_TYPE__);
#if __cplusplus
}
#endif
#define NONSTR __attribute__ ((nonstring))
NONSTR char nd3[3];
NONSTR char nd4[4];
NONSTR char nd5[5];
NONSTR char ns3[3];
NONSTR char ns4[4];
NONSTR char ns5[5];
NONSTR char* pns;
void sink (void*, ...);
#define T(call) sink (call)
/* Verify that for a nonstring source array of an unknown length
a warning is issued only when the bound exceeds the array size. */
void test_strncat_nonstring_cst (char *d)
{
T (strncat (d, ns3, 1));
T (strncat (d, ns3, 2));
T (strncat (d, ns3, 3));
T (strncat (d, ns3, sizeof ns3));
T (strncat (d, ns3, 4)); /* { dg-warning "argument 2 declared attribute .nonstring. is smaller than the specified bound 4" } */
T (strncat (d, ns4, 1));
T (strncat (d, ns4, 2));
T (strncat (d, ns4, 3));
T (strncat (d, ns4, 4));
T (strncat (d, ns4, sizeof ns4));
T (strncat (d, ns4, 5)); /* { dg-warning "argument 2 declared attribute .nonstring. is smaller than the specified bound 5" } */
T (strncat (nd3, ns3, 1));
T (strncat (nd3, ns3, 2));
T (strncat (nd3, ns3, 3)); /* { dg-warning "specified bound 3 equals destination size" } */
/* Either of the two warnings below is fine. */
T (strncat (nd3, ns3, 4)); /* { dg-warning "argument 2 declared attribute .nonstring. is smaller than the specified bound 4|specified bound 4 exceeds destination size 3" } */
T (strncat (d, pns, sizeof pns)); /* { dg-warning "argument to .sizeof. in .\[^\n\r\]*strncat\[^\n\r\]*. call is the same expression as the source" } */
}
void test_strncat_nonstring_var (char *d, size_t n)
{
/* In the following the bound coulld apply to either the destination
or the source. The expected use of strncat() is to pass it as
the bound DSIZE - strlen(D) - 1 so the call below is diagnosed. */
T (strncat (d, ns3, n)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
T (strncat (d, ns3, UR (0, 1)));
T (strncat (d, ns3, UR (1, 2)));
T (strncat (d, ns3, UR (2, 3)));
T (strncat (d, ns3, UR (3, 4))); /* { dg-warning "argument 2 declared attribute 'nonstring' may be smaller than the specified bound \\\[3, 4]" } */
T (strncat (d, ns3, UR (4, 5))); /* { dg-warning "argument 2 declared attribute 'nonstring' is smaller than the specified bound \\\[4, 5]" } */
/* Verify that the call below (the intended use of strncat()) is
also diagnosed. */
T (strncat (d, ns3, 256 - strlen (d) - 1)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
T (strncat (nd3, ns5, UR (0, 1)));
T (strncat (nd3, ns5, UR (1, 2)));
T (strncat (nd3, ns5, UR (2, 3)));
T (strncat (nd3, ns5, UR (3, 4)));
T (strncat (nd3, ns5, UR (4, 5))); /* { dg-warning "specified bound \\\[4, 5] exceeds destination size 3" } */
T (strncat (nd5, ns3, UR (0, 1)));
T (strncat (nd5, ns3, UR (1, 2)));
T (strncat (nd5, ns3, UR (2, 3)));
T (strncat (nd5, ns3, UR (3, 4))); /* { dg-warning "argument 2 declared attribute 'nonstring' may be smaller than the specified bound \\\[3, 4]" } */
}
/* Verify that for a nonstring source array of a known length (i.e.,
a nonstring array containing a nul-terminated string) a warning
is issued only for certain truncation.
The test cases are split up to work around bug 81343 (or one like
it). */
void test_strncat_string_1_1 (char *d)
{
strcpy (ns3, "1");
T (strncat (d, ns3, 1)); /* { dg-warning "output truncated before terminating nul copying 1 byte from a string of the same length" } */
}
void test_strncat_string_1_2 (char *d)
{
strcpy (ns3, "1");
T (strncat (d, ns3, 2));
}
void test_strncat_string_1_3 (char *d)
{
strcpy (ns3, "1");
T (strncat (d, ns3, 3));
}
void test_strncat_string_2_1 (char *d)
{
strcpy (ns3, "12");
T (strncat (d, ns3, 1)); /* { dg-warning "output truncated copying 1 byte from a string of length 2" } */
}
void test_strncat_string_2_2 (char *d)
{
strcpy (ns3, "12");
T (strncat (d, ns3, 2)); /* { dg-warning "output truncated before terminating nul copying 2 bytes from a string of the same length" } */
}
void test_strncat_string_2_3 (char *d)
{
strcpy (ns3, "12");
T (strncat (d, ns3, 3));
}
void test_strcncpy_nonstring_cst (char *d)
{
T (strncpy (d, ns3, 1));
T (strncpy (d, ns3, 2));
T (strncpy (d, ns3, 3));
T (strncpy (d, ns3, sizeof ns3));
T (strncpy (d, ns3, 4)); /* { dg-warning "argument 2 declared attribute .nonstring. is smaller than the specified bound 4" } */
}
|