emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] trunk r113467: Fix some minor file descriptor leaks and re


From: Paul Eggert
Subject: [Emacs-diffs] trunk r113467: Fix some minor file descriptor leaks and related glitches.
Date: Fri, 19 Jul 2013 18:09:26 +0000
User-agent: Bazaar (2.6b2)

------------------------------------------------------------
revno: 113467
revision-id: address@hidden
parent: address@hidden
author: Paul Eggert  <address@hidden>
committer: Paul Eggert <address@hidden>
branch nick: trunk
timestamp: Fri 2013-07-19 11:09:23 -0700
message:
  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.
modified:
  src/ChangeLog                  changelog-20091113204419-o5vbwnq5f7feedwu-1438
  src/filelock.c                 filelock.c-20091113204419-o5vbwnq5f7feedwu-179
  src/image.c                    image.c-20091113204419-o5vbwnq5f7feedwu-2969
  src/process.c                  process.c-20091113204419-o5vbwnq5f7feedwu-462
  src/xfaces.c                   xfaces.c-20091113204419-o5vbwnq5f7feedwu-560
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2013-07-19 17:54:26 +0000
+++ b/src/ChangeLog     2013-07-19 18:09:23 +0000
@@ -1,5 +1,18 @@
 2013-07-19  Paul Eggert  <address@hidden>
 
+       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.
+
        * alloc.c (staticpro): Avoid buffer overrun on repeated calls.
        (NSTATICS): Now a constant; doesn't need to be a macro.
 

=== modified file 'src/filelock.c'
--- a/src/filelock.c    2013-07-18 10:24:26 +0000
+++ b/src/filelock.c    2013-07-19 18:09:23 +0000
@@ -430,12 +430,14 @@
       else
        {
          ptrdiff_t lock_info_len;
-#if ! HAVE_MKOSTEMP
+#if ! (HAVE_MKOSTEMP && O_CLOEXEC)
          fcntl (fd, F_SETFD, FD_CLOEXEC);
 #endif
          lock_info_len = strlen (lock_info_str);
          err = 0;
-         if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len
+         /* Use 'write', not 'emacs_write', as garbage collection
+            might signal an error, which would leak FD.  */
+         if (write (fd, lock_info_str, lock_info_len) != lock_info_len
              || fchmod (fd, S_IRUSR | S_IRGRP | S_IROTH) != 0)
            err = errno;
          /* There is no need to call fsync here, as the contents of

=== modified file 'src/image.c'
--- a/src/image.c       2013-07-16 06:39:49 +0000
+++ b/src/image.c       2013-07-19 18:09:23 +0000
@@ -2276,23 +2276,28 @@
   unsigned char *buf = NULL;
   struct stat st;
 
-  if (fp && fstat (fileno (fp), &st) == 0
-      && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
-      && (buf = xmalloc (st.st_size),
-         fread (buf, 1, st.st_size, fp) == st.st_size))
-    {
-      *size = st.st_size;
-      fclose (fp);
-    }
-  else
-    {
-      if (fp)
-       fclose (fp);
-      if (buf)
+  if (fp)
+    {
+      ptrdiff_t count = SPECPDL_INDEX ();
+      record_unwind_protect_ptr (fclose_unwind, fp);
+
+      if (fstat (fileno (fp), &st) == 0
+         && 0 <= st.st_size && st.st_size < min (PTRDIFF_MAX, SIZE_MAX))
        {
-         xfree (buf);
-         buf = NULL;
+         /* Report an error if we read past the purported EOF.
+            This can happen if the file grows as we read it.  */
+         ptrdiff_t buflen = st.st_size;
+         buf = xmalloc (buflen + 1);
+         if (fread (buf, 1, buflen + 1, fp) == buflen)
+           *size = buflen;
+         else
+           {
+             xfree (buf);
+             buf = NULL;
+           }
        }
+
+      unbind_to (count, Qnil);
     }
 
   return buf;
@@ -5732,8 +5737,8 @@
       if (fread (sig, 1, sizeof sig, fp) != sizeof sig
          || fn_png_sig_cmp (sig, 0, sizeof sig))
        {
+         fclose (fp);
          image_error ("Not a PNG file: `%s'", file, Qnil);
-         fclose (fp);
          return 0;
        }
     }

