aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/ChangeLog35
-rw-r--r--lib-src/emacsclient.c95
-rw-r--r--lib-src/etags.c44
-rw-r--r--lib-src/movemail.c7
-rw-r--r--lib-src/update-game-score.c15
5 files changed, 135 insertions, 61 deletions
diff --git a/lib-src/ChangeLog b/lib-src/ChangeLog
index c878d313b70..9041eae8bbe 100644
--- a/lib-src/ChangeLog
+++ b/lib-src/ChangeLog
@@ -1,3 +1,38 @@
12011-09-04 Paul Eggert <eggert@cs.ucla.edu>
2
3 Integer and memory overflow issues (Bug#9397).
4
5 * emacsclient.c (xmalloc): Accept size_t, not unsigned int, to
6 avoid potential buffer overflow issues on typical 64-bit hosts.
7 Return void *, not long *.
8 (get_current_dir_name): Report a failure, instead of looping
9 forever, if buffer size calculation overflows. Treat malloc
10 failures like realloc failures, as that has better behavior and is
11 more consistent. Do not check whether xmalloc returns NULL, as
12 that's not possible.
13 (message): Do not arbitrarily truncate message to 2048 bytes when
14 sending it to stderr; use vfprintf instead.
15 (get_server_config, set_local_socket)
16 (start_daemon_and_retry_set_socket): Do not alloca
17 arbitrarily-large buffers; that's not safe.
18 (get_server_config, set_local_socket): Do not use sprintf when its
19 result might not fit in 'int'.
20 (set_local_socket): Do not assume uid fits in 'int'.
21
22 * etags.c (xmalloc, xrealloc): Accept size_t, not unsigned int,
23 to avoid potential buffer overflow issues on typical 64-bit hosts.
24 (whatlen_max): New static var.
25 (main): Avoid buffer overflow if subsidiary command length is
26 greater than BUFSIZ or 2*BUFSIZ + 20. Do not use sprintf when its
27 result might not fit in 'int'.
28
29 * movemail.c (main): Do not use sprintf when its result might not fit
30 in 'int'. Instead, put the possibly-long file name into the
31 output of pfatal_with_name.
32
33 * update-game-score.c: Include <limits.h>
34 (get_user_id): Do not assume uid fits in 'int'. Simplify.
35
12011-07-28 Paul Eggert <eggert@cs.ucla.edu> 362011-07-28 Paul Eggert <eggert@cs.ucla.edu>
2 37
3 Assume freestanding C89 headers, string.h, stdlib.h. 38 Assume freestanding C89 headers, string.h, stdlib.h.
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c
index 2af139aee6d..ece9dc65c49 100644
--- a/lib-src/emacsclient.c
+++ b/lib-src/emacsclient.c
@@ -194,10 +194,10 @@ struct option longopts[] =
194 194
195/* Like malloc but get fatal error if memory is exhausted. */ 195/* Like malloc but get fatal error if memory is exhausted. */
196 196
197static long * 197static void *
198xmalloc (unsigned int size) 198xmalloc (size_t size)
199{ 199{
200 long *result = (long *) malloc (size); 200 void *result = malloc (size);
201 if (result == NULL) 201 if (result == NULL)
202 { 202 {
203 perror ("malloc"); 203 perror ("malloc");
@@ -250,32 +250,33 @@ get_current_dir_name (void)
250 ) 250 )
251 { 251 {
252 buf = (char *) xmalloc (strlen (pwd) + 1); 252 buf = (char *) xmalloc (strlen (pwd) + 1);
253 if (!buf)
254 return NULL;
255 strcpy (buf, pwd); 253 strcpy (buf, pwd);
256 } 254 }
257#ifdef HAVE_GETCWD 255#ifdef HAVE_GETCWD
258 else 256 else
259 { 257 {
260 size_t buf_size = 1024; 258 size_t buf_size = 1024;
261 buf = (char *) xmalloc (buf_size);
262 if (!buf)
263 return NULL;
264 for (;;) 259 for (;;)
265 { 260 {
261 int tmp_errno;
262 buf = malloc (buf_size);
263 if (! buf)
264 break;
266 if (getcwd (buf, buf_size) == buf) 265 if (getcwd (buf, buf_size) == buf)
267 break; 266 break;
268 if (errno != ERANGE) 267 tmp_errno = errno;
268 free (buf);
269 if (tmp_errno != ERANGE)
269 { 270 {
270 int tmp_errno = errno;
271 free (buf);
272 errno = tmp_errno; 271 errno = tmp_errno;
273 return NULL; 272 return NULL;
274 } 273 }
275 buf_size *= 2; 274 buf_size *= 2;
276 buf = (char *) realloc (buf, buf_size); 275 if (! buf_size)
277 if (!buf) 276 {
278 return NULL; 277 errno = ENOMEM;
278 return NULL;
279 }
279 } 280 }
280 } 281 }
281#else 282#else
@@ -283,8 +284,6 @@ get_current_dir_name (void)
283 { 284 {
284 /* We need MAXPATHLEN here. */ 285 /* We need MAXPATHLEN here. */
285 buf = (char *) xmalloc (MAXPATHLEN + 1); 286 buf = (char *) xmalloc (MAXPATHLEN + 1);
286 if (!buf)
287 return NULL;
288 if (getwd (buf) == NULL) 287 if (getwd (buf) == NULL)
289 { 288 {
290 int tmp_errno = errno; 289 int tmp_errno = errno;
@@ -494,16 +493,17 @@ static void message (int, const char *, ...) ATTRIBUTE_FORMAT_PRINTF (2, 3);
494static void 493static void
495message (int is_error, const char *format, ...) 494message (int is_error, const char *format, ...)
496{ 495{
497 char msg[2048];
498 va_list args; 496 va_list args;
499 497
500 va_start (args, format); 498 va_start (args, format);
501 vsprintf (msg, format, args);
502 va_end (args);
503 499
504#ifdef WINDOWSNT 500#ifdef WINDOWSNT
505 if (w32_window_app ()) 501 if (w32_window_app ())
506 { 502 {
503 char msg[2048];
504 vsnprintf (msg, sizeof msg, format, args);
505 msg[sizeof msg - 1] = '\0';
506
507 if (is_error) 507 if (is_error)
508 MessageBox (NULL, msg, "Emacsclient ERROR", MB_ICONERROR); 508 MessageBox (NULL, msg, "Emacsclient ERROR", MB_ICONERROR);
509 else 509 else
@@ -514,9 +514,11 @@ message (int is_error, const char *format, ...)
514 { 514 {
515 FILE *f = is_error ? stderr : stdout; 515 FILE *f = is_error ? stderr : stdout;
516 516
517 fputs (msg, f); 517 vfprintf (f, format, args);
518 fflush (f); 518 fflush (f);
519 } 519 }
520
521 va_end (args);
520} 522}
521 523
522/* Decode the options from argv and argc. 524/* Decode the options from argv and argc.
@@ -959,18 +961,24 @@ get_server_config (struct sockaddr_in *server, char *authentication)
959 961
960 if (home) 962 if (home)
961 { 963 {
962 char *path = alloca (strlen (home) + strlen (server_file) 964 char *path = xmalloc (strlen (home) + strlen (server_file)
963 + EXTRA_SPACE); 965 + EXTRA_SPACE);
964 sprintf (path, "%s/.emacs.d/server/%s", home, server_file); 966 strcpy (path, home);
967 strcat (path, "/.emacs.d/server/");
968 strcat (path, server_file);
965 config = fopen (path, "rb"); 969 config = fopen (path, "rb");
970 free (path);
966 } 971 }
967#ifdef WINDOWSNT 972#ifdef WINDOWSNT
968 if (!config && (home = egetenv ("APPDATA"))) 973 if (!config && (home = egetenv ("APPDATA")))
969 { 974 {
970 char *path = alloca (strlen (home) + strlen (server_file) 975 char *path = xmalloc (strlen (home) + strlen (server_file)
971 + EXTRA_SPACE); 976 + EXTRA_SPACE);
972 sprintf (path, "%s/.emacs.d/server/%s", home, server_file); 977 strcpy (path, home);
978 strcat (path, "/.emacs.d/server/");
979 strcat (path, server_file);
973 config = fopen (path, "rb"); 980 config = fopen (path, "rb");
981 free (path);
974 } 982 }
975#endif 983#endif
976 } 984 }
@@ -1243,6 +1251,8 @@ set_local_socket (void)
1243 int saved_errno = 0; 1251 int saved_errno = 0;
1244 const char *server_name = "server"; 1252 const char *server_name = "server";
1245 const char *tmpdir IF_LINT ( = NULL); 1253 const char *tmpdir IF_LINT ( = NULL);
1254 char *tmpdir_storage = NULL;
1255 char *socket_name_storage = NULL;
1246 1256
1247 if (socket_name && !strchr (socket_name, '/') 1257 if (socket_name && !strchr (socket_name, '/')
1248 && !strchr (socket_name, '\\')) 1258 && !strchr (socket_name, '\\'))
@@ -1255,6 +1265,8 @@ set_local_socket (void)
1255 1265
1256 if (default_sock) 1266 if (default_sock)
1257 { 1267 {
1268 long uid = geteuid ();
1269 ptrdiff_t tmpdirlen;
1258 tmpdir = egetenv ("TMPDIR"); 1270 tmpdir = egetenv ("TMPDIR");
1259 if (!tmpdir) 1271 if (!tmpdir)
1260 { 1272 {
@@ -1265,17 +1277,19 @@ set_local_socket (void)
1265 size_t n = confstr (_CS_DARWIN_USER_TEMP_DIR, NULL, (size_t) 0); 1277 size_t n = confstr (_CS_DARWIN_USER_TEMP_DIR, NULL, (size_t) 0);
1266 if (n > 0) 1278 if (n > 0)
1267 { 1279 {
1268 tmpdir = alloca (n); 1280 tmpdir = tmpdir_storage = xmalloc (n);
1269 confstr (_CS_DARWIN_USER_TEMP_DIR, tmpdir, n); 1281 confstr (_CS_DARWIN_USER_TEMP_DIR, tmpdir, n);
1270 } 1282 }
1271 else 1283 else
1272#endif 1284#endif
1273 tmpdir = "/tmp"; 1285 tmpdir = "/tmp";
1274 } 1286 }
1275 socket_name = alloca (strlen (tmpdir) + strlen (server_name) 1287 tmpdirlen = strlen (tmpdir);
1276 + EXTRA_SPACE); 1288 socket_name = socket_name_storage =
1277 sprintf (socket_name, "%s/emacs%d/%s", 1289 xmalloc (tmpdirlen + strlen (server_name) + EXTRA_SPACE);
1278 tmpdir, (int) geteuid (), server_name); 1290 strcpy (socket_name, tmpdir);
1291 sprintf (socket_name + tmpdirlen, "/emacs%ld/", uid);
1292 strcat (socket_name + tmpdirlen, server_name);
1279 } 1293 }
1280 1294
1281 if (strlen (socket_name) < sizeof (server.sun_path)) 1295 if (strlen (socket_name) < sizeof (server.sun_path))
@@ -1309,10 +1323,13 @@ set_local_socket (void)
1309 if (pw && (pw->pw_uid != geteuid ())) 1323 if (pw && (pw->pw_uid != geteuid ()))
1310 { 1324 {
1311 /* We're running under su, apparently. */ 1325 /* We're running under su, apparently. */
1312 socket_name = alloca (strlen (tmpdir) + strlen (server_name) 1326 long uid = pw->pw_uid;
1313 + EXTRA_SPACE); 1327 ptrdiff_t tmpdirlen = strlen (tmpdir);
1314 sprintf (socket_name, "%s/emacs%d/%s", 1328 socket_name = xmalloc (tmpdirlen + strlen (server_name)
1315 tmpdir, (int) pw->pw_uid, server_name); 1329 + EXTRA_SPACE);
1330 strcpy (socket_name, tmpdir);
1331 sprintf (socket_name + tmpdirlen, "/emacs%ld/", uid);
1332 strcat (socket_name + tmpdirlen, server_name);
1316 1333
1317 if (strlen (socket_name) < sizeof (server.sun_path)) 1334 if (strlen (socket_name) < sizeof (server.sun_path))
1318 strcpy (server.sun_path, socket_name); 1335 strcpy (server.sun_path, socket_name);
@@ -1322,6 +1339,7 @@ set_local_socket (void)
1322 progname, socket_name); 1339 progname, socket_name);
1323 exit (EXIT_FAILURE); 1340 exit (EXIT_FAILURE);
1324 } 1341 }
1342 free (socket_name);
1325 1343
1326 sock_status = socket_status (server.sun_path); 1344 sock_status = socket_status (server.sun_path);
1327 saved_errno = errno; 1345 saved_errno = errno;
@@ -1331,6 +1349,9 @@ set_local_socket (void)
1331 } 1349 }
1332 } 1350 }
1333 1351
1352 free (socket_name_storage);
1353 free (tmpdir_storage);
1354
1334 switch (sock_status) 1355 switch (sock_status)
1335 { 1356 {
1336 case 1: 1357 case 1:
@@ -1526,8 +1547,8 @@ start_daemon_and_retry_set_socket (void)
1526 { 1547 {
1527 /* Pass --daemon=socket_name as argument. */ 1548 /* Pass --daemon=socket_name as argument. */
1528 const char *deq = "--daemon="; 1549 const char *deq = "--daemon=";
1529 char *daemon_arg = alloca (strlen (deq) 1550 char *daemon_arg = xmalloc (strlen (deq)
1530 + strlen (socket_name) + 1); 1551 + strlen (socket_name) + 1);
1531 strcpy (daemon_arg, deq); 1552 strcpy (daemon_arg, deq);
1532 strcat (daemon_arg, socket_name); 1553 strcat (daemon_arg, socket_name);
1533 d_argv[1] = daemon_arg; 1554 d_argv[1] = daemon_arg;
diff --git a/lib-src/etags.c b/lib-src/etags.c
index 522c54ee4a5..9d920565804 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -414,8 +414,8 @@ static bool filename_is_absolute (char *f);
414static void canonicalize_filename (char *); 414static void canonicalize_filename (char *);
415static void linebuffer_init (linebuffer *); 415static void linebuffer_init (linebuffer *);
416static void linebuffer_setlen (linebuffer *, int); 416static void linebuffer_setlen (linebuffer *, int);
417static PTR xmalloc (unsigned int); 417static PTR xmalloc (size_t);
418static PTR xrealloc (char *, unsigned int); 418static PTR xrealloc (char *, size_t);
419 419
420 420
421static char searchar = '/'; /* use /.../ searches */ 421static char searchar = '/'; /* use /.../ searches */
@@ -425,6 +425,7 @@ static char *progname; /* name this program was invoked with */
425static char *cwd; /* current working directory */ 425static char *cwd; /* current working directory */
426static char *tagfiledir; /* directory of tagfile */ 426static char *tagfiledir; /* directory of tagfile */
427static FILE *tagf; /* ioptr for tags file */ 427static FILE *tagf; /* ioptr for tags file */
428static ptrdiff_t whatlen_max; /* maximum length of any 'what' member */
428 429
429static fdesc *fdhead; /* head of file description list */ 430static fdesc *fdhead; /* head of file description list */
430static fdesc *curfdp; /* current file description */ 431static fdesc *curfdp; /* current file description */
@@ -1066,6 +1067,7 @@ main (int argc, char **argv)
1066 int current_arg, file_count; 1067 int current_arg, file_count;
1067 linebuffer filename_lb; 1068 linebuffer filename_lb;
1068 bool help_asked = FALSE; 1069 bool help_asked = FALSE;
1070 ptrdiff_t len;
1069 char *optstring; 1071 char *optstring;
1070 int opt; 1072 int opt;
1071 1073
@@ -1110,6 +1112,9 @@ main (int argc, char **argv)
1110 /* This means that a file name has been seen. Record it. */ 1112 /* This means that a file name has been seen. Record it. */
1111 argbuffer[current_arg].arg_type = at_filename; 1113 argbuffer[current_arg].arg_type = at_filename;
1112 argbuffer[current_arg].what = optarg; 1114 argbuffer[current_arg].what = optarg;
1115 len = strlen (optarg);
1116 if (whatlen_max < len)
1117 whatlen_max = len;
1113 ++current_arg; 1118 ++current_arg;
1114 ++file_count; 1119 ++file_count;
1115 break; 1120 break;
@@ -1118,6 +1123,9 @@ main (int argc, char **argv)
1118 /* Parse standard input. Idea by Vivek <vivek@etla.org>. */ 1123 /* Parse standard input. Idea by Vivek <vivek@etla.org>. */
1119 argbuffer[current_arg].arg_type = at_stdin; 1124 argbuffer[current_arg].arg_type = at_stdin;
1120 argbuffer[current_arg].what = optarg; 1125 argbuffer[current_arg].what = optarg;
1126 len = strlen (optarg);
1127 if (whatlen_max < len)
1128 whatlen_max = len;
1121 ++current_arg; 1129 ++current_arg;
1122 ++file_count; 1130 ++file_count;
1123 if (parsing_stdin) 1131 if (parsing_stdin)
@@ -1160,6 +1168,9 @@ main (int argc, char **argv)
1160 case 'r': 1168 case 'r':
1161 argbuffer[current_arg].arg_type = at_regexp; 1169 argbuffer[current_arg].arg_type = at_regexp;
1162 argbuffer[current_arg].what = optarg; 1170 argbuffer[current_arg].what = optarg;
1171 len = strlen (optarg);
1172 if (whatlen_max < len)
1173 whatlen_max = len;
1163 ++current_arg; 1174 ++current_arg;
1164 break; 1175 break;
1165 case 'R': 1176 case 'R':
@@ -1198,6 +1209,9 @@ main (int argc, char **argv)
1198 { 1209 {
1199 argbuffer[current_arg].arg_type = at_filename; 1210 argbuffer[current_arg].arg_type = at_filename;
1200 argbuffer[current_arg].what = argv[optind]; 1211 argbuffer[current_arg].what = argv[optind];
1212 len = strlen (argv[optind]);
1213 if (whatlen_max < len)
1214 whatlen_max = len;
1201 ++current_arg; 1215 ++current_arg;
1202 ++file_count; 1216 ++file_count;
1203 } 1217 }
@@ -1331,7 +1345,9 @@ main (int argc, char **argv)
1331 /* From here on, we are in (CTAGS && !cxref_style) */ 1345 /* From here on, we are in (CTAGS && !cxref_style) */
1332 if (update) 1346 if (update)
1333 { 1347 {
1334 char cmd[BUFSIZ]; 1348 char *cmd =
1349 xmalloc (strlen (tagfile) + whatlen_max +
1350 sizeof "mv..OTAGS;fgrep -v '\t\t' OTAGS >;rm OTAGS");
1335 for (i = 0; i < current_arg; ++i) 1351 for (i = 0; i < current_arg; ++i)
1336 { 1352 {
1337 switch (argbuffer[i].arg_type) 1353 switch (argbuffer[i].arg_type)
@@ -1342,12 +1358,17 @@ main (int argc, char **argv)
1342 default: 1358 default:
1343 continue; /* the for loop */ 1359 continue; /* the for loop */
1344 } 1360 }
1345 sprintf (cmd, 1361 strcpy (cmd, "mv ");
1346 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS", 1362 strcat (cmd, tagfile);
1347 tagfile, argbuffer[i].what, tagfile); 1363 strcat (cmd, " OTAGS;fgrep -v '\t");
1364 strcat (cmd, argbuffer[i].what);
1365 strcat (cmd, "\t' OTAGS >");
1366 strcat (cmd, tagfile);
1367 strcat (cmd, ";rm OTAGS");
1348 if (system (cmd) != EXIT_SUCCESS) 1368 if (system (cmd) != EXIT_SUCCESS)
1349 fatal ("failed to execute shell command", (char *)NULL); 1369 fatal ("failed to execute shell command", (char *)NULL);
1350 } 1370 }
1371 free (cmd);
1351 append_to_tagfile = TRUE; 1372 append_to_tagfile = TRUE;
1352 } 1373 }
1353 1374
@@ -1363,11 +1384,14 @@ main (int argc, char **argv)
1363 if (CTAGS) 1384 if (CTAGS)
1364 if (append_to_tagfile || update) 1385 if (append_to_tagfile || update)
1365 { 1386 {
1366 char cmd[2*BUFSIZ+20]; 1387 char *cmd = xmalloc (2 * strlen (tagfile) + sizeof "sort -u -o..");
1367 /* Maybe these should be used: 1388 /* Maybe these should be used:
1368 setenv ("LC_COLLATE", "C", 1); 1389 setenv ("LC_COLLATE", "C", 1);
1369 setenv ("LC_ALL", "C", 1); */ 1390 setenv ("LC_ALL", "C", 1); */
1370 sprintf (cmd, "sort -u -o %.*s %.*s", BUFSIZ, tagfile, BUFSIZ, tagfile); 1391 strcpy (cmd, "sort -u -o ");
1392 strcat (cmd, tagfile);
1393 strcat (cmd, " ");
1394 strcat (cmd, tagfile);
1371 exit (system (cmd)); 1395 exit (system (cmd));
1372 } 1396 }
1373 return EXIT_SUCCESS; 1397 return EXIT_SUCCESS;
@@ -6656,7 +6680,7 @@ linebuffer_setlen (linebuffer *lbp, int toksize)
6656 6680
6657/* Like malloc but get fatal error if memory is exhausted. */ 6681/* Like malloc but get fatal error if memory is exhausted. */
6658static PTR 6682static PTR
6659xmalloc (unsigned int size) 6683xmalloc (size_t size)
6660{ 6684{
6661 PTR result = (PTR) malloc (size); 6685 PTR result = (PTR) malloc (size);
6662 if (result == NULL) 6686 if (result == NULL)
@@ -6665,7 +6689,7 @@ xmalloc (unsigned int size)
6665} 6689}
6666 6690
6667static PTR 6691static PTR
6668xrealloc (char *ptr, unsigned int size) 6692xrealloc (char *ptr, size_t size)
6669{ 6693{
6670 PTR result = (PTR) realloc (ptr, size); 6694 PTR result = (PTR) realloc (ptr, size);
6671 if (result == NULL) 6695 if (result == NULL)
diff --git a/lib-src/movemail.c b/lib-src/movemail.c
index d70c655adec..097bf23c202 100644
--- a/lib-src/movemail.c
+++ b/lib-src/movemail.c
@@ -325,11 +325,10 @@ main (int argc, char **argv)
325 if (desc < 0) 325 if (desc < 0)
326 { 326 {
327 int mkstemp_errno = errno; 327 int mkstemp_errno = errno;
328 char *message = (char *) xmalloc (strlen (tempname) + 50); 328 error ("error while creating what would become the lock file",
329 sprintf (message, "creating %s, which would become the lock file", 329 0, 0);
330 tempname);
331 errno = mkstemp_errno; 330 errno = mkstemp_errno;
332 pfatal_with_name (message); 331 pfatal_with_name (tempname);
333 } 332 }
334 close (desc); 333 close (desc);
335 334
diff --git a/lib-src/update-game-score.c b/lib-src/update-game-score.c
index 2a89379aefe..9fba51a33de 100644
--- a/lib-src/update-game-score.c
+++ b/lib-src/update-game-score.c
@@ -35,6 +35,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
35 35
36#include <unistd.h> 36#include <unistd.h>
37#include <errno.h> 37#include <errno.h>
38#include <limits.h>
38#include <string.h> 39#include <string.h>
39#include <stdlib.h> 40#include <stdlib.h>
40#include <stdio.h> 41#include <stdio.h>
@@ -128,19 +129,13 @@ lose_syserr (const char *msg)
128static char * 129static char *
129get_user_id (void) 130get_user_id (void)
130{ 131{
131 char *name;
132 struct passwd *buf = getpwuid (getuid ()); 132 struct passwd *buf = getpwuid (getuid ());
133 if (!buf) 133 if (!buf)
134 { 134 {
135 int count = 1; 135 long uid = getuid ();
136 int uid = (int) getuid (); 136 char *name = malloc (sizeof uid * CHAR_BIT / 3 + 1);
137 int tuid = uid; 137 if (name)
138 while (tuid /= 10) 138 sprintf (name, "%ld", uid);
139 count++;
140 name = malloc (count+1);
141 if (!name)
142 return NULL;
143 sprintf (name, "%d", uid);
144 return name; 139 return name;
145 } 140 }
146 return buf->pw_name; 141 return buf->pw_name;