Codegen bug in current CVS on x86

Zack Weinberg zack@rabi.columbia.edu
Wed Feb 10 07:32:00 GMT 1999


The present CVS tree miscompiles glibc's strncpy.c, such that under
some conditions it will segfault when handed perfectly well-formed
arguments.  I've been unable to come up with a self-contained
testcase, but this reliably happens when strncpy is used by the
`rpcgen' program as part of the libc build.

I've attached the C source for strncpy.c and the assembly output for
egcs 1.1.1 and the current snapshot (-O2 -mpentium).  I think the
problem is that the source pointer sometimes gets initialized to
garbage, but I get lost in all those pointless flushes to memory...

zw

#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 1999-02-10 10:21 EST by <zack@midnite>.
# Source directory was `/usr/home/zack/t'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode       name
# ------ ---------- ------------------------------------------
#    798 -rw-r--r-- strncpy.c
#   1645 -rw-r--r-- strncpy.s
#   1329 -rw-r--r-- strncpy.s.111
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
     && ($dir/gettext --version >/dev/null 2>&1)
  then
    set `$dir/gettext --version 2>&1`
    if test "$3" = GNU
    then
      gettext_dir=$dir
    fi
  fi
  if test "$locale_dir" = FAILED && test -f $dir/shar \
     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
  then
    locale_dir=`$dir/shar --print-text-domain-dir`
  fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
  echo=echo
else
  TEXTDOMAINDIR=$locale_dir
  export TEXTDOMAINDIR
  TEXTDOMAIN=sharutils
  export TEXTDOMAIN
  echo="$gettext_dir/gettext -s"
fi
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
  shar_touch=touch
else
  shar_touch=:
  echo
  $echo 'WARNING: not restoring timestamps.  Consider getting and'
  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 1231235999 $$.touch
#
if mkdir _sh15926; then
  $echo 'x -' 'creating lock directory'
else
  $echo 'failed to create lock directory'
  exit 1
fi
# ============= strncpy.c ==============
if test -f 'strncpy.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'strncpy.c' '(file already exists)'
else
  $echo 'x -' extracting 'strncpy.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'strncpy.c' &&
typedef unsigned long size_t;
X
char *
strncpy (s1, s2, n)
X     char *s1;
X     const char *s2;
X     size_t n;
{
X  char c;
X  char *s = s1;
X
X  --s1;
X
X  if (n >= 4)
X    {
X      size_t n4 = n >> 2;
X
X      for (;;)
X	{
X	  c = *s2++;
X	  *++s1 = c;
X	  if (c == '\0')
X	    break;
X	  c = *s2++;
X	  *++s1 = c;
X	  if (c == '\0')
X	    break;
X	  c = *s2++;
X	  *++s1 = c;
X	  if (c == '\0')
X	    break;
X	  c = *s2++;
X	  *++s1 = c;
X	  if (c == '\0')
X	    break;
X	  if (--n4 == 0)
X	    goto last_chars;
X	}
X      n = n - (s1 - s) - 1;
X      if (n == 0)
X	return s;
X      goto zero_fill;
X    }
X
X last_chars:
X  n &= 3;
X  if (n == 0)
X    return s;
X
X  do
X    {
X      c = *s2++;
X      *++s1 = c;
X      if (--n == 0)
X	return s;
X    }
X  while (c != '\0');
X
X zero_fill:
X  do
X    *++s1 = '\0';
X  while (--n > 0);
X
X  return s;
}
SHAR_EOF
  $shar_touch -am 021010201999 'strncpy.c' &&
  chmod 0644 'strncpy.c' ||
  $echo 'restore of' 'strncpy.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'strncpy.c:' 'MD5 check failed'
35197ca4801e7b3a40dad4f2e289252d  strncpy.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'strncpy.c'`"
    test 798 -eq "$shar_count" ||
    $echo 'strncpy.c:' 'original size' '798,' 'current size' "$shar_count!"
  fi
fi
# ============= strncpy.s ==============
if test -f 'strncpy.s' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'strncpy.s' '(file already exists)'
else
  $echo 'x -' extracting 'strncpy.s' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'strncpy.s' &&
X	.file	"strncpy.c"
X	.version	"01.01"
gcc2_compiled.:
X.text
X	.align 4
X.globl strncpy
X	.type	 strncpy,@function
strncpy:
X	pushl %ebp
X	movl %esp,%ebp
X	subl $28,%esp
X	pushl %edi
X	pushl %esi
X	pushl %ebx
X	movl 12(%ebp),%ecx
X	movl 16(%ebp),%edx
X	movl 8(%ebp),%eax
X	movl %eax,-4(%ebp)
X	movl %eax,%ebx
X	decl %ebx
X	cmpl $3,%edx
X	jbe .L12
X	movl %edx,-8(%ebp)
X	shrl $2,-8(%ebp)
X	leal 2(%ecx),%esi
X	movl %esi,-20(%ebp)
X	movl %eax,%edi
X	jmp .L4
X	.p2align 4,,7
X.L10:
X	movl %edi,-28(%ebp)
X	leal 1(%ecx),%eax
X	movl %eax,-24(%ebp)
X	leal 3(%ecx),%esi
X	movl %esi,-16(%ebp)
X	decl -8(%ebp)
X	jz .L12
X.L4:
X	movl -16(%ebp),%esi
X	movb -3(%esi),%al
X	movl -28(%ebp),%esi
X	movb %al,(%esi)
X	testb %al,%al
X	je .L5
X	movl -24(%ebp),%esi
X	movb (%esi),%al
X	movl -28(%ebp),%esi
X	incl %esi
X	movl %esi,-12(%ebp)
X	movl -28(%ebp),%esi
X	movb %al,1(%esi)
X	testb %al,%al
X	je .L5
X	movl -20(%ebp),%esi
X	movb (%esi),%al
X	movb %al,2(%edi)
X	testb %al,%al
X	je .L5
X	movl -16(%ebp),%esi
X	addl $4,%ecx
X	addl $4,%edi
X	addl $4,%ebx
X	movb (%esi),%al
X	movl -12(%ebp),%esi
X	addl $4,-20(%ebp)
X	movb %al,-2(%esi)
X	testb %al,%al
X	jne .L10
X.L5:
X	movl %ebx,%eax
X	subl -4(%ebp),%eax
X	subl %eax,%edx
X	movl %edx,%eax
X	leal -1(%eax),%edx
X	testl %edx,%edx
X	jne .L23
X	jmp .L30
X	.p2align 4,,7
X.L12:
X	andl $3,%edx
X	je .L30
X	.p2align 4,,7
X.L17:
X	movb (%ecx),%al
X	incl %ecx
X	incl %ebx
X	movb %al,(%ebx)
X	decl %edx
X	jz .L30
X	testb %al,%al
X	jne .L17
X	.p2align 4,,7
X.L23:
X	incl %ebx
X	movb $0,(%ebx)
X	decl %edx
X	jnz .L23
X.L30:
X	movl -4(%ebp),%eax
X	popl %ebx
X	popl %esi
X	popl %edi
X	movl %ebp,%esp
X	popl %ebp
X	ret
X.Lfe1:
X	.size	 strncpy,.Lfe1-strncpy
X	.ident	"GCC: (GNU) egcs-2.93.06 19990209 (gcc2 ss-980929 experimental)"
SHAR_EOF
  $shar_touch -am 021009531999 'strncpy.s' &&
  chmod 0644 'strncpy.s' ||
  $echo 'restore of' 'strncpy.s' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'strncpy.s:' 'MD5 check failed'
2b8d4aa60b2ef1bb5614cf09a1cd12b4  strncpy.s
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'strncpy.s'`"
    test 1645 -eq "$shar_count" ||
    $echo 'strncpy.s:' 'original size' '1645,' 'current size' "$shar_count!"
  fi
fi
# ============= strncpy.s.111 ==============
if test -f 'strncpy.s.111' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'strncpy.s.111' '(file already exists)'
else
  $echo 'x -' extracting 'strncpy.s.111' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'strncpy.s.111' &&
X	.file	"strncpy.c"
X	.version	"01.01"
gcc2_compiled.:
X.text
X	.align 4
X.globl strncpy
X	.type	 strncpy,@function
strncpy:
X	pushl %ebp
X	movl %esp,%ebp
X	pushl %edi
X	pushl %esi
X	pushl %ebx
X	movl 8(%ebp),%edi
X	movl 12(%ebp),%edx
X	movl 16(%ebp),%ebx
X	leal -1(%edi),%ecx
X	cmpl $3,%ebx
X	jbe .L11
X	movb (%edx),%al
X	movl %ebx,%esi
X	incl %edx
X	shrl $2,%esi
X	movl %edi,%ecx
X	movb %al,(%edi)
X	testb %al,%al
X	je .L4
X	.p2align 4,,7
X.L6:
X	incl %ecx
X	movb (%edx),%al
X	incl %edx
X	movb %al,(%ecx)
X	testb %al,%al
X	je .L4
X	incl %ecx
X	movb (%edx),%al
X	incl %edx
X	movb %al,(%ecx)
X	testb %al,%al
X	je .L4
X	incl %ecx
X	movb (%edx),%al
X	incl %edx
X	movb %al,(%ecx)
X	testb %al,%al
X	je .L4
X	decl %esi
X	jz .L11
X	incl %ecx
X	movb (%edx),%al
X	incl %edx
X	movb %al,(%ecx)
X	testb %al,%al
X	jne .L6
X.L4:
X	movl %ecx,%eax
X	subl %edi,%eax
X	subl %eax,%ebx
X	movl %ebx,%eax
X	leal -1(%eax),%ebx
X	testl %ebx,%ebx
X	jne .L22
X	jmp .L29
X	.p2align 4,,7
X.L11:
X	andl $3,%ebx
X	je .L29
X	.p2align 4,,7
X.L16:
X	incl %ecx
X	movb (%edx),%al
X	incl %edx
X	movb %al,(%ecx)
X	decl %ebx
X	jz .L29
X	testb %al,%al
X	jne .L16
X	.p2align 4,,7
X.L22:
X	incl %ecx
X	movb $0,(%ecx)
X	decl %ebx
X	jnz .L22
X.L29:
X	movl %edi,%eax
X	leal -12(%ebp),%esp
X	popl %ebx
X	popl %esi
X	popl %edi
X	movl %ebp,%esp
X	popl %ebp
X	ret
X.Lfe1:
X	.size	 strncpy,.Lfe1-strncpy
X	.ident	"GCC: (GNU) egcs-2.91.60 Debian 2.1 (egcs-1.1.1 release)"
SHAR_EOF
  $shar_touch -am 021009541999 'strncpy.s.111' &&
  chmod 0644 'strncpy.s.111' ||
  $echo 'restore of' 'strncpy.s.111' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'strncpy.s.111:' 'MD5 check failed'
941666b71d19bd877169afb1994f8478  strncpy.s.111
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'strncpy.s.111'`"
    test 1329 -eq "$shar_count" ||
    $echo 'strncpy.s.111:' 'original size' '1329,' 'current size' "$shar_count!"
  fi
fi
rm -fr _sh15926
exit 0



More information about the Gcc-bugs mailing list