From 5609af083525dae86339be5c8548679363b1ed90 Mon Sep 17 00:00:00 2001 From: Paul Eggert
Date: Thu, 25 Dec 2014 04:19:17 -0800 Subject: [PATCH] Prefer stpcpy to strcat * admin/merge-gnulib (GNULIB_MODULES): Add stpcpy. * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate. * lib/stpcpy.c, m4/stpcpy.m4: New files, from gnulib. * lib-src/ebrowse.c (sym_scope_1, operator_name, open_file): * lib-src/emacsclient.c (get_server_config, set_local_socket) (start_daemon_and_retry_set_socket): * lib-src/etags.c (main, C_entries, relative_filename): * lib-src/pop.c (sendline): * lib-src/update-game-score.c (main): * lwlib/xlwmenu.c (resource_widget_value): * src/callproc.c (child_setup): * src/dbusbind.c (xd_signature_cat): * src/doc.c (get_doc_string, Fsnarf_documentation): * src/editfns.c (Fuser_full_name): * src/frame.c (xrdb_get_resource): * src/gtkutil.c (xg_get_file_with_chooser): * src/tparam.c (tparam1): * src/xfns.c (xic_create_fontsetname): * src/xrdb.c (gethomedir, get_user_db, get_environ_db): * src/xsmfns.c (smc_save_yourself_CB): Rewrite to avoid the need for strcat, typically by using stpcpy and/or liststpcpy. strcat tends to be part of O(N**2) algorithms. * src/doc.c (sibling_etc): * src/xrdb.c (xdefaults): Now a top-level static constant. --- ChangeLog | 29 +++++++++++++++++++++++++++ admin/merge-gnulib | 2 +- lib-src/ebrowse.c | 29 +++++++++++++++------------ lib-src/emacsclient.c | 35 +++++++++++++++----------------- lib-src/etags.c | 33 +++++++++++++++--------------- lib-src/pop.c | 3 +-- lib-src/update-game-score.c | 12 +++++------ lib/gnulib.mk | 11 +++++++++- lib/stpcpy.c | 49 +++++++++++++++++++++++++++++++++++++++++++++ lwlib/xlwmenu.c | 7 +++---- m4/gnulib-comp.m4 | 9 +++++++++ m4/stpcpy.m4 | 25 +++++++++++++++++++++++ src/callproc.c | 7 ++----- src/dbusbind.c | 2 +- src/doc.c | 33 +++++++++++------------------- src/editfns.c | 5 ++--- src/frame.c | 20 +++++++++--------- src/gtkutil.c | 6 +++--- src/tparam.c | 4 ++-- src/xfns.c | 34 +++++++++++++++---------------- src/xrdb.c | 44 ++++++++++++++++++---------------------- src/xsmfns.c | 6 ++---- 22 files changed, 252 insertions(+), 153 deletions(-) create mode 100644 lib/stpcpy.c create mode 100644 m4/stpcpy.m4 diff --git a/ChangeLog b/ChangeLog index 425984a..6ec465d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2014-12-25 Paul Eggert + + Prefer stpcpy to strcat + * admin/merge-gnulib (GNULIB_MODULES): Add stpcpy. + * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate. + * lib/stpcpy.c, m4/stpcpy.m4: New files, from gnulib. + * lib-src/ebrowse.c (sym_scope_1, operator_name, open_file): + * lib-src/emacsclient.c (get_server_config, set_local_socket) + (start_daemon_and_retry_set_socket): + * lib-src/etags.c (main, C_entries, relative_filename): + * lib-src/pop.c (sendline): + * lib-src/update-game-score.c (main): + * lwlib/xlwmenu.c (resource_widget_value): + * src/callproc.c (child_setup): + * src/dbusbind.c (xd_signature_cat): + * src/doc.c (get_doc_string, Fsnarf_documentation): + * src/editfns.c (Fuser_full_name): + * src/frame.c (xrdb_get_resource): + * src/gtkutil.c (xg_get_file_with_chooser): + * src/tparam.c (tparam1): + * src/xfns.c (xic_create_fontsetname): + * src/xrdb.c (gethomedir, get_user_db, get_environ_db): + * src/xsmfns.c (smc_save_yourself_CB): + Rewrite to avoid the need for strcat, typically by using stpcpy + and/or liststpcpy. strcat tends to be part of O(N**2) algorithms. + * src/doc.c (sibling_etc): + * src/xrdb.c (xdefaults): + Now a top-level static constant. + 2014-12-24 Stephen Leake * CONTRIBUTE: Move user-level information to doc/emacs/trouble.texi. diff --git a/admin/merge-gnulib b/admin/merge-gnulib index 64514f7..84c6ebf 100755 --- a/admin/merge-gnulib +++ b/admin/merge-gnulib @@ -36,7 +36,7 @@ GNULIB_MODULES=' manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat sig2str socklen stat-time stdalign stddef stdio - strftime strtoimax strtoumax symlink sys_stat + stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r timer-time timespec-add timespec-sub unsetenv update-copyright utimens vla warnings diff --git a/lib-src/ebrowse.c b/lib-src/ebrowse.c index 29a88e8..b743159 100644 --- a/lib-src/ebrowse.c +++ b/lib-src/ebrowse.c @@ -1150,19 +1150,19 @@ sym_scope_1 (struct sym *p) if (*scope_buffer) { ensure_scope_buffer_room (3); - strcat (scope_buffer, "::"); + strcpy (scope_buffer + scope_buffer_len, "::"); scope_buffer_len += 2; } len = strlen (p->name); ensure_scope_buffer_room (len + 1); - strcat (scope_buffer, p->name); + strcpy (scope_buffer + scope_buffer_len, p->name); scope_buffer_len += len; if (HAS_FLAG (p->flags, F_TEMPLATE)) { ensure_scope_buffer_room (3); - strcat (scope_buffer, "<>"); + strcpy (scope_buffer + scope_buffer_len, "<>"); scope_buffer_len += 2; } @@ -2797,24 +2797,25 @@ operator_name (int *sc) s = token_string (LA1); MATCH (); - len = strlen (s) + 10; + ptrdiff_t slen = strlen (s); + len = slen + 10; if (len > id_size) { size_t new_size = max (len, 2 * id_size); id = (char *) xrealloc (id, new_size); id_size = new_size; } - strcpy (id, s); + char *z = stpcpy (id, s); /* Vector new or delete? */ if (LOOKING_AT ('[')) { - strcat (id, "["); + z = stpcpy (z, "["); MATCH (); if (LOOKING_AT (']')) { - strcat (id, "]"); + strcpy (z, "]"); MATCH (); } } @@ -2830,7 +2831,7 @@ operator_name (int *sc) id = (char *) xrealloc (id, new_size); id_size = new_size; } - strcpy (id, "operator"); + char *z = stpcpy (id, "operator"); /* Beware access declarations of the form "X::f;" Beware of `operator () ()'. Yet another difficulty is found in @@ -2842,14 +2843,16 @@ operator_name (int *sc) len += strlen (s) + 2; if (len > id_size) { + ptrdiff_t idlen = z - id; size_t new_size = max (len, 2 * id_size); id = (char *) xrealloc (id, new_size); id_size = new_size; + z = id + idlen; } if (*s != ')' && *s != ']') - strcat (id, " "); - strcat (id, s); + *z++ = ' '; + z = stpcpy (z, s); MATCH (); /* If this is a simple operator like `+', stop now. */ @@ -3462,9 +3465,9 @@ open_file (char *file) buffer = (char *) xrealloc (buffer, buffer_size); } - strcpy (buffer, path->path); - strcat (buffer, "/"); - strcat (buffer, file); + char *z = stpcpy (buffer, path->path); + *z++ = '/'; + strcpy (z, file); fp = fopen (buffer, "r"); } diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index ddc1b6d..cfc321a 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c @@ -905,9 +905,9 @@ get_server_config (const char *config_file, struct sockaddr_in *server, { char *path = xmalloc (strlen (home) + strlen (config_file) + EXTRA_SPACE); - strcpy (path, home); - strcat (path, "/.emacs.d/server/"); - strcat (path, config_file); + char *z = stpcpy (path, home); + z = stpcpy (z, "/.emacs.d/server/"); + strcpy (z, config_file); config = fopen (path, "rb"); free (path); } @@ -916,9 +916,9 @@ get_server_config (const char *config_file, struct sockaddr_in *server, { char *path = xmalloc (strlen (home) + strlen (config_file) + EXTRA_SPACE); - strcpy (path, home); - strcat (path, "/.emacs.d/server/"); - strcat (path, config_file); + char *z = stpcpy (path, home); + z = stpcpy (z, "/.emacs.d/server/"); + strcpy (z, config_file); config = fopen (path, "rb"); free (path); } @@ -1193,7 +1193,6 @@ set_local_socket (const char *local_socket_name) { /* socket_name is a file name component. */ long uid = geteuid (); - ptrdiff_t tmpdirlen; use_tmpdir = 1; tmpdir = egetenv ("TMPDIR"); if (!tmpdir) @@ -1212,12 +1211,11 @@ set_local_socket (const char *local_socket_name) #endif tmpdir = "/tmp"; } - tmpdirlen = strlen (tmpdir); socket_name_storage = - xmalloc (tmpdirlen + strlen (server_name) + EXTRA_SPACE); - strcpy (socket_name_storage, tmpdir); - sprintf (socket_name_storage + tmpdirlen, "/emacs%ld/", uid); - strcat (socket_name_storage + tmpdirlen, server_name); + xmalloc (strlen (tmpdir) + strlen (server_name) + EXTRA_SPACE); + char *z = stpcpy (socket_name_storage, tmpdir); + z += sprintf (z, "/emacs%ld/", uid); + strcpy (z, server_name); local_socket_name = socket_name_storage; } @@ -1253,12 +1251,12 @@ set_local_socket (const char *local_socket_name) { /* We're running under su, apparently. */ long uid = pw->pw_uid; - ptrdiff_t tmpdirlen = strlen (tmpdir); char *user_socket_name - = xmalloc (tmpdirlen + strlen (server_name) + EXTRA_SPACE); - strcpy (user_socket_name, tmpdir); - sprintf (user_socket_name + tmpdirlen, "/emacs%ld/", uid); - strcat (user_socket_name + tmpdirlen, server_name); + = xmalloc (strlen (tmpdir) + strlen (server_name) + + EXTRA_SPACE); + char *z = stpcpy (user_socket_name, tmpdir); + z += sprintf (z, "/emacs%ld/", uid); + strcpy (z, server_name); if (strlen (user_socket_name) < sizeof (server.sun_path)) strcpy (server.sun_path, user_socket_name); @@ -1507,8 +1505,7 @@ start_daemon_and_retry_set_socket (void) const char *deq = "--daemon="; char *daemon_arg = xmalloc (strlen (deq) + strlen (socket_name) + 1); - strcpy (daemon_arg, deq); - strcat (daemon_arg, socket_name); + strcpy (stpcpy (daemon_arg, deq), socket_name); d_argv[1] = daemon_arg; } execvp ("emacs", d_argv); diff --git a/lib-src/etags.c b/lib-src/etags.c index 6639ac4..78b3fed 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c @@ -1277,13 +1277,13 @@ main (int argc, char **argv) default: continue; /* the for loop */ } - strcpy (cmd, "mv "); - strcat (cmd, tagfile); - strcat (cmd, " OTAGS;fgrep -v '\t"); - strcat (cmd, argbuffer[i].what); - strcat (cmd, "\t' OTAGS >"); - strcat (cmd, tagfile); - strcat (cmd, ";rm OTAGS"); + char *z = stpcpy (cmd, "mv "); + z = stpcpy (z, tagfile); + z = stpcpy (z, " OTAGS;fgrep -v '\t"); + z = stpcpy (z, argbuffer[i].what); + z = stpcpy (z, "\t' OTAGS >"); + z = stpcpy (z, tagfile); + strcpy (z, ";rm OTAGS"); if (system (cmd) != EXIT_SUCCESS) fatal ("failed to execute shell command", (char *)NULL); } @@ -1307,10 +1307,10 @@ main (int argc, char **argv) /* Maybe these should be used: setenv ("LC_COLLATE", "C", 1); setenv ("LC_ALL", "C", 1); */ - strcpy (cmd, "sort -u -o "); - strcat (cmd, tagfile); - strcat (cmd, " "); - strcat (cmd, tagfile); + char *z = stpcpy (cmd, "sort -u -o "); + z = stpcpy (z, tagfile); + *z++ = ' '; + strcpy (z, tagfile); exit (system (cmd)); } return EXIT_SUCCESS; @@ -3427,8 +3427,9 @@ C_entries (int c_ext, FILE *inf) case omethodtag: case omethodparm: objdef = omethodcolon; - linebuffer_setlen (&token_name, token_name.len + 1); - strcat (token_name.buffer, ":"); + int toklen = token_name.len; + linebuffer_setlen (&token_name, toklen + 1); + strcpy (token_name.buffer + toklen, ":"); break; } if (structdef == stagseen) @@ -6362,12 +6363,12 @@ relative_filename (char *file, char *dir) while ((dp = strchr (dp + 1, '/')) != NULL) i += 1; res = xnew (3*i + strlen (fp + 1) + 1, char); - res[0] = '\0'; + char *z = res; while (i-- > 0) - strcat (res, "../"); + z = stpcpy (z, "../"); /* Add the file name relative to the common root of file and dir. */ - strcat (res, fp + 1); + strcpy (z, fp + 1); free (afn); return res; diff --git a/lib-src/pop.c b/lib-src/pop.c index ffe16c5..7001150 100644 --- a/lib-src/pop.c +++ b/lib-src/pop.c @@ -1397,8 +1397,7 @@ sendline (popserver server, const char *line) over a few dozen messages, and is a big chunk of the time we spend fetching mail from a server close by. */ buf = alloca (strlen (line) + 3); - strcpy (buf, line); - strcat (buf, "\r\n"); + strcpy (stpcpy (buf, line), "\r\n"); ret = fullwrite (server->file, buf, strlen (buf)); if (ret < 0) diff --git a/lib-src/update-game-score.c b/lib-src/update-game-score.c index 7a64cd0..b311001 100644 --- a/lib-src/update-game-score.c +++ b/lib-src/update-game-score.c @@ -221,9 +221,9 @@ main (int argc, char **argv) if (!scorefile) lose_syserr ("Couldn't allocate score file"); - strcpy (scorefile, prefix); - strcat (scorefile, "/"); - strcat (scorefile, argv[optind]); + char *z = stpcpy (scorefile, prefix); + *z++ = '/'; + strcpy (z, argv[optind]); newscore.score = normalize_integer (argv[optind + 1]); if (! newscore.score) @@ -430,8 +430,7 @@ write_scores (const char *filename, const struct score_entry *scores, char *tempfile = malloc (strlen (filename) + strlen (".tempXXXXXX") + 1); if (!tempfile) return -1; - strcpy (tempfile, filename); - strcat (tempfile, ".tempXXXXXX"); + strcpy (stpcpy (tempfile, filename), ".tempXXXXXX"); fd = mkostemp (tempfile, 0); if (fd < 0) return -1; @@ -462,8 +461,7 @@ lock_file (const char *filename, void **state) char *lockpath = malloc (strlen (filename) + strlen (lockext) + 60); if (!lockpath) return -1; - strcpy (lockpath, filename); - strcat (lockpath, lockext); + strcpy (stpcpy (lockpath, filename), lockext); *state = lockpath; while ((fd = open (lockpath, O_CREAT | O_EXCL, 0600)) < 0) diff --git a/lib/gnulib.mk b/lib/gnulib.mk index 740ebb1..27a5964 100644 --- a/lib/gnulib.mk +++ b/lib/gnulib.mk @@ -21,7 +21,7 @@ # the same distribution terms as the rest of that program. # # Generated by gnulib-tool. -# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=stdarg --avoid=stdbool --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat sig2str socklen stat-time stdalign stddef stdio strftime strtoimax strtoumax symlink sys_stat sys_time time time_r timer-time timespec-add timespec-sub unsetenv update-copyright utimens vla warnings +# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=stdarg --avoid=stdbool --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat sig2str socklen stat-time stdalign stddef stdio stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r timer-time timespec-add timespec-sub unsetenv update-copyright utimens vla warnings MOSTLYCLEANFILES += core *.stackdump @@ -1214,6 +1214,15 @@ EXTRA_DIST += stdlib.in.h ## end gnulib module stdlib +## begin gnulib module stpcpy + + +EXTRA_DIST += stpcpy.c + +EXTRA_libgnu_a_SOURCES += stpcpy.c + +## end gnulib module stpcpy + ## begin gnulib module strftime libgnu_a_SOURCES += strftime.c diff --git a/lib/stpcpy.c b/lib/stpcpy.c new file mode 100644 index 0000000..880a706 --- /dev/null +++ b/lib/stpcpy.c @@ -0,0 +1,49 @@ +/* stpcpy.c -- copy a string and return pointer to end of new string + Copyright (C) 1992, 1995, 1997-1998, 2006, 2009-2014 Free Software + Foundation, Inc. + + NOTE: The canonical source of this file is maintained with the GNU C Library. + Bugs can be reported to address@hidden + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3 of the License, or any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see