emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] /srv/bzr/emacs/trunk r103919: emacs_write: Accept and retu


From: Paul Eggert
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r103919: emacs_write: Accept and return EMACS_INT for sizes.
Date: Fri, 15 Apr 2011 01:51:02 -0700
User-agent: Bazaar (2.3.1)

------------------------------------------------------------
revno: 103919 [merge]
committer: Paul Eggert <address@hidden>
branch nick: trunk
timestamp: Fri 2011-04-15 01:51:02 -0700
message:
  emacs_write: Accept and return EMACS_INT for sizes.
modified:
  src/ChangeLog
  src/gnutls.c
  src/gnutls.h
  src/lisp.h
  src/process.c
  src/sound.c
  src/sysdep.c
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2011-04-15 02:03:43 +0000
+++ b/src/ChangeLog     2011-04-15 08:51:02 +0000
@@ -1,3 +1,30 @@
+2011-04-15  Paul Eggert  <address@hidden>
+
+       emacs_write: Accept and return EMACS_INT for sizes.
+       See http://lists.gnu.org/archive/html/emacs-devel/2011-04/msg00514.html
+       et seq.
+       * gnutls.c, gnutls.h (emacs_gnutls_read, emacs_gnutls_write):
+       Accept and return EMACS_INT.
+       (emacs_gnutls_write): Return the number of bytes written on
+       partial writes.
+       * sysdep.c, lisp.h (emacs_read, emacs_write): Likewise.
+       (emacs_read, emacs_write): Remove check for negative size, as the
+       Emacs source code has been audited now.
+       * sysdep.c (MAX_RW_COUNT): New macro, to work around kernel bugs.
+       (emacs_read, emacs_write): Use it.
+       * process.c (send_process): Adjust to the new signatures of
+       emacs_write and emacs_gnutls_write.  Do not attempt to store
+       a byte offset into an 'int'; it might overflow.
+       See http://lists.gnu.org/archive/html/emacs-devel/2011-04/msg00483.html
+
+       * sound.c: Don't assume sizes fit in 'int'.
+       (struct sound_device.period_size, alsa_period_size):
+       Return EMACS_INT, not int.
+       (struct sound_device.write, vox_write, alsa_write):
+       Accept EMACS_INT, not int.
+       (wav_play, au_play): Use EMACS_INT to store sizes and to
+       record read return values.
+
 2011-04-15  Ben Key  <address@hidden>
 
        * keyboard.c (Qundefined):  Don't declare static since it is

=== modified file 'src/gnutls.c'
--- a/src/gnutls.c      2011-04-10 14:00:13 +0000
+++ b/src/gnutls.c      2011-04-15 08:22:34 +0000
@@ -70,12 +70,12 @@
     }
 }
 
-ssize_t
+EMACS_INT
 emacs_gnutls_write (int fildes, struct Lisp_Process *proc, const char *buf,
-                    size_t nbyte)
+                    EMACS_INT nbyte)
 {
   ssize_t rtnval;
-  size_t bytes_written;
+  EMACS_INT bytes_written;
   gnutls_session_t state = proc->gnutls_state;
 
   if (proc->gnutls_initstage != GNUTLS_STAGE_READY) {
@@ -85,7 +85,7 @@
 #ifdef EAGAIN
     errno = EAGAIN;
 #endif
-    return -1;
+    return 0;
   }
 
   bytes_written = 0;
@@ -99,7 +99,7 @@
           if (rtnval == GNUTLS_E_AGAIN || rtnval == GNUTLS_E_INTERRUPTED)
             continue;
           else
-            return (bytes_written ? bytes_written : -1);
+            break;
         }
 
       buf += rtnval;
@@ -110,9 +110,9 @@
   return (bytes_written);
 }
 
-ssize_t
+EMACS_INT
 emacs_gnutls_read (int fildes, struct Lisp_Process *proc, char *buf,
-                   size_t nbyte)
+                   EMACS_INT nbyte)
 {
   ssize_t rtnval;
   gnutls_session_t state = proc->gnutls_state;

=== modified file 'src/gnutls.h'
--- a/src/gnutls.h      2011-04-10 14:00:13 +0000
+++ b/src/gnutls.h      2011-04-15 08:22:34 +0000
@@ -50,12 +50,12 @@
 
 #define GNUTLS_LOG2(level, max, string, extra) if (level <= max) { 
gnutls_log_function2 (level, "(Emacs) " string, extra); }
 
-ssize_t
+EMACS_INT
 emacs_gnutls_write (int fildes, struct Lisp_Process *proc, const char *buf,
-                    size_t nbyte);
-ssize_t
+                    EMACS_INT nbyte);
+EMACS_INT
 emacs_gnutls_read (int fildes, struct Lisp_Process *proc, char *buf,
-                   size_t nbyte);
+                   EMACS_INT nbyte);
 
 extern void syms_of_gnutls (void);
 

