Avoid wraparound when casting unsigned size_t to signed ssize_t.
authorAndy Dougherty <doughera@lafayette.edu>
Wed, 16 Jan 2013 17:30:43 +0000 (12:30 -0500)
committerYves Orton <demerphq@gmail.com>
Thu, 14 Feb 2013 07:05:40 +0000 (08:05 +0100)
Practically, this only affects a perl compiled with 64-bit IVs on a 32-bit
system.  In that instance a value of count >= 2**31 would turn negative
when cast to (ssize_t).
(cherry picked from commit 94e529cc4d56863d7272c254a29eda2b002a4335)

perlio.c

index b54b9b1..35379e3 100644 (file)
--- a/perlio.c
+++ b/perlio.c
@@ -2125,7 +2125,7 @@ PerlIOBase_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
            SSize_t avail = PerlIO_get_cnt(f);
            SSize_t take = 0;
            if (avail > 0)
-               take = ((SSize_t)count < avail) ? (SSize_t)count : avail;
+               take = (((SSize_t) count >= 0) && ((SSize_t)count < avail)) ? (SSize_t)count : avail;
            if (take > 0) {
                STDCHAR *ptr = PerlIO_get_ptr(f);
                Copy(ptr, buf, take, STDCHAR);
@@ -3936,7 +3936,7 @@ PerlIOBuf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
             */
            b->posn -= b->bufsiz;
        }
-       if (avail > (SSize_t) count) {
+       if ((SSize_t) count >= 0 && avail > (SSize_t) count) {
            /*
             * If we have space for more than count, just move count
             */
@@ -3986,7 +3986,7 @@ PerlIOBuf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
     }
     while (count > 0) {
        SSize_t avail = b->bufsiz - (b->ptr - b->buf);
-       if ((SSize_t) count < avail)
+       if ((SSize_t) count >= 0 && (SSize_t) count < avail)
            avail = count;
        if (flushptr > buf && flushptr <= buf + avail)
            avail = flushptr - buf;
@@ -4262,7 +4262,7 @@ PerlIOPending_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
 {
     SSize_t avail = PerlIO_get_cnt(f);
     SSize_t got = 0;
-    if ((SSize_t)count < avail)
+    if ((SSize_t) count >= 0 && (SSize_t)count < avail)
        avail = count;
     if (avail > 0)
        got = PerlIOBuf_read(aTHX_ f, vbuf, avail);