]> git.eshelyaron.com Git - emacs.git/commitdiff
* charset.c: Fix file descriptor leaks and errno issues.
authorPaul Eggert <eggert@cs.ucla.edu>
Thu, 18 Jul 2013 02:12:59 +0000 (19:12 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 18 Jul 2013 02:12:59 +0000 (19:12 -0700)
Include <errno.h>.
(load_charset_map_from_file): Don't leak file descriptor on error.
Use plain record_xmalloc since the allocation is larger than
MAX_ALLOCA; that's simpler here.  Simplify test for exhaustion
of entries.
* eval.c (record_unwind_protect_nothing):
* fileio.c (fclose_unwind):
New functions.
* lread.c (load_unwind): Remove.  All uses replaced by fclose_unwind.
The replacement doesn't block input, but that no longer seems
necessary.

src/ChangeLog
src/charset.c
src/eval.c
src/fileio.c
src/lisp.h
src/lread.c

index 189a353bde6d18797c0f945845efaa93c4c847ce..3f667a7bcc724e0ab8083c5e7fc6d3ba9c8f83cf 100644 (file)
@@ -1,3 +1,18 @@
+2013-07-18  Paul Eggert  <eggert@cs.ucla.edu>
+
+       * charset.c: Fix file descriptor leaks and errno issues.
+       Include <errno.h>.
+       (load_charset_map_from_file): Don't leak file descriptor on error.
+       Use plain record_xmalloc since the allocation is larger than
+       MAX_ALLOCA; that's simpler here.  Simplify test for exhaustion
+       of entries.
+       * eval.c (record_unwind_protect_nothing):
+       * fileio.c (fclose_unwind):
+       New functions.
+       * lread.c (load_unwind): Remove.  All uses replaced by fclose_unwind.
+       The replacement doesn't block input, but that no longer seems
+       necessary.
+
 2013-07-17  Paul Eggert  <eggert@cs.ucla.edu>
 
        * lread.c: Fix file descriptor leaks and errno issues.
index 6b7e81c156d946636ccdf88db596fc4f6d983826..eedf65faa6c40f33cf62da14f76417c20579696f 100644 (file)
@@ -28,6 +28,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #define CHARSET_INLINE EXTERN_INLINE
 
+#include <errno.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <limits.h>
@@ -477,7 +478,8 @@ read_hex (FILE *fp, bool *eof, bool *overflow)
    `file-name-handler-alist' to avoid running any Lisp code.  */
 
 static void
-load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, int control_flag)
+load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile,
+                           int control_flag)
 {
   unsigned min_code = CHARSET_MIN_CODE (charset);
   unsigned max_code = CHARSET_MAX_CODE (charset);
@@ -487,21 +489,26 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, int co
   struct charset_map_entries *head, *entries;
   int n_entries;
   ptrdiff_t count;
-  USE_SAFE_ALLOCA;
 
   suffixes = list2 (build_string (".map"), build_string (".TXT"));
 
   count = SPECPDL_INDEX ();
+  record_unwind_protect_nothing ();
   specbind (Qfile_name_handler_alist, Qnil);
   fd = openp (Vcharset_map_path, mapfile, suffixes, NULL, Qnil);
-  unbind_to (count, Qnil);
-  if (fd < 0
-      || ! (fp = fdopen (fd, "r")))
-    error ("Failure in loading charset map: %s", SDATA (mapfile));
+  fp = fd < 0 ? 0 : fdopen (fd, "r");
+  if (!fp)
+    {
+      int open_errno = errno;
+      emacs_close (fd);
+      report_file_errno ("Loading charset map", mapfile, open_errno);
+    }
+  set_unwind_protect_ptr (count, fclose_unwind, fp);
+  unbind_to (count + 1, Qnil);
 
-  /* Use SAFE_ALLOCA instead of alloca, as `charset_map_entries' is
+  /* Use record_xmalloc, as `charset_map_entries' is
      large (larger than MAX_ALLOCA).  */
-  head = SAFE_ALLOCA (sizeof *head);
+  head = record_xmalloc (sizeof *head);
   entries = head;
   memset (entries, 0, sizeof (struct charset_map_entries));
 
@@ -530,9 +537,9 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, int co
       if (from < min_code || to > max_code || from > to || c > MAX_CHAR)
        continue;
 
-      if (n_entries > 0 && (n_entries % 0x10000) == 0)
+      if (n_entries == 0x10000)
        {
-         entries->next = SAFE_ALLOCA (sizeof *entries->next);
+         entries->next = record_xmalloc (sizeof *entries->next);
          entries = entries->next;
          memset (entries, 0, sizeof (struct charset_map_entries));
          n_entries = 0;
@@ -544,9 +551,10 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, int co
       n_entries++;
     }
   fclose (fp);
+  clear_unwind_protect (count);
 
   load_charset_map (charset, head, n_entries, control_flag);
-  SAFE_FREE ();
+  unbind_to (count, Qnil);
 }
 
 static void
