]> granicus.if.org Git - sudo/commitdiff
Avoid a cppcheck warning about undefined behavior (using the address
authorTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 30 Jan 2015 17:45:15 +0000 (10:45 -0700)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 30 Jan 2015 17:45:15 +0000 (10:45 -0700)
of a stack buffer - 1) and fix a memory leak of the iov when
doing nl->crnl conversion.

plugins/sudoers/sudoreplay.c

index d1fafbf691c444e5f922e73b4d06cef3028ad175..f3ba0a83e56bab44e0c7db353536f3c41721f739 100644 (file)
@@ -487,20 +487,27 @@ replay_session(const double max_wait, const char *decimal)
            if (need_nlcr) {
                size_t remainder = nread;
                size_t linelen;
-               char *cp = buf;
-               char *ep = buf - 1;
-
-               /* Handle a "\r\n" pair that spans a buffer. */
-               if (last_char == '\r' && buf[0] == '\n') {
-                   ep++;
+               char *line = buf;
+               char *nl, *cp = buf;
+
+               /*
+                * Handle a "\r\n" pair that spans a buffer.
+                * The newline will be written as part of the next line.
+                */
+               if (last_char == '\r' && *cp == '\n') {
+                   cp++;
                    remainder--;
                }
 
                iovcnt = 0;
-               while ((ep = memchr(ep + 1, '\n', remainder)) != NULL) {
-                   /* Is there already a carriage return? */
-                   if (cp != ep && ep[-1] == '\r') {
-                       remainder = (size_t)(&buf[nread - 1] - ep);
+               while ((nl = memchr(cp, '\n', remainder)) != NULL) {
+                   /*
+                    * If there is already a carriage return, keep going.
+                    * We'll include it as part of the next line written.
+                    */
+                   if (cp != nl && nl[-1] == '\r') {
+                       remainder = (size_t)(&buf[nread - 1] - nl);
+                       cp = nl + 1;
                        continue;
                    }
 
@@ -510,23 +517,23 @@ replay_session(const double max_wait, const char *decimal)
                            sudo_ereallocarray(iov, iovmax <<= 1, sizeof(*iov)) :
                            sudo_emallocarray(iovmax = 32, sizeof(*iov));
                    }
-                   linelen = (size_t)(ep - cp) + 1;
-                   iov[iovcnt].iov_base = cp;
+                   linelen = (size_t)(nl - line) + 1;
+                   iov[iovcnt].iov_base = line;
                    iov[iovcnt].iov_len = linelen - 1; /* not including \n */
                    iovcnt++;
                    iov[iovcnt].iov_base = "\r\n";
                    iov[iovcnt].iov_len = 2;
                    iovcnt++;
-                   cp = ep + 1;
+                   line = cp = nl + 1;
                    remainder -= linelen;
                }
-               if ((size_t)(cp - buf) != nread) {
+               if ((size_t)(line - buf) != nread) {
                    /*
                     * Partial line without a linefeed or multiple lines
-                    * with \r\n pairs.
+                    * that already had \r\n pairs.
                     */
-                   iov[iovcnt].iov_base = cp;
-                   iov[iovcnt].iov_len = nread - (cp - buf);
+                   iov[iovcnt].iov_base = line;
+                   iov[iovcnt].iov_len = nread - (line - buf);
                    iovcnt++;
                }
                last_char = buf[nread - 1]; /* stash last char of old buffer */
@@ -550,6 +557,8 @@ replay_session(const double max_wait, const char *decimal)
            sudo_ev_add(evbase, output_ev, NULL, false);
            sudo_ev_loop(evbase, 0);
        }
+       if (iov != &iovb)
+           sudo_efree(iov);
     }
     debug_return;
 }