blob: 1f8c418a7806d3d636bb43c9a30a61077a82db70 [file] [log] [blame]
/* APPLE LOCAL file mainline */
/* 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;
}