Fwd: [libiberty] problem with unaligned pointers when using md5_process_bytes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

I request your help on the following problem:
Recently, I used the libiberty md5_process_bytes function (for some MELT code) and got a problem with it:

I don't know why but on some systems (debian i686) I got some unaligned pointers (only when using MELT, I could not reproduce elsewhere, so that might come from me or from MELT). Normally, even with unaligned pointers, this should works as the function md5_process_bytes handles this case:

#if !_STRING_ARCH_unaligned
/* To check alignment gcc has an appropriate operator.  Other
 compilers don't.  */
# if __GNUC__ >= 2
# define UNALIGNED_P(p) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0)
# else
# define UNALIGNED_P(p) (((md5_uintptr) p) % sizeof (md5_uint32) != 0)
# endif
	len --;
    if (UNALIGNED_P (buffer))
      while (len > 64)
        {
			memcpy (ctx->buffer, buffer, 64);
          md5_process_block (ctx->buffer, 64, ctx);
          buffer = (const char *) buffer + 64;
          len -= 64;
        }
    else
#endif
    md5_process_block (buffer, len & ~63, ctx);
    buffer = (const void *) ((const char *) buffer + (len & ~63));
    len &= 63;
  }

However the handling looks quite strange to me, if UNALIGNED_P (buffer) (as this is the case for me) is true, we normally travel the while, but then, we execute a new time the line "buffer = (const void *) ((const char *) buffer + (len & ~63));", which appear to shift the buffer a new time (for more detail, you can have a look at my given gdb trace).

I was able to fully compile GCC MELT branch by only adding a pair of braces as you can see on the given diff file. I guess this is a bug in libiberty (even if I can't understand why my pointer is not aligned).

So can you confirm (or no) that there is a bug in this function (I can post to gcc-patches if you think it is a bug), and give me informations about how to explain the fact that I get unaligned pointers.

Thanks a lot for your help!

Pierre Vittet
dpierre@Octave gcc %gdb --args ./cc1 @warmelt-firstmelt-stage1.args                                                                                                                                                                     [0]
GNU gdb (GDB) 7.2-debian
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/dpierre/programmation/melt/gcc_melt_build/gcc/cc1...done.
Breakpoint 1 at 0x8df215d: file /home/dpierre/programmation/melt/gcc_melt_source/gcc/diagnostic.c, line 893.
Breakpoint 2 at 0x8df206b: file /home/dpierre/programmation/melt/gcc_melt_source/gcc/diagnostic.c, line 837.
Breakpoint 3 at 0x80cc9f0
Breakpoint 4 at 0x80cce20
(gdb) break md5_process_bytes 
Breakpoint 5 at 0x8e3461c: file /home/dpierre/programmation/melt/gcc_melt_source/libiberty/md5.c, line 206.
(gdb) run
Breakpoint 5, md5_process_bytes (buffer=0xbfffe3f6, len=1024, ctx=0xbfffe358) at /home/dpierre/programmation/melt/gcc_melt_source/libiberty/md5.c:206
206	  if (ctx->buflen != 0)
(gdb) n
228	  if (len > 64)
(gdb) n
238	      if (UNALIGNED_P (buffer))
(gdb) l
233	# if __GNUC__ >= 2
234	#  define UNALIGNED_P(p) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0)
235	# else
236	#  define UNALIGNED_P(p) (((md5_uintptr) p) % sizeof (md5_uint32) != 0)
237	# endif
238	      if (UNALIGNED_P (buffer))
239	        while (len > 64)
240	          {
241		    memcpy (ctx->buffer, buffer, 64);
242	            md5_process_block (ctx->buffer, 64, ctx);
(gdb) n
239	        while (len > 64)
(gdb) l
234	#  define UNALIGNED_P(p) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0)
235	# else
236	#  define UNALIGNED_P(p) (((md5_uintptr) p) % sizeof (md5_uint32) != 0)
237	# endif
238	      if (UNALIGNED_P (buffer))
239	        while (len > 64)
240	          {
241		    memcpy (ctx->buffer, buffer, 64);
242	            md5_process_block (ctx->buffer, 64, ctx);
243	            buffer = (const char *) buffer + 64;
(gdb) 
244	            len -= 64;
245	          }
246	      else
247	#endif
248	      md5_process_block (buffer, len & ~63, ctx);
249	      buffer = (const void *) ((const char *) buffer + (len & ~63));
250	      len &= 63;
251	    }
252	
253	  /* Move remaining bytes in internal buffer.  */
(gdb) break 248
Breakpoint 6 at 0x8e347b6: file /home/dpierre/programmation/melt/gcc_melt_source/libiberty/md5.c, line 248.
(gdb) break 249
Breakpoint 7 at 0x8e347d4: file /home/dpierre/programmation/melt/gcc_melt_source/libiberty/md5.c, line 249.
(gdb) c
Continuing.

Breakpoint 7, md5_process_bytes (buffer=0xbfffe7b6, len=64, ctx=0xbfffe358) at /home/dpierre/programmation/melt/gcc_melt_source/libiberty/md5.c:249
249	      buffer = (const void *) ((const char *) buffer + (len & ~63));
(gdb) c
Continuing.

Breakpoint 7, md5_process_bytes (buffer=0xbfffe7b6, len=64, ctx=0xbfffe358) at /home/dpierre/programmation/melt/gcc_melt_source/libiberty/md5.c:249
249	      buffer = (const void *) ((const char *) buffer + (len & ~63));
(gdb) print (len & ~63)
$1 = 64
(gdb) print buffer
$2 = (const void *) 0xbfffe7b6
(gdb) print (char *) buffer
$3 = 0xbfffe7b6 "r FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Pub"
(gdb) n
250	      len &= 63;
(gdb) print (char *) buffer
$4 = 0xbfffe7f6 ""
(gdb) print len
$5 = 64
#We see that buffer has been shift while we don't want this (it is empty while len != 0)
Index: libiberty/md5.c
===================================================================
--- libiberty/md5.c	(révision 178851)
+++ libiberty/md5.c	(copie de travail)
@@ -245,9 +245,11 @@ md5_process_bytes (const void *buffer, size_t len,
           }
       else
 #endif
+      {
       md5_process_block (buffer, len & ~63, ctx);
       buffer = (const void *) ((const char *) buffer + (len & ~63));
       len &= 63;
+      }
     }
 
   /* Move remaining bytes in internal buffer.  */

[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux