aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2019-06-25 14:53:39 -0700
committerPaul Eggert2019-06-25 14:55:08 -0700
commitd7c6836288c91bb639956cb8c748dd6597c55cd4 (patch)
tree687f6f257d3cb5f4bd54eb634aef2737eb9c0856
parent349b778dde7f583a92dd1531aef3ff5c336e9aee (diff)
downloademacs-d7c6836288c91bb639956cb8c748dd6597c55cd4.tar.gz
emacs-d7c6836288c91bb639956cb8c748dd6597c55cd4.zip
Avoid some strlen work, primarily via strnlen
* admin/merge-gnulib (GNULIB_MODULES): Add strnlen. * lib-src/etags.c (find_entries): * src/emacs.c (main): * src/nsmenu.m (parseKeyEquiv:): * src/nsterm.m (ns_xlfd_to_fontname): * src/term.c (vfatal): Prefer !*X to !strlen (X). * lib-src/etags.c (pfnote, add_regex): * lib-src/pop.c (pop_open): * lib-src/update-game-score.c (main): * lwlib/lwlib.c (lw_separator_p): * src/doprnt.c (doprnt): * src/emacs.c (main): * src/inotify.c (inotifyevent_to_event): * src/keyboard.c (menu_separator_name_p, parse_tool_bar_item): * src/sysdep.c (get_current_dir_name_or_unreachable): * src/xdisp.c (store_mode_line_string): Use strnlen to avoid unnecessary work with strlen. * lib-src/etags.c (Prolog_functions, prolog_pr) (Erlang_functions, erlang_func): Prefer ptrdiff_t to size_t when either will do. (prolog_pr, erlang_func): New arg LASTLEN, to avoid unnecessary strlen call. All callers changed. * lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate. * lib/strnlen.c, m4/strnlen.m4: New files, copied from Gnulib. * lwlib/lwlib.c (lw_separator_p): * src/json.c (json_has_prefix): Use strncmp to avoid unecessary work with strlen + memcmp. * src/process.c (set_socket_option): Use SBYTES instead of strlen.
-rwxr-xr-xadmin/merge-gnulib2
-rw-r--r--lib-src/etags.c155
-rw-r--r--lib-src/pop.c4
-rw-r--r--lib-src/update-game-score.c2
-rw-r--r--lib/gnulib.mk.in14
-rw-r--r--lib/strnlen.c30
-rw-r--r--lwlib/lwlib.c5
-rw-r--r--m4/gnulib-comp.m49
-rw-r--r--m4/strnlen.m430
-rw-r--r--src/doprnt.c4
-rw-r--r--src/emacs.c4
-rw-r--r--src/inotify.c3
-rw-r--r--src/json.c4
-rw-r--r--src/keyboard.c15
-rw-r--r--src/nsmenu.m2
-rw-r--r--src/nsterm.m2
-rw-r--r--src/process.c6
-rw-r--r--src/sysdep.c4
-rw-r--r--src/term.c2
-rw-r--r--src/xdisp.c4
20 files changed, 174 insertions, 127 deletions
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index 78e74882f3d..6cf29589f71 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -40,7 +40,7 @@ GNULIB_MODULES='
40 manywarnings memmem-simple memrchr minmax mkostemp mktime nstrftime 40 manywarnings memmem-simple memrchr minmax mkostemp mktime nstrftime
41 pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat regex 41 pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat regex
42 sig2str socklen stat-time std-gnu11 stdalign stddef stdio 42 sig2str socklen stat-time std-gnu11 stdalign stddef stdio
43 stpcpy strtoimax symlink sys_stat sys_time 43 stpcpy strnlen strtoimax symlink sys_stat sys_time
44 tempname time time_r time_rz timegm timer-time timespec-add timespec-sub 44 tempname time time_r time_rz timegm timer-time timespec-add timespec-sub
45 update-copyright unlocked-io utimens 45 update-copyright unlocked-io utimens
46 vla warnings 46 vla warnings
diff --git a/lib-src/etags.c b/lib-src/etags.c
index 442b622cceb..036c485d0bb 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -1811,7 +1811,7 @@ find_entries (FILE *inf)
1811 } 1811 }
1812 *cp = '\0'; 1812 *cp = '\0';
1813 1813
1814 if (strlen (lp) > 0) 1814 if (*lp)
1815 { 1815 {
1816 lang = get_language_from_interpreter (lp); 1816 lang = get_language_from_interpreter (lp);
1817 if (lang != NULL && lang->function != NULL) 1817 if (lang != NULL && lang->function != NULL)
@@ -2012,7 +2012,7 @@ pfnote (char *name, bool is_func, char *linestart, int linelen, int lno,
2012 np->left = np->right = NULL; 2012 np->left = np->right = NULL;
2013 if (CTAGS && !cxref_style) 2013 if (CTAGS && !cxref_style)
2014 { 2014 {
2015 if (strlen (linestart) < 50) 2015 if (strnlen (linestart, 50) < 50)
2016 np->regex = concat (linestart, "$", ""); 2016 np->regex = concat (linestart, "$", "");
2017 else 2017 else
2018 np->regex = savenstr (linestart, 50); 2018 np->regex = savenstr (linestart, 50);
@@ -5883,20 +5883,15 @@ HTML_labels (FILE *inf)
5883 * Original code by Sunichirou Sugou (1989) 5883 * Original code by Sunichirou Sugou (1989)
5884 * Rewritten by Anders Lindgren (1996) 5884 * Rewritten by Anders Lindgren (1996)
5885 */ 5885 */
5886static size_t prolog_pr (char *, char *); 5886static ptrdiff_t prolog_pr (char *, char *, ptrdiff_t);
5887static void prolog_skip_comment (linebuffer *, FILE *); 5887static void prolog_skip_comment (linebuffer *, FILE *);
5888static size_t prolog_atom (char *, size_t); 5888static size_t prolog_atom (char *, size_t);
5889 5889
5890static void 5890static void
5891Prolog_functions (FILE *inf) 5891Prolog_functions (FILE *inf)
5892{ 5892{
5893 char *cp, *last; 5893 char *cp, *last = NULL;
5894 size_t len; 5894 ptrdiff_t lastlen = 0, allocated = 0;
5895 size_t allocated;
5896
5897 allocated = 0;
5898 len = 0;
5899 last = NULL;
5900 5895
5901 LOOP_ON_INPUT_LINES (inf, lb, cp) 5896 LOOP_ON_INPUT_LINES (inf, lb, cp)
5902 { 5897 {
@@ -5906,17 +5901,22 @@ Prolog_functions (FILE *inf)
5906 continue; 5901 continue;
5907 else if (cp[0] == '/' && cp[1] == '*') /* comment. */ 5902 else if (cp[0] == '/' && cp[1] == '*') /* comment. */
5908 prolog_skip_comment (&lb, inf); 5903 prolog_skip_comment (&lb, inf);
5909 else if ((len = prolog_pr (cp, last)) > 0) 5904 else
5910 { 5905 {
5911 /* Predicate or rule. Store the function name so that we 5906 ptrdiff_t len = prolog_pr (cp, last, lastlen);
5912 only generate a tag for the first clause. */ 5907 if (0 < len)
5913 if (last == NULL) 5908 {
5914 last = xnew (len + 1, char); 5909 /* Store the predicate name to avoid generating duplicate
5915 else if (len + 1 > allocated) 5910 tags later. */
5916 xrnew (last, len + 1, char); 5911 if (allocated <= len)
5917 allocated = len + 1; 5912 {
5918 memcpy (last, cp, len); 5913 xrnew (last, len + 1, char);
5919 last[len] = '\0'; 5914 allocated = len + 1;
5915 }
5916 memcpy (last, cp, len);
5917 last[len] = '\0';
5918 lastlen = len;
5919 }
5920 } 5920 }
5921 } 5921 }
5922 free (last); 5922 free (last);
@@ -5949,33 +5949,25 @@ prolog_skip_comment (linebuffer *plb, FILE *inf)
5949 * Return the size of the name of the predicate or rule, or 0 if no 5949 * Return the size of the name of the predicate or rule, or 0 if no
5950 * header was found. 5950 * header was found.
5951 */ 5951 */
5952static size_t 5952static ptrdiff_t
5953prolog_pr (char *s, char *last) 5953prolog_pr (char *s, char *last, ptrdiff_t lastlen)
5954
5955 /* Name of last clause. */
5956{ 5954{
5957 size_t pos; 5955 ptrdiff_t len = prolog_atom (s, 0);
5958 size_t len; 5956 if (len == 0)
5959
5960 pos = prolog_atom (s, 0);
5961 if (! pos)
5962 return 0; 5957 return 0;
5958 ptrdiff_t pos = skip_spaces (s + len) - s;
5963 5959
5964 len = pos; 5960 /* Save only the first clause. */
5965 pos = skip_spaces (s + pos) - s;
5966
5967 if ((s[pos] == '.' 5961 if ((s[pos] == '.'
5968 || (s[pos] == '(' && (pos += 1)) 5962 || (s[pos] == '(' && (pos += 1))
5969 || (s[pos] == ':' && s[pos + 1] == '-' && (pos += 2))) 5963 || (s[pos] == ':' && s[pos + 1] == '-' && (pos += 2)))
5970 && (last == NULL /* save only the first clause */ 5964 && ! (lastlen == len && memcmp (s, last, len) == 0))
5971 || len != strlen (last) 5965 {
5972 || !strneq (s, last, len))) 5966 make_tag (s, len, true, s, pos, lineno, linecharno);
5973 { 5967 return len;
5974 make_tag (s, len, true, s, pos, lineno, linecharno); 5968 }
5975 return len; 5969
5976 } 5970 return 0;
5977 else
5978 return 0;
5979} 5971}
5980 5972
5981/* 5973/*
@@ -6043,21 +6035,15 @@ prolog_atom (char *s, size_t pos)
6043 * Assumes that Erlang functions start at column 0. 6035 * Assumes that Erlang functions start at column 0.
6044 * Original code by Anders Lindgren (1996) 6036 * Original code by Anders Lindgren (1996)
6045 */ 6037 */
6046static int erlang_func (char *, char *, int *); 6038static int erlang_func (char *, char *, ptrdiff_t, ptrdiff_t *);
6047static void erlang_attribute (char *); 6039static void erlang_attribute (char *);
6048static int erlang_atom (char *); 6040static int erlang_atom (char *);
6049 6041
6050static void 6042static void
6051Erlang_functions (FILE *inf) 6043Erlang_functions (FILE *inf)
6052{ 6044{
6053 char *cp, *last; 6045 char *cp, *last = NULL;
6054 int len; 6046 ptrdiff_t lastlen = 0, allocated = 0;
6055 int allocated;
6056 int name_offset = 0;
6057
6058 allocated = 0;
6059 len = 0;
6060 last = NULL;
6061 6047
6062 LOOP_ON_INPUT_LINES (inf, lb, cp) 6048 LOOP_ON_INPUT_LINES (inf, lb, cp)
6063 { 6049 {
@@ -6078,19 +6064,23 @@ Erlang_functions (FILE *inf)
6078 last = NULL; 6064 last = NULL;
6079 } 6065 }
6080 } 6066 }
6081 else if ((len = erlang_func (cp, last, &name_offset)) > 0) 6067 else
6082 { 6068 {
6083 /* 6069 ptrdiff_t name_offset;
6084 * Function. Store the function name so that we only 6070 ptrdiff_t len = erlang_func (cp, last, lastlen, &name_offset);
6085 * generates a tag for the first clause. 6071 if (0 < len)
6086 */ 6072 {
6087 if (last == NULL) 6073 /* Store the function name to avoid generating duplicate
6088 last = xnew (len + 1, char); 6074 tags later. */
6089 else if (len + 1 > allocated) 6075 if (allocated <= len)
6090 xrnew (last, len + 1, char); 6076 {
6091 allocated = len + 1; 6077 xrnew (last, len + 1, char);
6092 memcpy (last, cp + name_offset, len); 6078 allocated = len + 1;
6093 last[len] = '\0'; 6079 }
6080 memcpy (last, cp + name_offset, len);
6081 last[len] = '\0';
6082 lastlen = len;
6083 }
6094 } 6084 }
6095 } 6085 }
6096 free (last); 6086 free (last);
@@ -6108,40 +6098,27 @@ Erlang_functions (FILE *inf)
6108 * was found. 6098 * was found.
6109 */ 6099 */
6110static int 6100static int
6111erlang_func (char *s, char *last, int *name_offset) 6101erlang_func (char *s, char *last, ptrdiff_t lastlen, ptrdiff_t *name_offset)
6112
6113 /* Name of last clause. */
6114{ 6102{
6115 int pos;
6116 int len;
6117 char *name = s; 6103 char *name = s;
6118 6104 ptrdiff_t len = erlang_atom (s);
6119 pos = erlang_atom (s); 6105 if (len == 0)
6120 if (pos < 1)
6121 return 0; 6106 return 0;
6122 6107 ptrdiff_t pos = skip_spaces (s + len) - s;
6123 len = pos;
6124 pos = skip_spaces (s + pos) - s;
6125 6108
6126 /* If the name is quoted, the quotes are not part of the name. */ 6109 /* If the name is quoted, the quotes are not part of the name. */
6127 if (len > 2 && name[0] == '\'' && name[len - 1] == '\'') 6110 bool quoted = 2 < len && name[0] == '\'' && name[len - 1] == '\'';
6128 { 6111 name += quoted;
6129 *name_offset = 1; 6112 len -= 2 * quoted;
6130 name++;
6131 len -= 2;
6132 }
6133 else
6134 *name_offset = 0;
6135 6113
6136 /* Save only the first clause. */ 6114 /* Save only the first clause. */
6137 if (s[pos++] == '(' 6115 if (s[pos++] == '('
6138 && (last == NULL 6116 && ! (lastlen == len && memcmp (name, last, len) == 0))
6139 || len != (int)strlen (last) 6117 {
6140 || !strneq (name, last, len))) 6118 make_tag (s, len, true, s, pos, lineno, linecharno);
6141 { 6119 *name_offset = quoted;
6142 make_tag (name, len, true, s, pos, lineno, linecharno); 6120 return len;
6143 return len; 6121 }
6144 }
6145 6122
6146 return 0; 6123 return 0;
6147} 6124}
@@ -6363,7 +6340,7 @@ add_regex (char *regexp_pattern, language *lang)
6363 single_line = false; /* dot does not match newline */ 6340 single_line = false; /* dot does not match newline */
6364 6341
6365 6342
6366 if (strlen (regexp_pattern) < 3) 6343 if (strnlen (regexp_pattern, 3) < 3)
6367 { 6344 {
6368 error ("null regexp"); 6345 error ("null regexp");
6369 return; 6346 return;
diff --git a/lib-src/pop.c b/lib-src/pop.c
index c14808d6d37..e4bd6c04965 100644
--- a/lib-src/pop.c
+++ b/lib-src/pop.c
@@ -285,7 +285,7 @@ pop_open (char *host, char *username, char *password, int flags)
285 /* 285 /*
286 * I really shouldn't use the pop_error variable like this, but.... 286 * I really shouldn't use the pop_error variable like this, but....
287 */ 287 */
288 if (strlen (username) > ERROR_MAX - 6) 288 if (strnlen (username, ERROR_MAX - 6 + 1) == ERROR_MAX - 6 + 1)
289 { 289 {
290 pop_close (server); 290 pop_close (server);
291 strcpy (pop_error, 291 strcpy (pop_error,
@@ -299,7 +299,7 @@ pop_open (char *host, char *username, char *password, int flags)
299 return (0); 299 return (0);
300 } 300 }
301 301
302 if (strlen (password) > ERROR_MAX - 6) 302 if (strnlen (password, ERROR_MAX - 6 + 1) == ERROR_MAX - 6 + 1)
303 { 303 {
304 pop_close (server); 304 pop_close (server);
305 strcpy (pop_error, 305 strcpy (pop_error,
diff --git a/lib-src/update-game-score.c b/lib-src/update-game-score.c
index 8a6f46b38e7..782425186e8 100644
--- a/lib-src/update-game-score.c
+++ b/lib-src/update-game-score.c
@@ -240,7 +240,7 @@ main (int argc, char **argv)
240 if (! user) 240 if (! user)
241 lose_syserr ("Couldn't determine user id"); 241 lose_syserr ("Couldn't determine user id");
242 data = argv[optind + 2]; 242 data = argv[optind + 2];
243 if (strlen (data) > MAX_DATA_LEN) 243 if (strnlen (data, MAX_DATA_LEN + 1) == MAX_DATA_LEN + 1)
244 data[MAX_DATA_LEN] = '\0'; 244 data[MAX_DATA_LEN] = '\0';
245 nl = strchr (data, '\n'); 245 nl = strchr (data, '\n');
246 if (nl) 246 if (nl)
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index b9a32d9dbc1..b4d510bd62e 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -136,6 +136,7 @@
136# stddef \ 136# stddef \
137# stdio \ 137# stdio \
138# stpcpy \ 138# stpcpy \
139# strnlen \
139# strtoimax \ 140# strtoimax \
140# symlink \ 141# symlink \
141# sys_stat \ 142# sys_stat \
@@ -1075,7 +1076,6 @@ gl_GNULIB_ENABLED_getdtablesize = @gl_GNULIB_ENABLED_getdtablesize@
1075gl_GNULIB_ENABLED_getgroups = @gl_GNULIB_ENABLED_getgroups@ 1076gl_GNULIB_ENABLED_getgroups = @gl_GNULIB_ENABLED_getgroups@
1076gl_GNULIB_ENABLED_malloca = @gl_GNULIB_ENABLED_malloca@ 1077gl_GNULIB_ENABLED_malloca = @gl_GNULIB_ENABLED_malloca@
1077gl_GNULIB_ENABLED_open = @gl_GNULIB_ENABLED_open@ 1078gl_GNULIB_ENABLED_open = @gl_GNULIB_ENABLED_open@
1078gl_GNULIB_ENABLED_pathmax = @gl_GNULIB_ENABLED_pathmax@
1079gl_GNULIB_ENABLED_strtoll = @gl_GNULIB_ENABLED_strtoll@ 1079gl_GNULIB_ENABLED_strtoll = @gl_GNULIB_ENABLED_strtoll@
1080gl_LIBOBJS = @gl_LIBOBJS@ 1080gl_LIBOBJS = @gl_LIBOBJS@
1081gl_LTLIBOBJS = @gl_LTLIBOBJS@ 1081gl_LTLIBOBJS = @gl_LTLIBOBJS@
@@ -1110,7 +1110,6 @@ pdfdir = @pdfdir@
1110prefix = @prefix@ 1110prefix = @prefix@
1111program_transform_name = @program_transform_name@ 1111program_transform_name = @program_transform_name@
1112psdir = @psdir@ 1112psdir = @psdir@
1113runstatedir = @runstatedir@
1114sbindir = @sbindir@ 1113sbindir = @sbindir@
1115sharedstatedir = @sharedstatedir@ 1114sharedstatedir = @sharedstatedir@
1116srcdir = @srcdir@ 1115srcdir = @srcdir@
@@ -2811,6 +2810,17 @@ EXTRA_DIST += string.in.h
2811endif 2810endif
2812## end gnulib module string 2811## end gnulib module string
2813 2812
2813## begin gnulib module strnlen
2814ifeq (,$(OMIT_GNULIB_MODULE_strnlen))
2815
2816
2817EXTRA_DIST += strnlen.c
2818
2819EXTRA_libgnu_a_SOURCES += strnlen.c
2820
2821endif
2822## end gnulib module strnlen
2823
2814## begin gnulib module strtoimax 2824## begin gnulib module strtoimax
2815ifeq (,$(OMIT_GNULIB_MODULE_strtoimax)) 2825ifeq (,$(OMIT_GNULIB_MODULE_strtoimax))
2816 2826
diff --git a/lib/strnlen.c b/lib/strnlen.c
new file mode 100644
index 00000000000..9fb663509a0
--- /dev/null
+++ b/lib/strnlen.c
@@ -0,0 +1,30 @@
1/* Find the length of STRING, but scan at most MAXLEN characters.
2 Copyright (C) 2005-2007, 2009-2019 Free Software Foundation, Inc.
3 Written by Simon Josefsson.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <https://www.gnu.org/licenses/>. */
17
18#include <config.h>
19
20#include <string.h>
21
22/* Find the length of STRING, but scan at most MAXLEN characters.
23 If no '\0' terminator is found in that many characters, return MAXLEN. */
24
25size_t
26strnlen (const char *string, size_t maxlen)
27{
28 const char *end = memchr (string, '\0', maxlen);
29 return end ? (size_t) (end - string) : maxlen;
30}
diff --git a/lwlib/lwlib.c b/lwlib/lwlib.c
index 8142d92f077..f37c1058792 100644
--- a/lwlib/lwlib.c
+++ b/lwlib/lwlib.c
@@ -1233,8 +1233,7 @@ lw_separator_p (const char *label, enum menu_separator *type, int motif_p)
1233{ 1233{
1234 int separator_p = 0; 1234 int separator_p = 0;
1235 1235
1236 if (strlen (label) >= 3 1236 if (strncmp (label, "--:", 3) == 0)
1237 && memcmp (label, "--:", 3) == 0)
1238 { 1237 {
1239 static struct separator_table 1238 static struct separator_table
1240 { 1239 {
@@ -1276,7 +1275,7 @@ lw_separator_p (const char *label, enum menu_separator *type, int motif_p)
1276 break; 1275 break;
1277 } 1276 }
1278 } 1277 }
1279 else if (strlen (label) > 3 1278 else if (strnlen (label, 4) == 4
1280 && memcmp (label, "--", 2) == 0 1279 && memcmp (label, "--", 2) == 0
1281 && label[2] != '-') 1280 && label[2] != '-')
1282 { 1281 {
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index cb6dce15ccf..7e724fe3c4e 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -154,6 +154,7 @@ AC_DEFUN([gl_EARLY],
154 # Code from module stdlib: 154 # Code from module stdlib:
155 # Code from module stpcpy: 155 # Code from module stpcpy:
156 # Code from module string: 156 # Code from module string:
157 # Code from module strnlen:
157 # Code from module strtoimax: 158 # Code from module strtoimax:
158 # Code from module strtoll: 159 # Code from module strtoll:
159 # Code from module symlink: 160 # Code from module symlink:
@@ -403,6 +404,12 @@ AC_DEFUN([gl_INIT],
403 fi 404 fi
404 gl_STRING_MODULE_INDICATOR([stpcpy]) 405 gl_STRING_MODULE_INDICATOR([stpcpy])
405 gl_HEADER_STRING_H 406 gl_HEADER_STRING_H
407 gl_FUNC_STRNLEN
408 if test $HAVE_DECL_STRNLEN = 0 || test $REPLACE_STRNLEN = 1; then
409 AC_LIBOBJ([strnlen])
410 gl_PREREQ_STRNLEN
411 fi
412 gl_STRING_MODULE_INDICATOR([strnlen])
406 gl_FUNC_STRTOIMAX 413 gl_FUNC_STRTOIMAX
407 if test $HAVE_DECL_STRTOIMAX = 0 || test $REPLACE_STRTOIMAX = 1; then 414 if test $HAVE_DECL_STRTOIMAX = 0 || test $REPLACE_STRTOIMAX = 1; then
408 AC_LIBOBJ([strtoimax]) 415 AC_LIBOBJ([strtoimax])
@@ -1003,6 +1010,7 @@ AC_DEFUN([gl_FILE_LIST], [
1003 lib/str-two-way.h 1010 lib/str-two-way.h
1004 lib/strftime.h 1011 lib/strftime.h
1005 lib/string.in.h 1012 lib/string.in.h
1013 lib/strnlen.c
1006 lib/strtoimax.c 1014 lib/strtoimax.c
1007 lib/strtol.c 1015 lib/strtol.c
1008 lib/strtoll.c 1016 lib/strtoll.c
@@ -1131,6 +1139,7 @@ AC_DEFUN([gl_FILE_LIST], [
1131 m4/stdlib_h.m4 1139 m4/stdlib_h.m4
1132 m4/stpcpy.m4 1140 m4/stpcpy.m4
1133 m4/string_h.m4 1141 m4/string_h.m4
1142 m4/strnlen.m4
1134 m4/strtoimax.m4 1143 m4/strtoimax.m4
1135 m4/strtoll.m4 1144 m4/strtoll.m4
1136 m4/symlink.m4 1145 m4/symlink.m4
diff --git a/m4/strnlen.m4 b/m4/strnlen.m4
new file mode 100644
index 00000000000..c283c3ece9f
--- /dev/null
+++ b/m4/strnlen.m4
@@ -0,0 +1,30 @@
1# strnlen.m4 serial 13
2dnl Copyright (C) 2002-2003, 2005-2007, 2009-2019 Free Software Foundation,
3dnl Inc.
4dnl This file is free software; the Free Software Foundation
5dnl gives unlimited permission to copy and/or distribute it,
6dnl with or without modifications, as long as this notice is preserved.
7
8AC_DEFUN([gl_FUNC_STRNLEN],
9[
10 AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS])
11
12 dnl Persuade glibc <string.h> to declare strnlen().
13 AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
14
15 AC_CHECK_DECLS_ONCE([strnlen])
16 if test $ac_cv_have_decl_strnlen = no; then
17 HAVE_DECL_STRNLEN=0
18 else
19 m4_pushdef([AC_LIBOBJ], [:])
20 dnl Note: AC_FUNC_STRNLEN does AC_LIBOBJ([strnlen]).
21 AC_FUNC_STRNLEN
22 m4_popdef([AC_LIBOBJ])
23 if test $ac_cv_func_strnlen_working = no; then
24 REPLACE_STRNLEN=1
25 fi
26 fi
27])
28
29# Prerequisites of lib/strnlen.c.
30AC_DEFUN([gl_PREREQ_STRNLEN], [:])
diff --git a/src/doprnt.c b/src/doprnt.c
index 5fb70634048..64bb368ee3e 100644
--- a/src/doprnt.c
+++ b/src/doprnt.c
@@ -357,8 +357,8 @@ doprnt (char *buffer, ptrdiff_t bufsize, const char *format,
357 if (fmtcpy[1] != 's') 357 if (fmtcpy[1] != 's')
358 minlen = atoi (&fmtcpy[1]); 358 minlen = atoi (&fmtcpy[1]);
359 string = va_arg (ap, char *); 359 string = va_arg (ap, char *);
360 tem = strlen (string); 360 tem = strnlen (string, STRING_BYTES_BOUND + 1);
361 if (STRING_BYTES_BOUND < tem) 361 if (tem == STRING_BYTES_BOUND + 1)
362 error ("String for %%s or %%S format is too long"); 362 error ("String for %%s or %%S format is too long");
363 width = strwidth (string, tem); 363 width = strwidth (string, tem);
364 goto doit1; 364 goto doit1;
diff --git a/src/emacs.c b/src/emacs.c
index 1ddd10b8051..231acc0ef32 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1520,8 +1520,8 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1520 } 1520 }
1521 1521
1522 /* In exec'd: parse special dname into pipe and name info. */ 1522 /* In exec'd: parse special dname into pipe and name info. */
1523 if (!dname_arg || !strchr (dname_arg, '\n') 1523 if (!dname_arg || !*dname_arg || strnlen (dname_arg, 71) == 71
1524 || strlen (dname_arg) < 1 || strlen (dname_arg) > 70) 1524 || !strchr (dname_arg, '\n'))
1525 { 1525 {
1526 fprintf (stderr, "emacs daemon: daemon name absent or too long\n"); 1526 fprintf (stderr, "emacs daemon: daemon name absent or too long\n");
1527 exit (EXIT_CANNOT_INVOKE); 1527 exit (EXIT_CANNOT_INVOKE);
diff --git a/src/inotify.c b/src/inotify.c
index 9a7dbb8f413..e8891aefc7a 100644
--- a/src/inotify.c
+++ b/src/inotify.c
@@ -181,8 +181,7 @@ inotifyevent_to_event (Lisp_Object watch, struct inotify_event const *ev)
181 181
182 if (ev->len > 0) 182 if (ev->len > 0)
183 { 183 {
184 size_t const len = strlen (ev->name); 184 name = make_unibyte_string (ev->name, strnlen (ev->name, ev->len));
185 name = make_unibyte_string (ev->name, min (len, ev->len));
186 name = DECODE_FILE (name); 185 name = DECODE_FILE (name);
187 } 186 }
188 else 187 else
diff --git a/src/json.c b/src/json.c
index e2a4424463b..23234c767d8 100644
--- a/src/json.c
+++ b/src/json.c
@@ -197,9 +197,7 @@ init_json (void)
197static bool 197static bool
198json_has_prefix (const char *string, const char *prefix) 198json_has_prefix (const char *string, const char *prefix)
199{ 199{
200 size_t string_len = strlen (string); 200 return strncmp (string, prefix, strlen (prefix)) == 0;
201 size_t prefix_len = strlen (prefix);
202 return string_len >= prefix_len && memcmp (string, prefix, prefix_len) == 0;
203} 201}
204 202
205/* Return whether STRING ends with SUFFIX. */ 203/* Return whether STRING ends with SUFFIX. */
diff --git a/src/keyboard.c b/src/keyboard.c
index 0d7f124f5f3..56916e0cb4e 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -7331,7 +7331,7 @@ menu_separator_name_p (const char *label)
7331{ 7331{
7332 if (!label) 7332 if (!label)
7333 return 0; 7333 return 0;
7334 else if (strlen (label) > 3 7334 else if (strnlen (label, 4) == 4
7335 && memcmp (label, "--", 2) == 0 7335 && memcmp (label, "--", 2) == 0
7336 && label[2] != '-') 7336 && label[2] != '-')
7337 { 7337 {
@@ -8248,13 +8248,13 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item)
8248 Lisp_Object tcapt = PROP (TOOL_BAR_ITEM_CAPTION); 8248 Lisp_Object tcapt = PROP (TOOL_BAR_ITEM_CAPTION);
8249 const char *label = SYMBOLP (tkey) ? SSDATA (SYMBOL_NAME (tkey)) : ""; 8249 const char *label = SYMBOLP (tkey) ? SSDATA (SYMBOL_NAME (tkey)) : "";
8250 const char *capt = STRINGP (tcapt) ? SSDATA (tcapt) : ""; 8250 const char *capt = STRINGP (tcapt) ? SSDATA (tcapt) : "";
8251 ptrdiff_t max_lbl = 8251 ptrdiff_t max_lbl_size =
8252 2 * max (0, min (tool_bar_max_label_size, STRING_BYTES_BOUND / 2)); 8252 2 * max (0, min (tool_bar_max_label_size, STRING_BYTES_BOUND / 2)) + 1;
8253 char *buf = xmalloc (max_lbl + 1); 8253 char *buf = xmalloc (max_lbl_size);
8254 Lisp_Object new_lbl; 8254 Lisp_Object new_lbl;
8255 ptrdiff_t caption_len = strlen (capt); 8255 ptrdiff_t caption_len = strnlen (capt, max_lbl_size);
8256 8256
8257 if (caption_len <= max_lbl && capt[0] != '\0') 8257 if (0 < caption_len && caption_len < max_lbl_size)
8258 { 8258 {
8259 strcpy (buf, capt); 8259 strcpy (buf, capt);
8260 while (caption_len > 0 && buf[caption_len - 1] == '.') 8260 while (caption_len > 0 && buf[caption_len - 1] == '.')
@@ -8263,7 +8263,8 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item)
8263 label = capt = buf; 8263 label = capt = buf;
8264 } 8264 }
8265 8265
8266 if (strlen (label) <= max_lbl && label[0] != '\0') 8266 ptrdiff_t label_len = strnlen (label, max_lbl_size);
8267 if (0 < label_len && label_len < max_lbl_size)
8267 { 8268 {
8268 ptrdiff_t j; 8269 ptrdiff_t j;
8269 if (label != buf) 8270 if (label != buf)
diff --git a/src/nsmenu.m b/src/nsmenu.m
index 3fe06cda02a..817f8cff184 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -611,7 +611,7 @@ ns_activate_menubar (struct frame *f)
611 const char *tpos = key; 611 const char *tpos = key;
612 keyEquivModMask = NSEventModifierFlagCommand; 612 keyEquivModMask = NSEventModifierFlagCommand;
613 613
614 if (!key || !strlen (key)) 614 if (!key || !*key)
615 return @""; 615 return @"";
616 616
617 while (*tpos == ' ' || *tpos == '(') 617 while (*tpos == ' ' || *tpos == '(')
diff --git a/src/nsterm.m b/src/nsterm.m
index 0ab03b46df1..8d46a49cc5e 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -9298,7 +9298,7 @@ ns_xlfd_to_fontname (const char *xlfd)
9298 sscanf (xlfd, "-%*[^-]-%179[^-]-", name); 9298 sscanf (xlfd, "-%*[^-]-%179[^-]-", name);
9299 9299
9300 /* stopgap for malformed XLFD input */ 9300 /* stopgap for malformed XLFD input */
9301 if (strlen (name) == 0) 9301 if (!*name)
9302 strcpy (name, "Monaco"); 9302 strcpy (name, "Monaco");
9303 9303
9304 /* undo hack in ns_fontname_to_xlfd, converting '$' to '-', '_' to ' ' 9304 /* undo hack in ns_fontname_to_xlfd, converting '$' to '-', '_' to ' '
diff --git a/src/process.c b/src/process.c
index 6717ccb4187..15d87cf6015 100644
--- a/src/process.c
+++ b/src/process.c
@@ -2857,11 +2857,7 @@ set_socket_option (int s, Lisp_Object opt, Lisp_Object val)
2857 This should work on all systems. KFS. 2003-09-23. */ 2857 This should work on all systems. KFS. 2003-09-23. */
2858 memset (devname, 0, sizeof devname); 2858 memset (devname, 0, sizeof devname);
2859 if (STRINGP (val)) 2859 if (STRINGP (val))
2860 { 2860 memcpy (devname, SDATA (val), min (SBYTES (val), IFNAMSIZ));
2861 char *arg = SSDATA (val);
2862 int len = min (strlen (arg), IFNAMSIZ);
2863 memcpy (devname, arg, len);
2864 }
2865 else if (!NILP (val)) 2861 else if (!NILP (val))
2866 error ("Bad option value for %s", name); 2862 error ("Bad option value for %s", name);
2867 ret = setsockopt (s, sopt->optlevel, sopt->optnum, 2863 ret = setsockopt (s, sopt->optlevel, sopt->optnum,
diff --git a/src/sysdep.c b/src/sysdep.c
index 0910b69f8bc..b702bae5818 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -281,7 +281,7 @@ get_current_dir_name_or_unreachable (void)
281 pwd = get_current_dir_name (); 281 pwd = get_current_dir_name ();
282 if (pwd) 282 if (pwd)
283 { 283 {
284 if (strlen (pwd) < dirsize_max) 284 if (strnlen (pwd, dirsize_max) < dirsize_max)
285 return pwd; 285 return pwd;
286 free (pwd); 286 free (pwd);
287 errno = ERANGE; 287 errno = ERANGE;
@@ -298,7 +298,7 @@ get_current_dir_name_or_unreachable (void)
298 sometimes a nicer name, and using it may avoid a fatal error if a 298 sometimes a nicer name, and using it may avoid a fatal error if a
299 parent directory is searchable but not readable. */ 299 parent directory is searchable but not readable. */
300 if (pwd 300 if (pwd
301 && (pwdlen = strlen (pwd)) < bufsize_max 301 && (pwdlen = strnlen (pwd, bufsize_max)) < bufsize_max
302 && IS_DIRECTORY_SEP (pwd[pwdlen && IS_DEVICE_SEP (pwd[1]) ? 2 : 0]) 302 && IS_DIRECTORY_SEP (pwd[pwdlen && IS_DEVICE_SEP (pwd[1]) ? 2 : 0])
303 && stat (pwd, &pwdstat) == 0 303 && stat (pwd, &pwdstat) == 0
304 && stat (".", &dotstat) == 0 304 && stat (".", &dotstat) == 0
diff --git a/src/term.c b/src/term.c
index ce06e1cd4e5..8b5a710d80a 100644
--- a/src/term.c
+++ b/src/term.c
@@ -4400,7 +4400,7 @@ vfatal (const char *str, va_list ap)
4400{ 4400{
4401 fprintf (stderr, "emacs: "); 4401 fprintf (stderr, "emacs: ");
4402 vfprintf (stderr, str, ap); 4402 vfprintf (stderr, str, ap);
4403 if (!(strlen (str) > 0 && str[strlen (str) - 1] == '\n')) 4403 if (! (str[0] && str[strlen (str) - 1] == '\n'))
4404 fprintf (stderr, "\n"); 4404 fprintf (stderr, "\n");
4405 exit (1); 4405 exit (1);
4406} 4406}
diff --git a/src/xdisp.c b/src/xdisp.c
index 25e8932945e..9f63ef4b180 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -24341,9 +24341,7 @@ store_mode_line_string (const char *string, Lisp_Object lisp_string,
24341 24341
24342 if (string != NULL) 24342 if (string != NULL)
24343 { 24343 {
24344 len = strlen (string); 24344 len = strnlen (string, precision <= 0 ? SIZE_MAX : precision);
24345 if (precision > 0 && len > precision)
24346 len = precision;
24347 lisp_string = make_string (string, len); 24345 lisp_string = make_string (string, len);
24348 if (NILP (props)) 24346 if (NILP (props))
24349 props = mode_line_string_face_prop; 24347 props = mode_line_string_face_prop;