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

bug in memset()



I can't claim credit for finding this - Robin Watts tracked this one down.

       void *memset(void *s, int c, size_t n);

isn't masking the second parameter to a byte.

Test code:

#include <stdio.h>
#include <string.h>

int main () {
  char fred[16];
  int i = 0;
  memset(fred, 256, sizeof(fred));
  
  while (i < sizeof(fred)) {
    printf ("%d", fred[i]);
    if (++i < sizeof(fred))
      printf (", ");
  }
  puts("");
  return 0;
}

Returns:

debian-arm:  0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1
debian-x86:  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
FreeBSD-x86: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

[tested with glibc 2.2.4 on debian-arm]

Only source code I have to hand is 2.1.3, but assuming that
sysdeps/arm/memset.c is unchanged since then:

ENTRY(memset)
        mov     a4, a1
        cmp     a3, $8          @ at least 8 bytes to do?
        blt     2f
        orr     a2, a2, a2, lsl $8
        orr     a2, a2, a2, lsl $16
1:

should become

ENTRY(memset)
        mov     a4, a1
        cmp     a3, $8          @ at least 8 bytes to do?
        blt     2f
        and     a2, a2, #255
        orr     a2, a2, a2, lsl $8
        orr     a2, a2, a2, lsl $16
1:

(untested, suggested by Robin Watts, syntax errors my fault)

should glibc have a (platform independent) regression test to catch this?

Nicholas Clark



Reply to: