aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2013-07-19 11:09:23 -0700
committerPaul Eggert2013-07-19 11:09:23 -0700
commit3f5bef16fab0ba83cb2298f8137fec831af1aec4 (patch)
tree8f825fe5834080db213452ee3bb1b291f1923a6d /src
parent4195afc389bb0e5ed5aa749e7606a710e07a72d1 (diff)
downloademacs-3f5bef16fab0ba83cb2298f8137fec831af1aec4.tar.gz
emacs-3f5bef16fab0ba83cb2298f8137fec831af1aec4.zip
Fix some minor file descriptor leaks and related glitches.
* filelock.c (create_lock_file) [!O_CLOEXEC]: Use fcntl with FD_CLOEXEC. (create_lock_file): Use write, not emacs_write. * image.c (slurp_file, png_load_body): * process.c (Fnetwork_interface_list, Fnetwork_interface_info) (server_accept_connection): Don't leak an fd on memory allocation failure. * image.c (slurp_file): Add a cheap heuristic for growing files. * xfaces.c (Fx_load_color_file): Block input around the fopen too, as that's what the other routines do. Maybe input need not be blocked at all, but it's better to be consistent. Avoid undefined behavior when strlen is zero.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog13
-rw-r--r--src/filelock.c6
-rw-r--r--src/image.c35
-rw-r--r--src/process.c22
-rw-r--r--src/xfaces.c20
5 files changed, 61 insertions, 35 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 73e24bcf829..a63e441dcb2 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,18 @@
12013-07-19 Paul Eggert <eggert@cs.ucla.edu> 12013-07-19 Paul Eggert <eggert@cs.ucla.edu>
2 2
3 Fix some minor file descriptor leaks and related glitches.
4 * filelock.c (create_lock_file) [!O_CLOEXEC]: Use fcntl with FD_CLOEXEC.
5 (create_lock_file): Use write, not emacs_write.
6 * image.c (slurp_file, png_load_body):
7 * process.c (Fnetwork_interface_list, Fnetwork_interface_info)
8 (server_accept_connection):
9 Don't leak an fd on memory allocation failure.
10 * image.c (slurp_file): Add a cheap heuristic for growing files.
11 * xfaces.c (Fx_load_color_file): Block input around the fopen too,
12 as that's what the other routines do. Maybe input need not be
13 blocked at all, but it's better to be consistent.
14 Avoid undefined behavior when strlen is zero.
15
3 * alloc.c (staticpro): Avoid buffer overrun on repeated calls. 16 * alloc.c (staticpro): Avoid buffer overrun on repeated calls.
4 (NSTATICS): Now a constant; doesn't need to be a macro. 17 (NSTATICS): Now a constant; doesn't need to be a macro.
5 18
diff --git a/src/filelock.c b/src/filelock.c
index fefd14b3a92..b9c991e4baf 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -430,12 +430,14 @@ create_lock_file (char *lfname, char *lock_info_str, bool force)
430 else 430 else
431 { 431 {
432 ptrdiff_t lock_info_len; 432 ptrdiff_t lock_info_len;
433#if ! HAVE_MKOSTEMP 433#if ! (HAVE_MKOSTEMP && O_CLOEXEC)
434 fcntl (fd, F_SETFD, FD_CLOEXEC); 434 fcntl (fd, F_SETFD, FD_CLOEXEC);
435#endif 435#endif
436 lock_info_len = strlen (lock_info_str); 436 lock_info_len = strlen (lock_info_str);
437 err = 0; 437 err = 0;
438 if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len 438 /* Use 'write', not 'emacs_write', as garbage collection
439 might signal an error, which would leak FD. */
440 if (write (fd, lock_info_str, lock_info_len) != lock_info_len
439 || fchmod (fd, S_IRUSR | S_IRGRP | S_IROTH) != 0) 441 || fchmod (fd, S_IRUSR | S_IRGRP | S_IROTH) != 0)
440 err = errno; 442 err = errno;
441 /* There is no need to call fsync here, as the contents of 443 /* There is no need to call fsync here, as the contents of
diff --git a/src/image.c b/src/image.c
index 95d385dc9e2..1e3944ac1a1 100644
--- a/src/image.c
+++ b/src/image.c
@@ -2276,23 +2276,28 @@ slurp_file (char *file, ptrdiff_t *size)
2276 unsigned char *buf = NULL; 2276 unsigned char *buf = NULL;
2277 struct stat st; 2277 struct stat st;
2278 2278
2279 if (fp && fstat (fileno (fp), &st) == 0 2279 if (fp)
2280 && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
2281 && (buf = xmalloc (st.st_size),
2282 fread (buf, 1, st.st_size, fp) == st.st_size))
2283 {
2284 *size = st.st_size;
2285 fclose (fp);
2286 }
2287 else
2288 { 2280 {
2289 if (fp) 2281 ptrdiff_t count = SPECPDL_INDEX ();
2290 fclose (fp); 2282 record_unwind_protect_ptr (fclose_unwind, fp);
2291 if (buf) 2283
2284 if (fstat (fileno (fp), &st) == 0
2285 && 0 <= st.st_size && st.st_size < min (PTRDIFF_MAX, SIZE_MAX))
2292 { 2286 {
2293 xfree (buf); 2287 /* Report an error if we read past the purported EOF.
2294 buf = NULL; 2288 This can happen if the file grows as we read it. */
2289 ptrdiff_t buflen = st.st_size;
2290 buf = xmalloc (buflen + 1);
2291 if (fread (buf, 1, buflen + 1, fp) == buflen)
2292 *size = buflen;
2293 else
2294 {
2295 xfree (buf);
2296 buf = NULL;
2297 }
2295 } 2298 }
2299
2300 unbind_to (count, Qnil);
2296 } 2301 }
2297 2302
2298 return buf; 2303 return buf;
@@ -5732,8 +5737,8 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5732 if (fread (sig, 1, sizeof sig, fp) != sizeof sig 5737 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
5733 || fn_png_sig_cmp (sig, 0, sizeof sig)) 5738 || fn_png_sig_cmp (sig, 0, sizeof sig))
5734 { 5739 {
5735 image_error ("Not a PNG file: `%s'", file, Qnil);
5736 fclose (fp); 5740 fclose (fp);
5741 image_error ("Not a PNG file: `%s'", file, Qnil);
5737 return 0; 5742 return 0;
5738 } 5743 }
5739 } 5744 }
diff --git a/src/process.c b/src/process.c
index 7c63964aee6..f4ae662468b 100644
--- a/src/process.c
+++ b/src/process.c
@@ -3526,10 +3526,13 @@ format; see the description of ADDRESS in `make-network-process'. */)
3526 ptrdiff_t buf_size = 512; 3526 ptrdiff_t buf_size = 512;
3527 int s; 3527 int s;
3528 Lisp_Object res; 3528 Lisp_Object res;
3529 ptrdiff_t count;
3529 3530
3530 s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); 3531 s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
3531 if (s < 0) 3532 if (s < 0)
3532 return Qnil; 3533 return Qnil;
3534 count = SPECPDL_INDEX ();
3535 record_unwind_protect_int (close_file_unwind, s);
3533 3536
3534 do 3537 do
3535 { 3538 {
@@ -3545,9 +3548,7 @@ format; see the description of ADDRESS in `make-network-process'. */)
3545 } 3548 }
3546 while (ifconf.ifc_len == buf_size); 3549 while (ifconf.ifc_len == buf_size);
3547 3550
3548 emacs_close (s); 3551 res = unbind_to (count, Qnil);
3549
3550 res = Qnil;
3551 ifreq = ifconf.ifc_req; 3552 ifreq = ifconf.ifc_req;
3552 while ((char *) ifreq < (char *) ifconf.ifc_req + ifconf.ifc_len) 3553 while ((char *) ifreq < (char *) ifconf.ifc_req + ifconf.ifc_len)
3553 { 3554 {
@@ -3672,6 +3673,7 @@ FLAGS is the current flags of the interface. */)
3672 Lisp_Object elt; 3673 Lisp_Object elt;
3673 int s; 3674 int s;
3674 bool any = 0; 3675 bool any = 0;
3676 ptrdiff_t count;
3675#if (! (defined SIOCGIFHWADDR && defined HAVE_STRUCT_IFREQ_IFR_HWADDR) \ 3677#if (! (defined SIOCGIFHWADDR && defined HAVE_STRUCT_IFREQ_IFR_HWADDR) \
3676 && defined HAVE_GETIFADDRS && defined LLADDR) 3678 && defined HAVE_GETIFADDRS && defined LLADDR)
3677 struct ifaddrs *ifap; 3679 struct ifaddrs *ifap;
@@ -3686,6 +3688,8 @@ FLAGS is the current flags of the interface. */)
3686 s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); 3688 s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
3687 if (s < 0) 3689 if (s < 0)
3688 return Qnil; 3690 return Qnil;
3691 count = SPECPDL_INDEX ();
3692 record_unwind_protect_int (close_file_unwind, s);
3689 3693
3690 elt = Qnil; 3694 elt = Qnil;
3691#if defined (SIOCGIFFLAGS) && defined (HAVE_STRUCT_IFREQ_IFR_FLAGS) 3695#if defined (SIOCGIFFLAGS) && defined (HAVE_STRUCT_IFREQ_IFR_FLAGS)
@@ -3802,9 +3806,7 @@ FLAGS is the current flags of the interface. */)
3802#endif 3806#endif
3803 res = Fcons (elt, res); 3807 res = Fcons (elt, res);
3804 3808
3805 emacs_close (s); 3809 return unbind_to (count, any ? res : Qnil);
3806
3807 return any ? res : Qnil;
3808} 3810}
3809#endif 3811#endif
3810#endif /* defined (HAVE_NET_IF_H) */ 3812#endif /* defined (HAVE_NET_IF_H) */
@@ -3978,6 +3980,7 @@ server_accept_connection (Lisp_Object server, int channel)
3978#endif 3980#endif
3979 } saddr; 3981 } saddr;
3980 socklen_t len = sizeof saddr; 3982 socklen_t len = sizeof saddr;
3983 ptrdiff_t count;
3981 3984
3982 s = accept4 (channel, &saddr.sa, &len, SOCK_CLOEXEC); 3985 s = accept4 (channel, &saddr.sa, &len, SOCK_CLOEXEC);
3983 3986
@@ -4000,6 +4003,9 @@ server_accept_connection (Lisp_Object server, int channel)
4000 return; 4003 return;
4001 } 4004 }
4002 4005
4006 count = SPECPDL_INDEX ();
4007 record_unwind_protect_int (close_file_unwind, s);
4008
4003 connect_counter++; 4009 connect_counter++;
4004 4010
4005 /* Setup a new process to handle the connection. */ 4011 /* Setup a new process to handle the connection. */
@@ -4116,6 +4122,10 @@ server_accept_connection (Lisp_Object server, int channel)
4116 pset_filter (p, ps->filter); 4122 pset_filter (p, ps->filter);
4117 pset_command (p, Qnil); 4123 pset_command (p, Qnil);
4118 p->pid = 0; 4124 p->pid = 0;
4125
4126 /* Discard the unwind protect for closing S. */
4127 specpdl_ptr = specpdl + count;
4128
4119 p->infd = s; 4129 p->infd = s;
4120 p->outfd = s; 4130 p->outfd = s;
4121 pset_status (p, Qrun); 4131 pset_status (p, Qrun);
diff --git a/src/xfaces.c b/src/xfaces.c
index d35851220b0..f647ff2e209 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -6283,6 +6283,7 @@ where R,G,B are numbers between 0 and 255 and name is an arbitrary string. */)
6283 CHECK_STRING (filename); 6283 CHECK_STRING (filename);
6284 abspath = Fexpand_file_name (filename, Qnil); 6284 abspath = Fexpand_file_name (filename, Qnil);
6285 6285
6286 block_input ();
6286 fp = emacs_fopen (SSDATA (abspath), "rt"); 6287 fp = emacs_fopen (SSDATA (abspath), "rt");
6287 if (fp) 6288 if (fp)
6288 { 6289 {
@@ -6290,29 +6291,24 @@ where R,G,B are numbers between 0 and 255 and name is an arbitrary string. */)
6290 int red, green, blue; 6291 int red, green, blue;
6291 int num; 6292 int num;
6292 6293
6293 block_input ();
6294
6295 while (fgets (buf, sizeof (buf), fp) != NULL) { 6294 while (fgets (buf, sizeof (buf), fp) != NULL) {
6296 if (sscanf (buf, "%u %u %u %n", &red, &green, &blue, &num) == 3) 6295 if (sscanf (buf, "%u %u %u %n", &red, &green, &blue, &num) == 3)
6297 { 6296 {
6298 char *name = buf + num;
6299 num = strlen (name) - 1;
6300 if (num >= 0 && name[num] == '\n')
6301 name[num] = 0;
6302 cmap = Fcons (Fcons (build_string (name),
6303#ifdef HAVE_NTGUI 6297#ifdef HAVE_NTGUI
6304 make_number (RGB (red, green, blue))), 6298 int color = RGB (red, green, blue);
6305#else 6299#else
6306 make_number ((red << 16) | (green << 8) | blue)), 6300 int color = (red << 16) | (green << 8) | blue;
6307#endif 6301#endif
6302 char *name = buf + num;
6303 ptrdiff_t len = strlen (name);
6304 len -= 0 < len && name[len - 1] == '\n';
6305 cmap = Fcons (Fcons (make_string (name, len), make_number (color)),
6308 cmap); 6306 cmap);
6309 } 6307 }
6310 } 6308 }
6311 fclose (fp); 6309 fclose (fp);
6312
6313 unblock_input ();
6314 } 6310 }
6315 6311 unblock_input ();
6316 return cmap; 6312 return cmap;
6317} 6313}
6318#endif 6314#endif