From 9c05bccfb9cd29ab66b5c46643467671315a0f29 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 23 Aug 2013 19:23:34 -0700 Subject: [PATCH] System-dependent integer overflow fixes. * process.c (Fset_process_window_size): Signal an error if the window size is outside the range supported by the lower level. * sysdep.c (set_window_size): Return negative on error, nonnegative on success, rather than -1, 0, 1 on not in system, failure, success. This is simpler. Caller changed. (serial_configure): Remove unnecessary initialization of local. (procfs_get_total_memory) [GNU_LINUX]: Don't assume system memory size fits in unsigned long; this isn't true on some 32-bit hosts. Avoid buffer overrun if some future version of /proc/meminfo has a variable name longer than 20 bytes. (system_process_attributes) [__FreeBSD__]: Don't assume hw.availpages fits in 'int'. --- src/ChangeLog | 16 ++++++++++++++++ src/process.c | 13 ++++++++----- src/sysdep.c | 55 +++++++++++++++++++++++++++++++------------------------ 3 files changed, 55 insertions(+), 29 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 73fdb0221ce..3eccf6ff557 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,19 @@ +2013-08-24 Paul Eggert + + System-dependent integer overflow fixes. + * process.c (Fset_process_window_size): Signal an error if + the window size is outside the range supported by the lower level. + * sysdep.c (set_window_size): Return negative on error, + nonnegative on success, rather than -1, 0, 1 on not in system, + failure, success. This is simpler. Caller changed. + (serial_configure): Remove unnecessary initialization of local. + (procfs_get_total_memory) [GNU_LINUX]: Don't assume system memory + size fits in unsigned long; this isn't true on some 32-bit hosts. + Avoid buffer overrun if some future version of /proc/meminfo has a + variable name longer than 20 bytes. + (system_process_attributes) [__FreeBSD__]: + Don't assume hw.availpages fits in 'int'. + 2013-08-23 Paul Eggert Don't let very long directory names overrun the stack. diff --git a/src/process.c b/src/process.c index ea1129ffbb8..c5e691bf602 100644 --- a/src/process.c +++ b/src/process.c @@ -1140,15 +1140,18 @@ See `set-process-sentinel' for more info on sentinels. */) DEFUN ("set-process-window-size", Fset_process_window_size, Sset_process_window_size, 3, 3, 0, doc: /* Tell PROCESS that it has logical window size HEIGHT and WIDTH. */) - (register Lisp_Object process, Lisp_Object height, Lisp_Object width) + (Lisp_Object process, Lisp_Object height, Lisp_Object width) { CHECK_PROCESS (process); - CHECK_RANGED_INTEGER (height, 0, INT_MAX); - CHECK_RANGED_INTEGER (width, 0, INT_MAX); + + /* All known platforms store window sizes as 'unsigned short'. */ + CHECK_RANGED_INTEGER (height, 0, USHRT_MAX); + CHECK_RANGED_INTEGER (width, 0, USHRT_MAX); if (XPROCESS (process)->infd < 0 - || set_window_size (XPROCESS (process)->infd, - XINT (height), XINT (width)) <= 0) + || (set_window_size (XPROCESS (process)->infd, + XINT (height), XINT (width)) + < 0)) return Qnil; else return Qt; diff --git a/src/sysdep.c b/src/sysdep.c index c6d5f9942ab..0d732526528 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -1170,7 +1170,8 @@ get_tty_size (int fd, int *widthp, int *heightp) } /* Set the logical window size associated with descriptor FD - to HEIGHT and WIDTH. This is used mainly with ptys. */ + to HEIGHT and WIDTH. This is used mainly with ptys. + Return a negative value on failure. */ int set_window_size (int fd, int height, int width) @@ -1182,10 +1183,7 @@ set_window_size (int fd, int height, int width) size.ws_row = height; size.ws_col = width; - if (ioctl (fd, TIOCSWINSZ, &size) == -1) - return 0; /* error */ - else - return 1; + return ioctl (fd, TIOCSWINSZ, &size); #else #ifdef TIOCSSIZE @@ -1195,10 +1193,7 @@ set_window_size (int fd, int height, int width) size.ts_lines = height; size.ts_cols = width; - if (ioctl (fd, TIOCGSIZE, &size) == -1) - return 0; - else - return 1; + return ioctl (fd, TIOCGSIZE, &size); #else return -1; #endif /* not SunOS-style */ @@ -2459,7 +2454,7 @@ serial_configure (struct Lisp_Process *p, Lisp_Object childp2 = Qnil; Lisp_Object tem = Qnil; struct termios attr; - int err = -1; + int err; char summary[4] = "???"; /* This usually becomes "8N1". */ childp2 = Fcopy_sequence (p->childp); @@ -2826,29 +2821,41 @@ procfs_ttyname (int rdev) return build_string (name); } -static unsigned long +static uintmax_t procfs_get_total_memory (void) { FILE *fmem; - unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */ + uintmax_t retval = 2 * 1024 * 1024; /* default: 2 GiB */ + int c; block_input (); fmem = emacs_fopen ("/proc/meminfo", "r"); if (fmem) { - unsigned long entry_value; - char entry_name[20]; /* the longest I saw is 13+1 */ + uintmax_t entry_value; + bool done; + + do + switch (fscanf (fmem, "MemTotal: %"SCNuMAX, &entry_value)) + { + case 1: + retval = entry_value; + done = 1; + break; + + case 0: + while ((c = getc (fmem)) != EOF && c != '\n') + continue; + done = c == EOF; + break; + + default: + done = 1; + break; + } + while (!done); - while (!feof (fmem) && !ferror (fmem)) - { - if (fscanf (fmem, "%s %lu kB\n", entry_name, &entry_value) >= 2 - && strcmp (entry_name, "MemTotal:") == 0) - { - retval = entry_value; - break; - } - } fclose (fmem); } unblock_input (); @@ -3249,7 +3256,7 @@ system_process_attributes (Lisp_Object pid) { int proc_id; int pagesize = getpagesize (); - int npages; + unsigned long npages; int fscale; struct passwd *pw; struct group *gr; -- 2.11.4.GIT