index a4f94ee14157defdb1ce8d1b2be89b67861b2a7e..23834cb54f62883d11c1b8da257feaef1141ca36 100644 (file)
@@ -3190,6 +3190,8 @@ specbind (Lisp_Object symbol, Lisp_Object value)
     }
 }
 
+/* Push unwind-protect entries of various types.  */
+
 void
 record_unwind_protect (void (*function) (Lisp_Object), Lisp_Object arg)
 {
@@ -3229,6 +3231,18 @@ static void
 do_nothing (void)
 {}
 
+/* Push an unwind-protect entry that does nothing, so that
+   set_unwind_protect_ptr can overwrite it later.  */
+
+void
+record_unwind_protect_nothing (void)
+{
+  record_unwind_protect_void (do_nothing);
+}
+
+/* Clear the unwind-protect entry COUNT, so that it does nothing.
+   It need not be at the top of the stack.  */
+
 void
 clear_unwind_protect (ptrdiff_t count)
 {
@@ -3237,6 +3251,10 @@ clear_unwind_protect (ptrdiff_t count)
   p->unwind_void.func = do_nothing;
 }
 
+/* Set the unwind-protect entry COUNT so that it invokes FUNC (ARG).
+   It need not be at the top of the stack.  Discard the entry's
+   previous value without invoking it.  */
+
 void
 set_unwind_protect_ptr (ptrdiff_t count, void (*func) (void *), void *arg)
 {
@@ -3246,6 +3264,9 @@ set_unwind_protect_ptr (ptrdiff_t count, void (*func) (void *), void *arg)
   p->unwind_ptr.arg = arg;
 }
 
+/* Pop and execute entries from the unwind-protect stack until the
+   depth COUNT is reached.  Return VALUE.  */
+
 Lisp_Object
 unbind_to (ptrdiff_t count, Lisp_Object value)
 {
index 28b2dc847261ddea27d2a2ed2aacf4b69713c2fb..5fe359d58bbc36b8a6a1683e3e4e1c2e8bd4aed4 100644 (file)
@@ -220,6 +220,13 @@ close_file_unwind (int fd)
   emacs_close (fd);
 }
 
+void
+fclose_unwind (void *arg)
+{
+  FILE *stream = arg;
+  fclose (stream);
+}
+
 /* Restore point, having saved it as a marker.  */
 
 void
index 231dbee2d21137ce805776f8dd748c61bd295ca1..518de9db0ffc30b7a22e332ee9261636c448962b 100644 (file)
@@ -3743,6 +3743,7 @@ extern void record_unwind_protect (void (*) (Lisp_Object), Lisp_Object);
 extern void record_unwind_protect_int (void (*) (int), int);
 extern void record_unwind_protect_ptr (void (*) (void *), void *);
 extern void record_unwind_protect_void (void (*) (void));
+extern void record_unwind_protect_nothing (void);
 extern void clear_unwind_protect (ptrdiff_t);
 extern void set_unwind_protect_ptr (ptrdiff_t, void (*) (void *), void *);
 extern Lisp_Object unbind_to (ptrdiff_t, Lisp_Object);
@@ -3827,6 +3828,7 @@ extern Lisp_Object Qfile_name_history;
 extern Lisp_Object expand_and_dir_to_file (Lisp_Object, Lisp_Object);
 EXFUN (Fread_file_name, 6);     /* Not a normal DEFUN.  */
 extern void close_file_unwind (int);
+extern void fclose_unwind (void *);
 extern void restore_point_unwind (Lisp_Object);
 extern _Noreturn void report_file_errno (const char *, Lisp_Object, int);
 extern _Noreturn void report_file_error (const char *, Lisp_Object);
index ee387b832c5c72b63add7f6cd45f62f7794e9079..146543a99fd7a5a6b2f50154a06eeb115636f89a 100644 (file)
@@ -145,7 +145,6 @@ static int read_emacs_mule_char (int, int (*) (int, Lisp_Object),
 static void readevalloop (Lisp_Object, FILE *, Lisp_Object, bool,
                           Lisp_Object, Lisp_Object,
                           Lisp_Object, Lisp_Object);
-static void load_unwind (void *);
 \f
 /* Functions that read one byte from the current source READCHARFUN
    or unreads one byte.  If the integer argument C is -1, it returns
@@ -1317,7 +1316,7 @@ Return t if the file exists and loads successfully.  */)
     }
   if (! stream)
     report_file_error ("Opening stdio stream", file);
-  set_unwind_protect_ptr (fd_index, load_unwind, stream);
+  set_unwind_protect_ptr (fd_index, fclose_unwind, stream);
 
   if (! NILP (Vpurify_flag))
     Vpreloaded_file_list = Fcons (Fpurecopy (file), Vpreloaded_file_list);
@@ -1387,18 +1386,6 @@ Return t if the file exists and loads successfully.  */)
 
   return Qt;
 }
-
-static void
-load_unwind (void *arg)
-{
-  FILE *stream = arg;
-  if (stream != NULL)
-    {
-      block_input ();
-      fclose (stream);
-      unblock_input ();
-    }
-}
 \f
 static bool
 complete_filename_p (Lisp_Object pathname)