This is the mail archive of the newlib@sources.redhat.com mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Bugs in libc/machine/cris/memmove.c, memmove test-case


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]