Bug 759493

Summary: Wrong strcpy() when shifting left a single place
Product: [Fedora] Fedora Reporter: Jean-Pierre AndrĂ© <jean-pierre.andre>
Component: glibcAssignee: Jeff Law <law>
Status: CLOSED NOTABUG QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: high Docs Contact:
Priority: unspecified    
Version: 16CC: fweimer, jakub, law, schwab
Target Milestone: ---   
Target Release: ---   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2011-12-02 14:41:12 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:

Description Jean-Pierre André 2011-12-02 14:28:02 UTC
Description of problem:

Error in strcpy() in 32 bit mode on a 64 bit OS

Version-Release number of selected component (if applicable):

glibc-2.14.90-19.i686.rpm

How reproducible:

Always

Steps to Reproduce:
1. Execute the simple program below, which shifts left one position a 16 char string.
2.
3.
  
Actual results:
A part of the string has been shifted two places

Expected results:
The full string should be shifted a single place


#include <stdio.h>
#include <string.h>  /* strcpy() must not be inlined */

main()
{
	char dst[30];
	char *src = "abcdefghijklmnopq"; /* 17 chars */

	strcpy(dst,src); /* plain copy */
        strcpy(dst,dst+1); /* shift left one position */
	printf("src %s\ndst %s\n",src,dst);
	return (0);
}

[linux@dimension emacs]$ ./copy
src abcdefghijklmnopq
dst bcdefhijklmnopqq

This happens in the following sequence, and could be related to some level of harware cache badly shared between the source and destination on the processor used (cpuinfo below).

:4AF7B151 660FEFC0                pxor xmm(0),xmm(0)
:4AF7B155 F30F6F09                movdqu xmm(1),oword [ecx]
:4AF7B159 F30F7F0A                movdqu oword [edx],xmm(1)
:4AF7B15D 660F7403                pcmpeqb xmm(0),qword [ebx]
:4AF7B161 660FD7C0                pmovmskb xmm(0),xmm(0)
:4AF7B165 29CB                    sub ebx,ecx

Additional info:

[linux@dimension emacs]$ cat /proc/cpuinfo
processor	: 0
vendor_id	: AuthenticAMD
cpu family	: 15
model		: 75
model name	: AMD Athlon(tm) 64 X2 Dual Core Processor 4200+
stepping	: 2
cpu MHz		: 1000.000
cache size	: 512 KB

Comment 1 Jakub Jelinek 2011-12-02 14:41:12 UTC
Calling strcpy that way is invalid.
Read e.g. man 3p strcpy:
"If copying takes place between objects that overlap, the behavior is undefined."
this wording or similar is in ISO C99 as well as POSIX.
You need to use memmove for such an overlapping operation.