Avoid a cppcheck warning about undefined behavior (using the address

of a stack buffer - 1) and fix a memory leak of the iov when
doing nl->crnl conversion.
This commit is contained in:
Todd C. Miller
2015-01-30 10:45:15 -07:00
parent 1517d18b1d
commit 0ac881ba4b

View File

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