gawk-diffs
[Top][All Lists]
Advanced

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

[gawk-diffs] [SCM] gawk branch, feature/stringfix, updated. gawk-4.1.0-2


From: Andrew J. Schorr
Subject: [gawk-diffs] [SCM] gawk branch, feature/stringfix, updated. gawk-4.1.0-2434-gabe02aa
Date: Fri, 27 Jan 2017 19:58:58 +0000 (UTC)

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gawk".

The branch, feature/stringfix has been updated
       via  abe02aa78b8d1620d7d142ab96b650b3acd9d54c (commit)
      from  a7addf98875555f48f30e7a9260f39a36a7b3e75 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.sv.gnu.org/cgit/gawk.git/commit/?id=abe02aa78b8d1620d7d142ab96b650b3acd9d54c

commit abe02aa78b8d1620d7d142ab96b650b3acd9d54c
Author: Andrew J. Schorr <address@hidden>
Date:   Fri Jan 27 14:58:27 2017 -0500

    Protect against string overrun in redirection strings and inet parsing.

diff --git a/ChangeLog b/ChangeLog
index 44eb563..543021b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
 2017-01-27         Andrew J. Schorr     <address@hidden>
 
+       * io.c (redirect_string): Check explen positive before accessing *str.
+       In lintwarn message, use explen string length. Pass length to inetfile.
+       (devopen): Pass name length to inetfile.
+       Stop assuming that remoteport is NUL-terminated.
+       (two_way_open): Pass name length to inetfile.
+       (inetfile): Stop assuming NUL string termination; add checks to avoid 
+       string overrun.
+
+2017-01-27         Andrew J. Schorr     <address@hidden>
+
        * awk.h (str_terminate_f): New helper function for terminating a string
        NODE.
        (str_terminate): Macro wrapper to call str_terminate_f.
diff --git a/io.c b/io.c
index d65f2aa..9d1d06a 100644
--- a/io.c
+++ b/io.c
@@ -306,7 +306,7 @@ struct inet_socket_info {
        } localport, remotehost, remoteport;
 };
 
-static bool inetfile(const char *str, struct inet_socket_info *isn);
+static bool inetfile(const char *str, size_t len, struct inet_socket_info 
*isn);
 
 static NODE *in_PROCINFO(const char *pidx1, const char *pidx2, NODE 
**full_idx);
 static long get_read_timeout(IOBUF *iop);