=== modified file 'src/lisp.h'
--- a/src/lisp.h        2011-04-15 00:58:49 +0000
+++ b/src/lisp.h        2011-04-15 08:22:34 +0000
@@ -3317,8 +3317,8 @@
 extern void seed_random (long);
 extern int emacs_open (const char *, int, int);
 extern int emacs_close (int);
-extern ssize_t emacs_read (int, char *, size_t);
-extern ssize_t emacs_write (int, const char *, size_t);
+extern EMACS_INT emacs_read (int, char *, EMACS_INT);
+extern EMACS_INT emacs_write (int, const char *, EMACS_INT);
 enum { READLINK_BUFSIZE = 1024 };
 extern char *emacs_readlink (const char *, char [READLINK_BUFSIZE]);
 #ifndef HAVE_MEMSET

=== modified file 'src/process.c'
--- a/src/process.c     2011-04-15 00:58:49 +0000
+++ b/src/process.c     2011-04-15 08:35:53 +0000
@@ -5368,6 +5368,7 @@
          /* Send this batch, using one or more write calls.  */
          while (this > 0)
            {
+             EMACS_INT written = 0;
              int outfd = p->outfd;
              old_sigpipe = (void (*) (int)) signal (SIGPIPE, 
send_process_trap);
 #ifdef DATAGRAM_SOCKETS
@@ -5376,7 +5377,9 @@
                  rv = sendto (outfd, buf, this,
                               0, datagram_address[outfd].sa,
                               datagram_address[outfd].len);
-                 if (rv < 0 && errno == EMSGSIZE)
+                 if (0 <= rv)
+                   written = rv;
+                 else if (errno == EMSGSIZE)
                    {
                      signal (SIGPIPE, old_sigpipe);
                      report_file_error ("sending datagram",
@@ -5388,12 +5391,13 @@
                {
 #ifdef HAVE_GNUTLS
                  if (XPROCESS (proc)->gnutls_p)
-                   rv = emacs_gnutls_write (outfd,
-                                            XPROCESS (proc),
-                                            buf, this);
+                   written = emacs_gnutls_write (outfd,
+                                                XPROCESS (proc),
+                                                buf, this);
                  else
 #endif
-                   rv = emacs_write (outfd, buf, this);
+                   written = emacs_write (outfd, buf, this);
+                 rv = (written ? 0 : -1);
 #ifdef ADAPTIVE_READ_BUFFERING
                  if (p->read_output_delay > 0
                      && p->adaptive_read_buffering == 1)
@@ -5420,7 +5424,7 @@
                       that may allow the program
                       to finish doing output and read more.  */
                    {
-                     int offset = 0;
+                     EMACS_INT offset = 0;
 
 #ifdef BROKEN_PTY_READ_AFTER_EAGAIN
                      /* A gross hack to work around a bug in FreeBSD.
@@ -5466,16 +5470,14 @@
                                                         offset);
                      else if (STRINGP (object))
                        buf = offset + SSDATA (object);
-
-                     rv = 0;
                    }
                  else
                    /* This is a real error.  */
                    report_file_error ("writing to process", Fcons (proc, 
Qnil));
                }
-             buf += rv;
-             len -= rv;
-             this -= rv;
+             buf += written;
+             len -= written;
+             this -= written;
            }
        }
     }

=== modified file 'src/sound.c'
--- a/src/sound.c       2011-04-14 20:16:48 +0000
+++ b/src/sound.c       2011-04-15 08:47:25 +0000
@@ -235,11 +235,11 @@
 
   /* Return a preferred data size in bytes to be sent to write (below)
      each time.  2048 is used if this is NULL.  */
-  int (* period_size) (struct sound_device *sd);
+  EMACS_INT (* period_size) (struct sound_device *sd);
 
   /* Write NYBTES bytes from BUFFER to device SD.  */
   void (* write) (struct sound_device *sd, const char *buffer,
-                  int nbytes);
+                  EMACS_INT nbytes);
 
   /* A place for devices to store additional data.  */
   void *data;
@@ -291,7 +291,7 @@
 static void vox_close (struct sound_device *sd);
 static void vox_choose_format (struct sound_device *, struct sound *);
 static int vox_init (struct sound_device *);
-static void vox_write (struct sound_device *, const char *, int);
+static void vox_write (struct sound_device *, const char *, EMACS_INT);
 static void find_sound_type (struct sound *);
 static u_int32_t le2hl (u_int32_t);
 static u_int16_t le2hs (u_int16_t);
