aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2013-07-17 19:12:59 -0700
committerPaul Eggert2013-07-17 19:12:59 -0700
commitf4b1eb36186a2f873d84d4c089292f9fb0394d31 (patch)
treeea6a4d904679b9f50026abb6dfab00f9b693eb6a /src
parenta0931322f6c257bb4a4a678f62dcb4ae3b253221 (diff)
downloademacs-f4b1eb36186a2f873d84d4c089292f9fb0394d31.tar.gz
emacs-f4b1eb36186a2f873d84d4c089292f9fb0394d31.zip
* 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.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog15
-rw-r--r--src/charset.c30
-rw-r--r--src/eval.c21
-rw-r--r--src/fileio.c7
-rw-r--r--src/lisp.h2
-rw-r--r--src/lread.c15
6 files changed, 65 insertions, 25 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 189a353bde6..3f667a7bcc7 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,18 @@
12013-07-18 Paul Eggert <eggert@cs.ucla.edu>
2
3 * charset.c: Fix file descriptor leaks and errno issues.
4 Include <errno.h>.
5 (load_charset_map_from_file): Don't leak file descriptor on error.
6 Use plain record_xmalloc since the allocation is larger than
7 MAX_ALLOCA; that's simpler here. Simplify test for exhaustion
8 of entries.
9 * eval.c (record_unwind_protect_nothing):
10 * fileio.c (fclose_unwind):
11 New functions.
12 * lread.c (load_unwind): Remove. All uses replaced by fclose_unwind.
13 The replacement doesn't block input, but that no longer seems
14 necessary.
15
12013-07-17 Paul Eggert <eggert@cs.ucla.edu> 162013-07-17 Paul Eggert <eggert@cs.ucla.edu>
2 17
3 * lread.c: Fix file descriptor leaks and errno issues. 18 * lread.c: Fix file descriptor leaks and errno issues.
diff --git a/src/charset.c b/src/charset.c
index 6b7e81c156d..eedf65faa6c 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -28,6 +28,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
28 28
29#define CHARSET_INLINE EXTERN_INLINE 29#define CHARSET_INLINE EXTERN_INLINE
30 30
31#include <errno.h>
31#include <stdio.h> 32#include <stdio.h>
32#include <unistd.h> 33#include <unistd.h>
33#include <limits.h> 34#include <limits.h>
@@ -477,7 +478,8 @@ read_hex (FILE *fp, bool *eof, bool *overflow)
477 `file-name-handler-alist' to avoid running any Lisp code. */ 478 `file-name-handler-alist' to avoid running any Lisp code. */
478 479
479static void 480static void
480load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, int control_flag) 481load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile,
482 int control_flag)
481{ 483{
482 unsigned min_code = CHARSET_MIN_CODE (charset); 484 unsigned min_code = CHARSET_MIN_CODE (charset);
483 unsigned max_code = CHARSET_MAX_CODE (charset); 485 unsigned max_code = CHARSET_MAX_CODE (charset);
@@ -487,21 +489,26 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, int co
487 struct charset_map_entries *head, *entries; 489 struct charset_map_entries *head, *entries;
488 int n_entries; 490 int n_entries;
489 ptrdiff_t count; 491 ptrdiff_t count;
490 USE_SAFE_ALLOCA;
491 492
492 suffixes = list2 (build_string (".map"), build_string (".TXT")); 493 suffixes = list2 (build_string (".map"), build_string (".TXT"));
493 494
494 count = SPECPDL_INDEX (); 495 count = SPECPDL_INDEX ();
496 record_unwind_protect_nothing ();
495 specbind (Qfile_name_handler_alist, Qnil); 497 specbind (Qfile_name_handler_alist, Qnil);
496 fd = openp (Vcharset_map_path, mapfile, suffixes, NULL, Qnil); 498 fd = openp (Vcharset_map_path, mapfile, suffixes, NULL, Qnil);
497 unbind_to (count, Qnil); 499 fp = fd < 0 ? 0 : fdopen (fd, "r");
498 if (fd < 0 500 if (!fp)
499 || ! (fp = fdopen (fd, "r"))) 501 {
500 error ("Failure in loading charset map: %s", SDATA (mapfile)); 502 int open_errno = errno;
503 emacs_close (fd);
504 report_file_errno ("Loading charset map", mapfile, open_errno);
505 }
506 set_unwind_protect_ptr (count, fclose_unwind, fp);
507 unbind_to (count + 1, Qnil);
501 508
502 /* Use SAFE_ALLOCA instead of alloca, as `charset_map_entries' is 509 /* Use record_xmalloc, as `charset_map_entries' is
503 large (larger than MAX_ALLOCA). */ 510 large (larger than MAX_ALLOCA). */
504 head = SAFE_ALLOCA (sizeof *head); 511 head = record_xmalloc (sizeof *head);
505 entries = head; 512 entries = head;
506 memset (entries, 0, sizeof (struct charset_map_entries)); 513 memset (entries, 0, sizeof (struct charset_map_entries));
507 514
@@ -530,9 +537,9 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, int co
530 if (from < min_code || to > max_code || from > to || c > MAX_CHAR) 537 if (from < min_code || to > max_code || from > to || c > MAX_CHAR)
531 continue; 538 continue;
532 539
533 if (n_entries > 0 && (n_entries % 0x10000) == 0) 540 if (n_entries == 0x10000)
534 { 541 {
535 entries->next = SAFE_ALLOCA (sizeof *entries->next); 542 entries->next = record_xmalloc (sizeof *entries->next);
536 entries = entries->next; 543 entries = entries->next;
537 memset (entries, 0, sizeof (struct charset_map_entries)); 544 memset (entries, 0, sizeof (struct charset_map_entries));
538 n_entries = 0; 545 n_entries = 0;
@@ -544,9 +551,10 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, int co
544 n_entries++; 551 n_entries++;
545 } 552 }
546 fclose (fp); 553 fclose (fp);
554 clear_unwind_protect (count);
547 555
548 load_charset_map (charset, head, n_entries, control_flag); 556 load_charset_map (charset, head, n_entries, control_flag);
549 SAFE_FREE (); 557 unbind_to (count, Qnil);
550} 558}
551 559
552static void 560static void
diff --git a/src/eval.c b/src/eval.c
index a4f94ee1415..23834cb54f6 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -3190,6 +3190,8 @@ specbind (Lisp_Object symbol, Lisp_Object value)
3190 } 3190 }
3191} 3191}
3192 3192
3193/* Push unwind-protect entries of various types. */
3194
3193void 3195void
3194record_unwind_protect (void (*function) (Lisp_Object), Lisp_Object arg) 3196record_unwind_protect (void (*function) (Lisp_Object), Lisp_Object arg)
3195{ 3197{
@@ -3229,6 +3231,18 @@ static void
3229do_nothing (void) 3231do_nothing (void)
3230{} 3232{}
3231 3233
3234/* Push an unwind-protect entry that does nothing, so that
3235 set_unwind_protect_ptr can overwrite it later. */
3236
3237void
3238record_unwind_protect_nothing (void)
3239{
3240 record_unwind_protect_void (do_nothing);
3241}
3242
3243/* Clear the unwind-protect entry COUNT, so that it does nothing.
3244 It need not be at the top of the stack. */
3245
3232void 3246void
3233clear_unwind_protect (ptrdiff_t count) 3247clear_unwind_protect (ptrdiff_t count)
3234{ 3248{
@@ -3237,6 +3251,10 @@ clear_unwind_protect (ptrdiff_t count)
3237 p->unwind_void.func = do_nothing; 3251 p->unwind_void.func = do_nothing;
3238} 3252}
3239 3253
3254/* Set the unwind-protect entry COUNT so that it invokes FUNC (ARG).
3255 It need not be at the top of the stack. Discard the entry's
3256 previous value without invoking it. */
3257
3240void 3258void
3241set_unwind_protect_ptr (ptrdiff_t count, void (*func) (void *), void *arg) 3259set_unwind_protect_ptr (ptrdiff_t count, void (*func) (void *), void *arg)
3242{ 3260{
@@ -3246,6 +3264,9 @@ set_unwind_protect_ptr (ptrdiff_t count, void (*func) (void *), void *arg)
3246 p->unwind_ptr.arg = arg; 3264 p->unwind_ptr.arg = arg;
3247} 3265}
3248 3266
3267/* Pop and execute entries from the unwind-protect stack until the
3268 depth COUNT is reached. Return VALUE. */
3269
3249Lisp_Object 3270Lisp_Object
3250unbind_to (ptrdiff_t count, Lisp_Object value) 3271unbind_to (ptrdiff_t count, Lisp_Object value)
3251{ 3272{
diff --git a/src/fileio.c b/src/fileio.c
index 28b2dc84726..5fe359d58bb 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -220,6 +220,13 @@ close_file_unwind (int fd)
220 emacs_close (fd); 220 emacs_close (fd);
221} 221}
222 222
223void
224fclose_unwind (void *arg)
225{
226 FILE *stream = arg;
227 fclose (stream);
228}
229
223/* Restore point, having saved it as a marker. */ 230/* Restore point, having saved it as a marker. */
224 231
225void 232void
diff --git a/src/lisp.h b/src/lisp.h
index 231dbee2d21..518de9db0ff 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3743,6 +3743,7 @@ extern void record_unwind_protect (void (*) (Lisp_Object), Lisp_Object);
3743extern void record_unwind_protect_int (void (*) (int), int); 3743extern void record_unwind_protect_int (void (*) (int), int);
3744extern void record_unwind_protect_ptr (void (*) (void *), void *); 3744extern void record_unwind_protect_ptr (void (*) (void *), void *);
3745extern void record_unwind_protect_void (void (*) (void)); 3745extern void record_unwind_protect_void (void (*) (void));
3746extern void record_unwind_protect_nothing (void);
3746extern void clear_unwind_protect (ptrdiff_t); 3747extern void clear_unwind_protect (ptrdiff_t);
3747extern void set_unwind_protect_ptr (ptrdiff_t, void (*) (void *), void *); 3748extern void set_unwind_protect_ptr (ptrdiff_t, void (*) (void *), void *);
3748extern Lisp_Object unbind_to (ptrdiff_t, Lisp_Object); 3749extern Lisp_Object unbind_to (ptrdiff_t, Lisp_Object);
@@ -3827,6 +3828,7 @@ extern Lisp_Object Qfile_name_history;
3827extern Lisp_Object expand_and_dir_to_file (Lisp_Object, Lisp_Object); 3828extern Lisp_Object expand_and_dir_to_file (Lisp_Object, Lisp_Object);
3828EXFUN (Fread_file_name, 6); /* Not a normal DEFUN. */ 3829EXFUN (Fread_file_name, 6); /* Not a normal DEFUN. */
3829extern void close_file_unwind (int); 3830extern void close_file_unwind (int);
3831extern void fclose_unwind (void *);
3830extern void restore_point_unwind (Lisp_Object); 3832extern void restore_point_unwind (Lisp_Object);
3831extern _Noreturn void report_file_errno (const char *, Lisp_Object, int); 3833extern _Noreturn void report_file_errno (const char *, Lisp_Object, int);
3832extern _Noreturn void report_file_error (const char *, Lisp_Object); 3834extern _Noreturn void report_file_error (const char *, Lisp_Object);
diff --git a/src/lread.c b/src/lread.c
index ee387b832c5..146543a99fd 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -145,7 +145,6 @@ static int read_emacs_mule_char (int, int (*) (int, Lisp_Object),
145static void readevalloop (Lisp_Object, FILE *, Lisp_Object, bool, 145static void readevalloop (Lisp_Object, FILE *, Lisp_Object, bool,
146 Lisp_Object, Lisp_Object, 146 Lisp_Object, Lisp_Object,
147 Lisp_Object, Lisp_Object); 147 Lisp_Object, Lisp_Object);
148static void load_unwind (void *);
149 148
150/* Functions that read one byte from the current source READCHARFUN 149/* Functions that read one byte from the current source READCHARFUN
151 or unreads one byte. If the integer argument C is -1, it returns 150 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. */)
1317 } 1316 }
1318 if (! stream) 1317 if (! stream)
1319 report_file_error ("Opening stdio stream", file); 1318 report_file_error ("Opening stdio stream", file);
1320 set_unwind_protect_ptr (fd_index, load_unwind, stream); 1319 set_unwind_protect_ptr (fd_index, fclose_unwind, stream);
1321 1320
1322 if (! NILP (Vpurify_flag)) 1321 if (! NILP (Vpurify_flag))
1323 Vpreloaded_file_list = Fcons (Fpurecopy (file), Vpreloaded_file_list); 1322 Vpreloaded_file_list = Fcons (Fpurecopy (file), Vpreloaded_file_list);
@@ -1387,18 +1386,6 @@ Return t if the file exists and loads successfully. */)
1387 1386
1388 return Qt; 1387 return Qt;
1389} 1388}
1390
1391static void
1392load_unwind (void *arg)
1393{
1394 FILE *stream = arg;
1395 if (stream != NULL)
1396 {
1397 block_input ();
1398 fclose (stream);
1399 unblock_input ();
1400 }
1401}
1402 1389
1403static bool 1390static bool
1404complete_filename_p (Lisp_Object pathname) 1391complete_filename_p (Lisp_Object pathname)