Using current git sources compiled with gcc-4.9.1 or mainline gcc at
-O3 results in failure of random-test.

On powerpc64le we see
PASS:  random-test 1: random delta test
svn_tests: E200006: mismatch at position xxxxx
FAIL:  random-test 2: random combine delta test

x86_64 gives
PASS:  random-test 1: random delta test
svn_tests: E200006: Test crashed (run in debugger with '--allow-segfaults')
FAIL:  random-test 2: random combine delta test

After some digging, I narrowed the failure down to
subversion/libsvn_delta/text_delta.c, and the specific -O3 options
causing the failure to -ftree-loop-vectorize -fvect-cost-model=dynamic. 
At first I thought I'd found a vectorizer bug, but the real problem is
a bug in the source, specifically this line in patterning_copy:

      *(apr_uint32_t *)(target) = *(apr_uint32_t *)(source);

Quoting from ISO/IEC 9899:1999
6.3.2.3 Pointers
...
7 A pointer to an object or incomplete type may be converted to a
pointer to a different object or incomplete type. If the resulting
pointer is not correctly aligned for the pointed-to type, the behavior
is undefined.

So here we have undefined behaviour if "source" and "target" are not
4-byte aligned..  Fixed as follows.

Index: subversion/libsvn_delta/text_delta.c
===================================================================
--- subversion/libsvn_delta/text_delta.c        (revision 1616755)
+++ subversion/libsvn_delta/text_delta.c        (working copy)
@@ -669,14 +669,15 @@
 
 #if SVN_UNALIGNED_ACCESS_IS_OK
 
-  if (source + sizeof(apr_uint32_t) <= target)
+  typedef apr_uint32_t __attribute__ ((aligned (1))) unaligned32;
+  if (source + sizeof(unaligned32) <= target)
     {
       /* Source and target are at least 4 bytes apart, so we can copy in
        * 4-byte chunks.  */
-      for (; source + sizeof(apr_uint32_t) <= end;
-           source += sizeof(apr_uint32_t),
-           target += sizeof(apr_uint32_t))
-      *(apr_uint32_t *)(target) = *(apr_uint32_t *)(source);
+      for (; source + sizeof(unaligned32) <= end;
+           source += sizeof(unaligned32),
+           target += sizeof(unaligned32))
+      *(unaligned32 *)target = *(unaligned32 *)source;
     }
 
 #endif

-- 
Alan Modra
Australia Development Lab, IBM

Reply via email to