=== modified file 'src/process.c'
--- a/src/process.c     2013-07-17 04:37:27 +0000
+++ b/src/process.c     2013-07-19 18:09:23 +0000
@@ -3526,10 +3526,13 @@
   ptrdiff_t buf_size = 512;
   int s;
   Lisp_Object res;
+  ptrdiff_t count;
 
   s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
   if (s < 0)
     return Qnil;
+  count = SPECPDL_INDEX ();
+  record_unwind_protect_int (close_file_unwind, s);
 
   do
     {
@@ -3545,9 +3548,7 @@
     }
   while (ifconf.ifc_len == buf_size);
 
-  emacs_close (s);
-
-  res = Qnil;
+  res = unbind_to (count, Qnil);
   ifreq = ifconf.ifc_req;
   while ((char *) ifreq < (char *) ifconf.ifc_req + ifconf.ifc_len)
     {
@@ -3672,6 +3673,7 @@
   Lisp_Object elt;
   int s;
   bool any = 0;
+  ptrdiff_t count;
 #if (! (defined SIOCGIFHWADDR && defined HAVE_STRUCT_IFREQ_IFR_HWADDR) \
      && defined HAVE_GETIFADDRS && defined LLADDR)
   struct ifaddrs *ifap;
@@ -3686,6 +3688,8 @@
   s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
   if (s < 0)
     return Qnil;
+  count = SPECPDL_INDEX ();
+  record_unwind_protect_int (close_file_unwind, s);
 
   elt = Qnil;
 #if defined (SIOCGIFFLAGS) && defined (HAVE_STRUCT_IFREQ_IFR_FLAGS)
@@ -3802,9 +3806,7 @@
 #endif
   res = Fcons (elt, res);
 
-  emacs_close (s);
-
-  return any ? res : Qnil;
+  return unbind_to (count, any ? res : Qnil);
 }
 #endif
 #endif /* defined (HAVE_NET_IF_H) */
@@ -3978,6 +3980,7 @@
 #endif
   } saddr;
   socklen_t len = sizeof saddr;
+  ptrdiff_t count;
 
   s = accept4 (channel, &saddr.sa, &len, SOCK_CLOEXEC);
 
@@ -4000,6 +4003,9 @@
       return;
     }
 
+  count = SPECPDL_INDEX ();
+  record_unwind_protect_int (close_file_unwind, s);
+
   connect_counter++;
 
   /* Setup a new process to handle the connection.  */
@@ -4116,6 +4122,10 @@
   pset_filter (p, ps->filter);
   pset_command (p, Qnil);
   p->pid = 0;
+
+  /* Discard the unwind protect for closing S.  */
+  specpdl_ptr = specpdl + count;
+
   p->infd  = s;
   p->outfd = s;
   pset_status (p, Qrun);

=== modified file 'src/xfaces.c'
--- a/src/xfaces.c      2013-07-16 06:39:49 +0000
+++ b/src/xfaces.c      2013-07-19 18:09:23 +0000
@@ -6283,6 +6283,7 @@
   CHECK_STRING (filename);
   abspath = Fexpand_file_name (filename, Qnil);
 
+  block_input ();
   fp = emacs_fopen (SSDATA (abspath), "rt");
   if (fp)
     {
@@ -6290,29 +6291,24 @@
       int red, green, blue;
       int num;
 
-      block_input ();
-
       while (fgets (buf, sizeof (buf), fp) != NULL) {
        if (sscanf (buf, "%u %u %u %n", &red, &green, &blue, &num) == 3)
          {
+#ifdef HAVE_NTGUI
+           int color = RGB (red, green, blue);
+#else
+           int color = (red << 16) | (green << 8) | blue;
+#endif
            char *name = buf + num;
-           num = strlen (name) - 1;
-           if (num >= 0 && name[num] == '\n')
-             name[num] = 0;
-           cmap = Fcons (Fcons (build_string (name),
-#ifdef HAVE_NTGUI
-                                make_number (RGB (red, green, blue))),
-#else
-                                make_number ((red << 16) | (green << 8) | 
blue)),
-#endif
+           ptrdiff_t len = strlen (name);
+           len -= 0 < len && name[len - 1] == '\n';
+           cmap = Fcons (Fcons (make_string (name, len), make_number (color)),
                          cmap);
          }
       }
       fclose (fp);
-
-      unblock_input ();
     }
-
+  unblock_input ();
   return cmap;
 }
 #endif


reply via email to

[Prev in Thread] Current Thread [Next in Thread]