strcpy output incorrect if src and dst overlap

Bug #810739 reported by Vadim Gutnik
20
This bug affects 4 people
Affects Status Importance Assigned to Milestone
eglibc (Ubuntu)
Confirmed
Undecided
Unassigned

Bug Description

A commercial application (Cadence) that runs with an older libc gives
incorrect results with the current libc. I've tracked down the
problem to strcpy. If I make my own strcopy, following the template of
https://bugzilla.redhat.com/show_bug.cgi?id=638477#c38, the tool gives
correct results. Here is mystrcpy.c:

$ cat mystrcpy.c

char *strcpy(char *dest, const char *src){
  char *destcopy=dest;
  while(*dest++ = *src++)
        ;
  return destcopy;
}

I've traced through the application and see that it
is calling strcpy with overlapping source and destination,
and that the execution goes through __strcpy_ssse3,
which seems to cause the problem.

I made a small testcase to replicate the behavior.
Following http://forums.gentoo.org/viewtopic-t-840983-start-0.html,
here is my test case:
------------
$ cat strcopytest.c
char *strcpy(char *,char *);
int main(){
        char buf[80];
        strcpy(buf, "012345678\n");
        strcpy(buf, buf+1);
        puts(buf);
        return 0;
}

$ gcc -O2 -c mystrcpy.c
$ ld -G mystrcpy.o -o mystrcpy.so
$ gcc strcopytest.c -o strcopytest
$ ./strcopytest
12345688

$ LD_PRELOAD=./mystrcpy.so ./strcopytest
12345678

----------------

I know that I can make my testcase work with #include "string.h",
but the I cannot recompile the commercial application, so that's not
a workable solution.

ProblemType: Bug
DistroRelease: Ubuntu 11.04
Package: libc6 2.13-0ubuntu13
ProcVersionSignature: Ubuntu 2.6.39-3.10-generic 2.6.39
Uname: Linux 2.6.39-3-generic x86_64
Architecture: amd64
Date: Thu Jul 14 13:43:36 2011
InstallationMedia: Ubuntu 10.04 "Lucid Lynx" - Beta amd64 (20100317.1)
ProcEnviron:
 LANGUAGE=en_US:en
 PATH=(custom, user)
 LANG=en_US.UTF-8
 SHELL=/bin/bash
SourcePackage: eglibc
UpgradeStatus: Upgraded to natty on 2011-04-29 (76 days ago)

Revision history for this message
Vadim Gutnik (gutnik) wrote :
Revision history for this message
Launchpad Janitor (janitor) wrote :

Status changed to 'Confirmed' because the bug affects multiple users.

Changed in eglibc (Ubuntu):
status: New → Confirmed
Revision history for this message
Rico Zoss (rico.zoss) wrote :
Download full text (3.6 KiB)

I can confirm this Problem using a old version of gcc for cross compiling.:

ppc_8xx-gcc (GCC) 4.2.2
Copyright (C) 2007 Free Software Foundation, Inc.

The problem is the parsing of the include paths:

Output of strace:
15791 stat64("/opt/eldk_4.2/ppsr/libusr/lib/gcc/powerpc-linux//includude/c++/4./c++/4.2.2/powerpc-linux", 0xffc9eb00) = -1 ENOENT (No such file or directory)
15791 stat64("/opt/eldk_4.2/ppsr/libusr/lib/gcc/powerpc-linux//includude/c++/4./c++/4.2.2/backward", 0xffc9eb00) = -1 ENOENT (No such file or directory)

As you can see the path was mixed up and therefore the include files could not be found.

