https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86528
Bug ID: 86528 Summary: strlen of constant string malfunction -- had to back out fix for PR middle-end/77357 Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: jim at meyering dot net Target Milestone: --- gcc miscompiles latest emacs' fileio.c(file_accessible_directory_p) It all started with a new unwarranted warning from emacs. This one is ok: /p/emacs-2018-07-11.10h58/bin/emacs k this one and all subsequent (up to at least 2018-07-15) emit a warning: /p/emacs-2018-07-12.10h35/bin/emacs k Here's the warning: Warning (initialization): Unable to access `user-emacs-directory' (~/.emacs.d/). Any data that would normally be written there may be lost! If you never want to see this message again, customize the variable `user-emacs-directory-warning'. That's obviously wrong, because that directory *does* exist. Running it under strace shows a suspicious file name. It looks like use of uninitialized memory: $ strace -efile -ok.log emacs -q k $ grep -m3 x/.ema k.log faccessat(AT_FDCWD, "/m/.emacs.d/abbrev_defs", R_OK) = 0 openat(AT_FDCWD, "/m/.emacs.d", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_PATH) = 7 faccessat(AT_FDCWD, "/m/.emacs.d/\10YY|\376\177", F_OK) = -1 ENOENT (No such file or directory) Once the debugger showed which lines were involved, I found that this patch works around it. Besides, I have a tiny preference for memcpy over strcpy, since the length is known. diff --git a/src/fileio.c b/src/fileio.c index 5a1c7ae10e..3363cc0cf6 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -2861,9 +2861,11 @@ file_accessible_directory_p (Lisp_Object file) here. After appending '.', append another '/' to work around a macOS bug (Bug#30350). */ static char const appended[] = "/./"; + bool trailing_slash = data[len - 1] == '/'; char *buf = SAFE_ALLOCA (len + sizeof appended); memcpy (buf, data, len); - strcpy (buf + len, &appended[data[len - 1] == '/']); + memcpy (buf + len, &appended[trailing_slash], + sizeof appended - trailing_slash); dir = buf; } Then, I realized: it's related to a recent change in gcc and optimization. I had built latest emacs with latest built-from-git gcc. Emacs works when built with gcc from around July 8: rm src/fileio.o;make CC=/p/p/gcc-2018-07-08.16h57/bin/gcc CFLAGS='-ggdb3 -O2' Yet fails when built with gcc from July 11: rm src/fileio.o;make CC=/p/p/gcc-2018-07-11.11h00/bin/gcc CFLAGS='-ggdb3 -O2' Also, -O0 works in either case. Bisecting gcc led me to a commit that involves strlen of constant, which is what the replaced strcpy uses. 47d2cd73185a207ecc90970a73f5b38b114c48c2 PR middle-end/77357 - strlen of constant strings not folded Revert that, and emacs once again works when compiled with latest gcc.