aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2011-08-28 16:52:34 -0700
committerPaul Eggert2011-08-28 16:52:34 -0700
commit17107bb698f82bb5b9c8a732cd6b3faaad4d7af6 (patch)
tree5a0e1fb90617fbe9eb24ae763caed03c45daf948
parent5fc295a42feaef453b57010b826e589b9b9cb7dd (diff)
downloademacs-17107bb698f82bb5b9c8a732cd6b3faaad4d7af6.tar.gz
emacs-17107bb698f82bb5b9c8a732cd6b3faaad4d7af6.zip
Integer and memory overflow issues.
* emacsclient.c (xmalloc): Accept size_t, not unsigned int, to avoid potential buffer overflow issues on typical 64-bit hosts. Return void *, not long *. (get_current_dir_name): Report a failure, instead of looping forever, if buffer size calculation overflows. Treat malloc failures like realloc failures, as that has better behavior and is more consistent. Do not check whether xmalloc returns NULL, as that's not possible. (message): Do not arbitrarily truncate message to 2048 bytes when sending it to stderr; use vfprintf instead. (get_server_config, set_local_socket) (start_daemon_and_retry_set_socket): Do not alloca arbitrarily-large buffers; that's not safe. (get_server_config, set_local_socket): Do not use sprintf when its result might not fit in 'int'. (set_local_socket): Do not assume uid fits in 'int'.
-rw-r--r--lib-src/ChangeLog21
-rw-r--r--lib-src/emacsclient.c95
2 files changed, 79 insertions, 37 deletions
diff --git a/lib-src/ChangeLog b/lib-src/ChangeLog
index c878d313b70..d056b1a4b81 100644
--- a/lib-src/ChangeLog
+++ b/lib-src/ChangeLog
@@ -1,3 +1,24 @@
12011-08-28 Paul Eggert <eggert@cs.ucla.edu>
2
3 Integer and memory overflow issues.
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
12011-07-28 Paul Eggert <eggert@cs.ucla.edu> 222011-07-28 Paul Eggert <eggert@cs.ucla.edu>
2 23
3 Assume freestanding C89 headers, string.h, stdlib.h. 24 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;