Output of ltrace:
15801 strchr("/opt/eldk_4.2/usr/../ppc_8xx/usr"..., '/') = "/opt/eldk_4.2/usr/../ppc_8xx/usr"...
15801 strchr("opt/eldk_4.2/usr/../ppc_8xx/usr/"..., '/') = "/eldk_4.2/usr/../ppc_8xx/usr/lib"...
15801 strchr("eldk_4.2/usr/../ppc_8xx/usr/lib/"..., '/') = "/usr/../ppc_8xx/usr/lib/gcc/powe"...
15801 strchr("usr/../ppc_8xx/usr/lib/gcc/power"..., '/') = "/../ppc_8xx/usr/lib/gcc/powerpc-"...
15801 strcpy(0x092d87cd, "/ppc_8xx/usr/lib/gcc/powerpc-lin"...) = 0x092d87cd
15801 strchr("/ppsr/libusr/lib/gcc/powerpc-lin"..., '/') = "/ppsr/libusr/lib/gcc/powerpc-lin"...
15801 strchr("ppsr/libusr/lib/gcc/powerpc-linu"..., '/') = "/libusr/lib/gcc/powerpc-linux/./"...
15801 strchr("libusr/lib/gcc/powerpc-linux/./."..., '/') = "/lib/gcc/powerpc-linux/./../../."...
15801 strchr("lib/gcc/powerpc-linux/./../../.."..., '/') = "/gcc/powerpc-linux/./../../../in"...
15801 strchr("gcc/powerpc-linux/./../../../inc"..., '/') = "/powerpc-linux/./../../../includ"...
15801 strchr("powerpc-linux/./../../../include"..., '/') = "/./../../../include/c++/4./c++/4"...
15801 strcpy(0x092d87ef, "/../../../include/c++/4./c++/4.2"...) = 0x092d87ef
15801 strchr("../../includude/c++/4./c++/4.2.2"..., '/') = "/../includude/c++/4./c++/4.2.2/p"...
15801 strcpy(0x092d87f0, "/includude/c++/4./c++/4.2.2/powe"...) = 0x092d87f0
15801 strchr("/includude/c++/4./c++/4.2.2/powe"..., '/') = "/includude/c++/4./c++/4.2.2/powe"...
15801 strchr("includude/c++/4./c++/4.2.2/power"..., '/') = "/c++/4./c++/4.2.2/powerpc-linux"
15801 strchr("c++/4./c++/4.2.2/powerpc-linux", '/') = "/4./c++/4.2.2/powerpc-linux"
15801 strchr("4./c++/4.2.2/powerpc-linux", '/') = "/c++/4.2.2/powerpc-linux"
15801 strchr("c++/4.2.2/powerpc-linux", '/') = "/4.2.2/powerpc-linux"
...

Read more...

Revision history for this message
Adam Conrad (adconrad) wrote :

Does this bug still affect precise? If it's the sse3 memcpy bug, it should have been fixed in git before 2.15 was cut, so precise and quantal should be fine. Can anyone confirm?

Revision history for this message
Rico Zoss (rico.zoss) wrote :

I can still confim this bug in precise. My version of libc-bin is 2.15-0ubuntu10.2.

Revision history for this message
Matthias Klose (doko) wrote :

strcpy(3):

DESCRIPTION
       [...] The strings may not overlap, and the destination string
       dest must be large enough to receive the copy.

18 months should be sufficient to even fix a commercial application.

Changed in eglibc (Ubuntu):
status: Confirmed → Invalid
Revision history for this message
Vadim Gutnik (gutnik) wrote :

Invalid? First, the application has not fixed it. They don't support every kernel as it comes out, so I have a choice between running Ubuntu or running my primary work application.

Second, not everyone (see the link the original report) sees this as a bug in the application. A strong argument can be made that this is a bug in the kernel, and that there is no actual performance benefit to the change.

The fact that this regression is documented doesn't make it a feature.

Revision history for this message
Distro-jumper (boblounsbury) wrote :

Any news on this?? I can confirm the behavior on precise as well, version 2.15-0ubuntu10.3.

Revision history for this message
Distro-jumper (boblounsbury) wrote :

It appears that this has been reverted by Red Hat to the old behavior:
https://bugzilla.redhat.com/show_bug.cgi?id=781646
http://rhn.redhat.com/errata/RHBA-2012-0763.html

Is Ubuntu going to provide a regression to the old behavior??

Changed in eglibc (Ubuntu):
status: Invalid → Confirmed
Revision history for this message
Elango (elango-go) wrote :

Any update on this bug.

I have a native application working fine in Ubuntu 10.04 but failing in Ubuntu 12.04 due to overlapping memory passed to strcpy. Kindly let me know how I can fix/patch strcpy implementationn.

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

@elango-go

you may fetch an older glibc and preload it before launching your affected application.

Alternatively, maybe it should be considered to provide a wrapper script that preloads old variant off strcpy.

Doko, 18 months is long enough... if the software in question is at all developed/updated still...

Revision history for this message
Elango (elango-go) wrote :

Thanks Dmitrijis. Can you help me/provide pointers how I can preload an older glibc.

Revision history for this message
Elango (elango-go) wrote :

I have preloaded the strcpy implementation from glibc version 2.18 and solves the overlap string copy issues.
Thanks Dmitrijs Ledkovs.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.