Bugs in libc/machine/cris/memmove.c, memmove test-case
Jeff Johnston
jjohnstn@redhat.com
Thu Jan 27 20:55:00 GMT 2005
Testsuite portion of patch checked in. I expect you will have the updated
memmove.c in the resubmitted first patch.
Thanks,
-- Jeff J.
Hans-Peter Nilsson wrote:
> When I recently updated the mem*.c files to avoid pointer
> arithmetic on void * and to work around the removed GCC
> extension to postincrement a casted pointer, of course I
> introduced bugs! See last patch. In memset.c, luckily it's
> just a useless cast to the pointer type that remained, but in
> memmove.c I added a couple of nasty typos. Many thanks to Eric
> Harbers for pointing this out! (Though in private email.)
>
> Strange that the GCC test-results didn't suffer more; a few
> libstdc++ tests were hurt, but lots fail for newlib targets
> anyway, so there was much noise.
>
> Trying to live up to the no-change-without-testcase idiom,
> here's a memmove test-case, which fits right into the existing
> newlib framework.
>
> I see other newlib tests fail compilation due to recently added
> GCC warnings. Patch next.
>
> 2005-01-27 Hans-Peter Nilsson <hp@axis.com>
>
> * testsuite/newlib.string/memmove1.c: New test.
>
> --- /dev/null Tue Oct 29 15:57:07 2002
> +++ testsuite/newlib.string/memmove1.c Thu Jan 27 04:36:51 2005
> @@ -0,0 +1,184 @@
> +/* A minor test-program for memmove.
> + Copyright (C) 2005 Axis Communications.
> + All rights reserved.
> +
> + Redistribution and use in source and binary forms, with or without
> + modification, are permitted provided that the following conditions
> + are met:
> +
> + 1. Redistributions of source code must retain the above copyright
> + notice, this list of conditions and the following disclaimer.
> +
> + 2. Neither the name of Axis Communications nor the names of its
> + contributors may be used to endorse or promote products derived
> + from this software without specific prior written permission.
> +
> + THIS SOFTWARE IS PROVIDED BY AXIS COMMUNICATIONS AND ITS CONTRIBUTORS
> + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AXIS
> + COMMUNICATIONS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
> + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
> + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
> + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
> + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> + POSSIBILITY OF SUCH DAMAGE. */
> +
> +/* Test moves of 0..MAX bytes; overlapping-src-higher,
> + overlapping-src-lower and non-overlapping. The overlap varies with
> + 1..N where N is the size moved. This means an order of MAX**2
> + iterations. The size of an octet may seem appropriate for MAX and
> + makes an upper limit for simple testing. For the CRIS simulator,
> + making this 256 added 90s to the test-run (2GHz P4) while 64 (4s) was
> + enough to spot the bugs that had crept in, hence the number chosen. */
> +#define MAX 64
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +
> +#define TOO_MANY_ERRORS 11
> +int errors = 0;
> +
> +#define DEBUGP \
> + if (errors == TOO_MANY_ERRORS) \
> + printf ("Further errors omitted\n"); \
> + else if (errors < TOO_MANY_ERRORS) \
> + printf
> +
> +/* A safe target-independent memmove. */
> +
> +void
> +mymemmove (unsigned char *dest, unsigned char *src, size_t n)
> +{
> + size_t i;
> +
> + if ((src <= dest && src + n <= dest)
> + || src >= dest)
> + while (n-- > 0)
> + *dest++ = *src++;
> + else
> + {
> + dest += n;
> + src += n;
> + while (n-- > 0)
> + *--dest = *--src;
> + }
> +}
> +
> +/* It's either the noinline attribute or forcing the test framework to
> + pass -fno-builtin-memmove. */
> +void
> +xmemmove (unsigned char *dest, unsigned char *src, size_t n)
> + __attribute__ ((__noinline__));
> +
> +void
> +xmemmove (unsigned char *dest, unsigned char *src, size_t n)
> +{
> + void *retp;
> + retp = memmove (dest, src, n);
> +
> + if (retp != dest)
> + {
> + errors++;
> + DEBUGP ("memmove of n bytes returned %p instead of dest=%p\n",
> + retp, dest);
> + }
> +}
> +
> +
> +/* Fill the array with something we can associate with a position, but
> + not exactly the same as the position index. */
> +
> +void
> +fill (unsigned char dest[MAX*3])
> +{
> + size_t i;
> + for (i = 0; i < MAX*3; i++)
> + dest[i] = (10 + i) % MAX;
> +}
> +
> +int
> +main (void)
> +{
> + size_t i;
> + int errors = 0;
> +
> + /* Leave some room before and after the area tested, so we can detect
> + overwrites of up to N bytes, N being the amount tested. If you
> + want to test using valgrind, make these malloced instead. */
> + unsigned char from_test[MAX*3];
> + unsigned char to_test[MAX*3];
> + unsigned char from_known[MAX*3];
> + unsigned char to_known[MAX*3];
> +
> + /* Non-overlap. */
> + for (i = 0; i < MAX; i++)
> + {
> + /* Do the memmove first before setting the known array, so we know
> + it didn't change any of the known array. */
> + fill (from_test);
> + fill (to_test);
> + xmemmove (to_test + MAX, 1 + from_test + MAX, i);
> +
> + fill (from_known);
> + fill (to_known);
> + mymemmove (to_known + MAX, 1 + from_known + MAX, i);
> +
> + if (memcmp (to_known, to_test, sizeof (to_known)) != 0)
> + {
> + errors++;
> + DEBUGP ("memmove failed non-overlap test for %d bytes\n", i);
> + }
> + }
> +
> + /* Overlap-from-before. */
> + for (i = 0; i < MAX; i++)
> + {
> + size_t j;
> + for (j = 0; j < i; j++)
> + {
> + fill (to_test);
> + xmemmove (to_test + MAX * 2 - i, to_test + MAX * 2 - i - j, i);
> +
> + fill (to_known);
> + mymemmove (to_known + MAX * 2 - i, to_known + MAX * 2 - i - j, i);
> +
> + if (memcmp (to_known, to_test, sizeof (to_known)) != 0)
> + {
> + errors++;
> + DEBUGP ("memmove failed for %d bytes,"
> + " with src %d bytes before dest\n",
> + i, j);
> + }
> + }
> + }
> +
> + /* Overlap-from-after. */
> + for (i = 0; i < MAX; i++)
> + {
> + size_t j;
> + for (j = 0; j < i; j++)
> + {
> + fill (to_test);
> + xmemmove (to_test + MAX, to_test + MAX + j, i);
> +
> + fill (to_known);
> + mymemmove (to_known + MAX, to_known + MAX + j, i);
> +
> + if (memcmp (to_known, to_test, sizeof (to_known)) != 0)
> + {
> + errors++;
> + DEBUGP ("memmove failed when moving %d bytes,"
> + " with src %d bytes after dest\n",
> + i, j);
> + }
> + }
> + }
> +
> + if (errors != 0)
> + abort ();
> + exit (0);
> +}
>
>
> --- libc/machine/cris/memmove.c.bad Tue Jan 25 12:47:31 2005
> +++ libc/machine/cris/memmove.c Wed Jan 26 15:30:19 2005
> @@ -71,7 +71,7 @@ memmove(void *pdst, const void *psrc, si
>
> return return_dst;
> }
> - /* Whew, no overlap. Proceed as with mempcy. We could call it instead
> + /* Whew, no overlap. Proceed as with memcpy. We could call it instead
> of having a copy here. That would spoil some of the optimization, so
> we take the trouble with having two copies. */
>
> @@ -191,7 +191,7 @@ memmove(void *pdst, const void *psrc, si
>
> case 6:
> *(long *) dst = *(long *) src; dst += 4; src += 4;
> - *dst = *src;
> + *(short *) dst = *(short *) src;
> break;
>
> case 7:
> @@ -214,13 +214,13 @@ memmove(void *pdst, const void *psrc, si
> case 10:
> *(long *) dst = *(long *) src; dst += 4; src += 4;
> *(long *) dst = *(long *) src; dst += 4; src += 4;
> - *dst = *src;
> + *(short *) dst = *(short *) src;
> break;
>
> case 11:
> *(long *) dst = *(long *) src; dst += 4; src += 4;
> *(long *) dst = *(long *) src; dst += 4; src += 4;
> - *(short *) dst = *(short *) src; dst += 4; src += 4;
> + *(short *) dst = *(short *) src; dst += 2; src += 2;
> *dst = *src;
> break;
>
> @@ -248,7 +248,7 @@ memmove(void *pdst, const void *psrc, si
> *(long *) dst = *(long *) src; dst += 4; src += 4;
> *(long *) dst = *(long *) src; dst += 4; src += 4;
> *(long *) dst = *(long *) src; dst += 4; src += 4;
> - *(short *) dst = *(short *) src; dst += 4; src += 4;
> + *(short *) dst = *(short *) src; dst += 2; src += 2;
> *dst = *src;
> break;
> }
> --- libc/machine/cris/memset.c.bad Tue Jan 25 12:47:43 2005
> +++ libc/machine/cris/memset.c Wed Jan 26 15:33:12 2005
> @@ -222,7 +222,7 @@ void *memset(void *pdst, int c, unsigned
> *(long *) dst = lc; dst += 4;
> *(long *) dst = lc; dst += 4;
> *(short *) dst = (short) lc; dst += 2;
> - *(char*) dst = (char) lc;
> + *dst = (char) lc;
> break;
>
> case 12:
>
> brgds, H-P
More information about the Newlib
mailing list