@@ -786,21 +786,21 @@ redirect_string(const char *str, size_t explen, bool 
not_string,
                lintwarn(_("expression in `%s' redirection is a number"),
                        what);
 
-       if (str == NULL || *str == '\0')
+       if (explen < 1 || str == NULL || *str == '\0')
                fatal(_("expression for `%s' redirection has null string 
value"),
                        what);
 
        if (do_lint && (strncmp(str, "0", explen) == 0
                        || strncmp(str, "1", explen) == 0))
-               lintwarn(_("filename `%s' for `%s' redirection may be result of 
logical expression"),
-                               str, what);
+               lintwarn(_("filename `%.*s' for `%s' redirection may be result 
of logical expression"),
+                               (int) explen, str, what);
 
 #ifdef HAVE_SOCKETS
        /*
         * Use /inet4 to force IPv4, /inet6 to force IPv6, and plain
         * /inet will be whatever we get back from the system.
         */
-       if (inetfile(str, & isi)) {
+       if (inetfile(str, explen, & isi)) {
                tflag |= RED_SOCKET;
                if (isi.protocol == SOCK_STREAM)
                        tflag |= RED_TCP;       /* use shutdown when closing */
@@ -1740,7 +1740,7 @@ devopen(const char *name, const char *mode)
 
        if (do_traditional) {
                goto strictopen;
-       } else if (inetfile(name, & isi)) {
+       } else if (inetfile(name, strlen(name), & isi)) {
 #ifdef HAVE_SOCKETS
 #define DEFAULT_RETRIES 20
                static unsigned long def_retries = DEFAULT_RETRIES;
@@ -1749,13 +1749,15 @@ devopen(const char *name, const char *mode)
                static long msleep = 1000;
                bool hard_error = false;
                bool non_fatal = is_non_fatal_redirect(name, strlen(name));
+               char save;
 
                cp = (char *) name;
 
                /* socketopen requires NUL-terminated strings */
                cp[isi.localport.offset+isi.localport.len] = '\0';
                cp[isi.remotehost.offset+isi.remotehost.len] = '\0';
-               /* remoteport comes last, so already NUL-terminated */
+               save = cp[isi.remoteport.offset+isi.remoteport.len];
+               cp[isi.remoteport.offset+isi.remoteport.len] = '\0';
 
                if (first_time) {
                        char *cp, *end;
@@ -1801,6 +1803,7 @@ devopen(const char *name, const char *mode)
                /* restore original name string */
                cp[isi.localport.offset+isi.localport.len] = '/';
                cp[isi.remotehost.offset+isi.remotehost.len] = '/';
+               cp[isi.remoteport.offset+isi.remoteport.len] = save;
 #else /* ! HAVE_SOCKETS */
                fatal(_("TCP/IP communications are not supported"));
 #endif /* HAVE_SOCKETS */
@@ -1823,7 +1826,7 @@ strictopen:
                   not permitted.  */
                struct stat buf;
 
-               if (! inetfile(name, NULL)
+               if (! inetfile(name, strlen(name), NULL)
                    && stat(name, & buf) == 0 && S_ISDIR(buf.st_mode))
                        errno = EISDIR;
        }
@@ -1845,7 +1848,7 @@ two_way_open(const char *str, struct redirect *rp, int 
extfd)
 
 #ifdef HAVE_SOCKETS
        /* case 1: socket */
-       if (extfd >= 0 || inetfile(str, NULL)) {
+       if (extfd >= 0 || inetfile(str, strlen(str), NULL)) {
                int fd, newfd;
 
                fd = (extfd >= 0) ? extfd : devopen(str, "rw");
@@ -3960,21 +3963,24 @@ free_rp(struct redirect *rp)
 /* inetfile --- return true for a /inet special file, set other values */
 
 static bool
-inetfile(const char *str, struct inet_socket_info *isi)
+inetfile(const char *str, size_t len, struct inet_socket_info *isi)
 {
 #ifndef HAVE_SOCKETS
        return false;
 #else
        const char *cp = str;
+       const char *cpend = str + len;
        struct inet_socket_info buf;
 
        /* syntax: /inet/protocol/localport/hostname/remoteport */
-       if (strncmp(cp, "/inet", 5) != 0)
+       if (len < 5 || strncmp(cp, "/inet", 5) != 0)
                /* quick exit */
                return false;
        if (! isi)
                isi = & buf;
        cp += 5;
+       if (cpend - cp < 2)
+               return false;
        switch (*cp) {
        case '/':
                isi->family = AF_UNSPEC;
@@ -3995,6 +4001,8 @@ inetfile(const char *str, struct inet_socket_info *isi)
        cp++;   /* skip past '/' */
 
        /* which protocol? */
+       if (cpend - cp < 5)
+               return false;
        if (strncmp(cp, "tcp/", 4) == 0)
                isi->protocol = SOCK_STREAM;
        else if (strncmp(cp, "udp/", 4) == 0)
@@ -4005,37 +4013,43 @@ inetfile(const char *str, struct inet_socket_info *isi)
 
        /* which localport? */
        isi->localport.offset = cp-str;
-       while (*cp != '/' && *cp != '\0')
-               cp++;
+       while (*cp != '/') {
+               if (++cp >= cpend)
+                       return false;
+       }
        /*
         * Require a port, let them explicitly put 0 if
         * they don't care.
         */
-       if (*cp != '/' || ((isi->localport.len = 
(cp-str)-isi->localport.offset) == 0))
+       if ((isi->localport.len = (cp-str)-isi->localport.offset) == 0)
                return false;
 
        /* which hostname? */
+       if (cpend - cp < 2)
+               return false;
        cp++;
        isi->remotehost.offset = cp-str;
-       while (*cp != '/' && *cp != '\0')
-               cp++;
-       if (*cp != '/' || ((isi->remotehost.len = 
(cp-str)-isi->remotehost.offset) == 0))
+       while (*cp != '/') {
+               if (++cp >= cpend)
+                       return false;
+       }
+       if ((isi->remotehost.len = (cp-str)-isi->remotehost.offset) == 0)
                return false;
 
        /* which remoteport? */
+       if (cpend - cp < 2)
+               return false;
        cp++;
        /*
         * The remote port ends the special file name.
-        * This means there already is a '\0' at the end of the string.
-        * Therefore no need to patch any string ending.
         *
         * Here too, require a port, let them explicitly put 0 if
         * they don't care.
         */
        isi->remoteport.offset = cp-str;
-       while (*cp != '/' && *cp != '\0')
+       while (*cp != '/' && cp < cpend)
                cp++;
-       if (*cp != '\0' || ((isi->remoteport.len = 
(cp-str)-isi->remoteport.offset) == 0))
+       if (cp != cpend || ((isi->remoteport.len = 
(cp-str)-isi->remoteport.offset) == 0))
                return false;
 
 #ifndef HAVE_GETADDRINFO

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog |   10 ++++++++++
 io.c      |   56 +++++++++++++++++++++++++++++++++++---------------------
 2 files changed, 45 insertions(+), 21 deletions(-)


hooks/post-receive
-- 
gawk



reply via email to

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