https://llvm.org/bugs/show_bug.cgi?id=27526
Bug ID: 27526 Summary: Wrong optimization of sprintf Product: clang Version: trunk Hardware: PC OS: Linux Status: NEW Severity: normal Priority: P Component: -New Bugs Assignee: unassignedclangb...@nondot.org Reporter: chere...@mccme.ru CC: llvm-bugs@lists.llvm.org Classification: Unclassified The program: #include <stdio.h> int main() { char s[] = "abcdef"; sprintf(s, "%s", s + 3); printf(">%s<\n", s); } should print ">def<" but prints "><" when compiled with clang -O. It works fine when compiled with gcc. Tested with clang 3.50 and 3.9.0 (trunk 267340) on Debian x86-64. The reason is that sprintf(..., "%s", ...) is optimized into memcpy(..., ..., strlen(...) + 1) and glibc's memcpy then presumably copies the string backwards. To use memcpy one have to be sure that memory blocks don't overlap. This is more or less guaranteed for sprintf as its description in C11, 7.21.6.6p2 reads: "If copying takes place between objects that overlap, the behavior is undefined." But there is a subtle point here. The 's' conversion specifier doesn't copy the terminating null from the source string -- C11, 7.21.6.1p8: "Characters from the array are written up to (but not including) the terminating null character." IOW copying non-null chars and writing the terminating null char to the destination array are two distinct actions. In particular, I don't think C11 requires the argument for the 's' specifier not to overlap with the (future) terminating null in the destination array. Then, C11, 7.21.6p1 reads: "The formatted input/output functions shall behave as if there is a sequence point after the actions associated with each specifier." That is, in our example, all non-null chars have to be fully read and written before the terminating null is written. To summarize: sprintf(..., "%s", ...) is a two-step process and cannot be reduced to one memcpy. -- You are receiving this mail because: You are on the CC list for the bug.
_______________________________________________ llvm-bugs mailing list llvm-bugs@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs