MemSet() must not cast its pointer argument to int32* until after it has
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 18 Jul 2005 15:53:46 +0000 (15:53 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 18 Jul 2005 15:53:46 +0000 (15:53 +0000)
checked that the pointer is actually word-aligned.  Casting a non-aligned
pointer to int32* is technically illegal per the C spec, and some recent
versions of gcc actually generate bad code for the memset() when given
such a pointer.  Per report from Andrew Morrow.

src/include/c.h

index 5f884d8f2f03d4384f3342ffb994c2c9ca1b7882..08ce6dd243f74021dee3d644e61223f630d83571 100644 (file)
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/c.h,v 1.178 2004/12/31 22:03:18 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/c.h,v 1.178.4.1 2005/07/18 15:53:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -593,21 +593,22 @@ typedef NameData *Name;
 #define MemSet(start, val, len) \
    do \
    { \
-       int32 * _start = (int32 *) (start); \
+       void   *_vstart = (void *) (start); \
        int     _val = (val); \
        Size    _len = (len); \
 \
-       if ((((long) _start) & INT_ALIGN_MASK) == 0 && \
+       if ((((long) _vstart) & INT_ALIGN_MASK) == 0 && \
            (_len & INT_ALIGN_MASK) == 0 && \
            _val == 0 && \
            _len <= MEMSET_LOOP_LIMIT) \
        { \
-           int32 * _stop = (int32 *) ((char *) _start + _len); \
+           int32 *_start = (int32 *) _vstart; \
+           int32 *_stop = (int32 *) ((char *) _start + _len); \
            while (_start < _stop) \
                *_start++ = 0; \
        } \
        else \
-           memset((char *) _start, _val, _len); \
+           memset(_vstart, _val, _len); \
    } while (0)
 
 #define MEMSET_LOOP_LIMIT  1024