@@ -600,9 +600,9 @@
   else
     {
       char *buffer;
-      int nbytes = 0;
-      int blksize = sd->period_size ? sd->period_size (sd) : 2048;
-      int data_left = header->data_length;
+      EMACS_INT nbytes = 0;
+      EMACS_INT blksize = sd->period_size ? sd->period_size (sd) : 2048;
+      EMACS_INT data_left = header->data_length;
 
       buffer = (char *) alloca (blksize);
       lseek (s->fd, sizeof *header, SEEK_SET);
@@ -690,9 +690,9 @@
               SBYTES (s->data) - header->data_offset);
   else
     {
-      int blksize = sd->period_size ? sd->period_size (sd) : 2048;
+      EMACS_INT blksize = sd->period_size ? sd->period_size (sd) : 2048;
       char *buffer;
-      int nbytes;
+      EMACS_INT nbytes;
 
       /* Seek */
       lseek (s->fd, header->data_offset, SEEK_SET);
@@ -895,10 +895,9 @@
 /* Write NBYTES bytes from BUFFER to device SD.  */
 
 static void
-vox_write (struct sound_device *sd, const char *buffer, int nbytes)
+vox_write (struct sound_device *sd, const char *buffer, EMACS_INT nbytes)
 {
-  ssize_t nwritten = emacs_write (sd->fd, buffer, nbytes);
-  if (nwritten < 0)
+  if (emacs_write (sd->fd, buffer, nbytes) != nbytes)
     sound_perror ("Error writing to sound device");
 }
 
@@ -953,7 +952,7 @@
     alsa_sound_perror (file, err);
 }
 
-static int
+static EMACS_INT
 alsa_period_size (struct sound_device *sd)
 {
   struct alsa_params *p = (struct alsa_params *) sd->data;
@@ -1156,13 +1155,13 @@
 /* Write NBYTES bytes from BUFFER to device SD.  */
 
 static void
-alsa_write (struct sound_device *sd, const char *buffer, int nbytes)
+alsa_write (struct sound_device *sd, const char *buffer, EMACS_INT nbytes)
 {
   struct alsa_params *p = (struct alsa_params *) sd->data;
 
   /* The the third parameter to snd_pcm_writei is frames, not bytes. */
   int fact = snd_pcm_format_size (sd->format, 1) * sd->channels;
-  int nwritten = 0;
+  EMACS_INT nwritten = 0;
   int err;
 
   while (nwritten < nbytes)

=== modified file 'src/sysdep.c'
--- a/src/sysdep.c      2011-04-14 20:16:48 +0000
+++ b/src/sysdep.c      2011-04-15 08:22:34 +0000
@@ -1825,41 +1825,47 @@
   return rtnval;
 }
 
-ssize_t
-emacs_read (int fildes, char *buf, size_t nbyte)
+/* Maximum number of bytes to read or write in a single system call.
+   This works around a serious bug in Linux kernels before 2.6.16; see
+   <https://bugzilla.redhat.com/show_bug.cgi?format=multiple&id=612839>.
+   It's likely to work around similar bugs in other operating systems, so do it
+   on all platforms.  Round INT_MAX down to a page size, with the conservative
+   assumption that page sizes are at most 2**18 bytes (any kernel with a
+   page size larger than that shouldn't have the bug).  */
+#ifndef MAX_RW_COUNT
+#define MAX_RW_COUNT (INT_MAX >> 18 << 18)
+#endif
+
+/* Read from FILEDESC to a buffer BUF with size NBYTE, retrying if interrupted.
+   Return the number of bytes read, which might be less than NBYTE.
+   On error, set errno and return -1.  */
+EMACS_INT
+emacs_read (int fildes, char *buf, EMACS_INT nbyte)
 {
   register ssize_t rtnval;
 
-  /* Defend against the possibility that a buggy caller passes a negative NBYTE
-     argument, which would be converted to a large unsigned size_t NBYTE.  This
-     defense prevents callers from doing large writes, unfortunately.  This
-     size restriction can be removed once we have carefully checked that there
-     are no such callers.  */
-  if ((ssize_t) nbyte < 0)
-    abort ();
-
-  while ((rtnval = read (fildes, buf, nbyte)) == -1
+  while ((rtnval = read (fildes, buf, min (nbyte, MAX_RW_COUNT))) == -1
         && (errno == EINTR))
     QUIT;
   return (rtnval);
 }
 
-ssize_t
-emacs_write (int fildes, const char *buf, size_t nbyte)
+/* Write to FILEDES from a buffer BUF with size NBYTE, retrying if interrupted
+   or if a partial write occurs.  Return the number of bytes written, setting
+   errno if this is less than NBYTE.  */
+EMACS_INT
+emacs_write (int fildes, const char *buf, EMACS_INT nbyte)
 {
-  register ssize_t rtnval, bytes_written;
-
-  /* Defend against negative NBYTE, as in emacs_read.  */
-  if ((ssize_t) nbyte < 0)
-    abort ();
+  ssize_t rtnval;
+  EMACS_INT bytes_written;
 
   bytes_written = 0;
 
-  while (nbyte != 0)
+  while (nbyte > 0)
     {
-      rtnval = write (fildes, buf, nbyte);
+      rtnval = write (fildes, buf, min (nbyte, MAX_RW_COUNT));
 
-      if (rtnval == -1)
+      if (rtnval < 0)
        {
          if (errno == EINTR)
            {
@@ -1871,13 +1877,14 @@
              continue;
            }
          else
-           return (bytes_written ? bytes_written : -1);
+           break;
        }
 
       buf += rtnval;
       nbyte -= rtnval;
       bytes_written += rtnval;
     }
+
   return (bytes_written);
 }
 


reply via email to

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