138 lines
2.4 KiB
C
138 lines
2.4 KiB
C
/* This file was miscompiled by an earlier version of the object size
|
|
checking patch. Object size in one of the memcpy calls was
|
|
incorrectly determined to be 0 while it should be (size_t) -1
|
|
(== unknown). */
|
|
/* { dg-do compile } */
|
|
/* { dg-options "-O2" } */
|
|
|
|
#include "../gcc.c-torture/execute/builtins/chk.h"
|
|
|
|
void *bar (int);
|
|
extern void *malloc (__SIZE_TYPE__);
|
|
|
|
struct A
|
|
{
|
|
int i, j, k;
|
|
};
|
|
|
|
/* Here all object sizes are not known at compile time. There
|
|
should be no warning, nor any checker functions called. */
|
|
|
|
void
|
|
foo (const struct A *x, int y, const unsigned char *z)
|
|
{
|
|
unsigned int b;
|
|
unsigned char *c = 0;
|
|
|
|
b = (x->i & 0xff) == 1 ? 3 : 4;
|
|
if (y)
|
|
c = bar (x->j * x->k);
|
|
|
|
const unsigned char *d = z;
|
|
unsigned char *e = c;
|
|
unsigned char *f = c + x->j * x->k;
|
|
int g = 0;
|
|
|
|
while (e < f)
|
|
{
|
|
unsigned int h = *d++;
|
|
|
|
if (h & 128)
|
|
{
|
|
h = h - 128;
|
|
g = e + h * b > f;
|
|
if (g)
|
|
h = (f - e) / b;
|
|
if (b < 4)
|
|
do
|
|
{
|
|
memcpy (e, d, 3);
|
|
e += 3;
|
|
}
|
|
while (--h);
|
|
else
|
|
do
|
|
{
|
|
memcpy (e, d, 4);
|
|
e += 4;
|
|
}
|
|
while (--h);
|
|
d += b;
|
|
}
|
|
else
|
|
{
|
|
h *= b;
|
|
g = e + h > f;
|
|
if (g)
|
|
h = f - e;
|
|
memcpy (e, d, h);
|
|
e += h;
|
|
d += h;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* The same routine, slightly modified:
|
|
1) c has known size at compile time
|
|
2) e += h was changed into e += 16.
|
|
GCC could actually through VRP determine that
|
|
in e += h is (h >= 0 && h <= 127), thus know
|
|
it is pointer addition and not subtraction and
|
|
know e's __builtin_object_size (e, 0) is at 512,
|
|
but we are not there yet. */
|
|
|
|
unsigned char *
|
|
baz (const struct A *x, const unsigned char *z)
|
|
{
|
|
unsigned int b;
|
|
unsigned char *c = 0;
|
|
|
|
b = (x->i & 0xff) == 1 ? 3 : 4;
|
|
c = malloc (512);
|
|
|
|
const unsigned char *d = z;
|
|
unsigned char *e = c;
|
|
unsigned char *f = c + x->j * x->k;
|
|
int g = 0;
|
|
|
|
while (e < f)
|
|
{
|
|
unsigned int h = *d++;
|
|
|
|
if (h & 128)
|
|
{
|
|
h = h - 128;
|
|
g = e + h * b > f;
|
|
if (g)
|
|
h = (f - e) / b;
|
|
if (b < 4)
|
|
do
|
|
{
|
|
memcpy (e, d, 3);
|
|
e += 3;
|
|
}
|
|
while (--h);
|
|
else
|
|
do
|
|
{
|
|
memcpy (e, d, 513); /* { dg-warning "will always overflow" "memcpy" } */
|
|
e += 4;
|
|
}
|
|
while (--h);
|
|
d += b;
|
|
}
|
|
else
|
|
{
|
|
h *= b;
|
|
g = e + h > f;
|
|
if (g)
|
|
h = f - e;
|
|
memcpy (e, d, h);
|
|
/* e += h; */
|
|
e += 16;
|
|
d += h;
|
|
}
|
|
}
|
|
return c;
|
|
}
|