Page MenuHomeFreeBSD

D58113.id181700.diff
No OneTemporary

D58113.id181700.diff

diff --git a/lib/libfetch/common.h b/lib/libfetch/common.h
--- a/lib/libfetch/common.h
+++ b/lib/libfetch/common.h
@@ -49,8 +49,10 @@
struct fetchconn {
int sd; /* socket descriptor */
char *buf; /* buffer */
+ char *line; /* line (within buffer) */
size_t bufsize; /* buffer size */
size_t buflen; /* length of buffer contents */
+ size_t linelen; /* length of line */
size_t pos; /* current position in buffer */
int err; /* last protocol reply code */
#ifdef WITH_SSL
diff --git a/lib/libfetch/common.c b/lib/libfetch/common.c
--- a/lib/libfetch/common.c
+++ b/lib/libfetch/common.c
@@ -1437,12 +1437,23 @@
/* allocate initial buffer */
if (conn->buf == NULL) {
if ((conn->buf = malloc(MIN_BUF_SIZE)) == NULL)
- return (-1);
+ goto fail;
+ conn->line = conn->buf;
conn->bufsize = MIN_BUF_SIZE;
conn->buflen = 0;
conn->pos = 0;
}
+ /* look at the data we already have */
+ if (conn->pos < conn->buflen) {
+ conn->line = conn->buf + conn->pos;
+ while (conn->pos < conn->buflen)
+ if (conn->buf[conn->pos++] == '\n')
+ goto found;
+ /* reset for the upcoming memmove() */
+ conn->pos = conn->line - conn->buf;
+ }
+
/* move residual data up */
if (conn->buflen > 0) {
if (conn->pos < conn->buflen) {
@@ -1451,20 +1462,16 @@
}
conn->buflen -= conn->pos;
conn->pos -= conn->pos;
+ conn->line = conn->buf;
}
- /* do we have a complete line? */
- while (conn->pos < conn->buflen)
- if (conn->buf[conn->pos++] == '\n')
- goto found;
-
for (;;) {
/* read as much as we can right now */
rlen = fetch_read(conn, conn->buf + conn->buflen,
conn->bufsize - conn->buflen - 1);
/* error */
if (rlen < 0)
- return (-1);
+ goto fail;
/* advance and terminate */
conn->buflen += rlen;
conn->buf[conn->buflen] = '\0';
@@ -1480,21 +1487,25 @@
tmp = conn->buf;
tmpsize = conn->bufsize * 2;
if ((tmp = realloc(tmp, tmpsize)) == NULL)
- return (-1);
- conn->buf = tmp;
+ goto fail;
+ conn->line = conn->buf = tmp;
conn->bufsize = tmpsize;
}
}
/* connection closed, return what's left */
conn->pos = conn->buflen;
found:
- rlen = conn->pos;
- if (rlen > 0 && conn->buf[rlen - 1] == '\n')
- conn->buf[--rlen] = '\0';
- if (rlen > 0 && conn->buf[rlen - 1] == '\r')
- conn->buf[--rlen] = '\0';
- DEBUGF("<<< %.*s\n", (int)rlen, conn->buf);
- return (rlen);
+ conn->linelen = (conn->buf + conn->pos) - conn->line;
+ if (conn->linelen > 0 && conn->line[conn->linelen - 1] == '\n')
+ conn->line[--conn->linelen] = '\0';
+ if (conn->linelen > 0 && conn->line[conn->linelen - 1] == '\r')
+ conn->line[--conn->linelen] = '\0';
+ DEBUGF("<<< %.*s\n", (int)conn->linelen, conn->line);
+ return (conn->linelen);
+fail:
+ conn->line = NULL;
+ conn->linelen = 0;
+ return (-1);
}
@@ -1520,6 +1531,8 @@
conn->buflen = 0;
conn->pos = 0;
}
+ conn->line = NULL;
+ conn->linelen = 0;
/* return residual data first */
if (conn->buflen > conn->pos) {
diff --git a/lib/libfetch/ftp.c b/lib/libfetch/ftp.c
--- a/lib/libfetch/ftp.c
+++ b/lib/libfetch/ftp.c
@@ -148,8 +148,9 @@
fetch_syserr();
return (-1);
}
- if (isftpinfo(conn->buf)) {
- while (conn->buflen && !isftpreply(conn->buf)) {
+
+ if (isftpinfo(conn->line)) {
+ while (rlen && !isftpreply(conn->line)) {
if ((rlen = fetch_getln(conn)) < 0) {
fetch_syserr();
return (-1);
@@ -157,14 +158,14 @@
}
}
- if (!isftpreply(conn->buf)) {
+ if (!isftpreply(conn->line)) {
ftp_seterr(FTP_PROTOCOL_ERROR);
return (-1);
}
- conn->err = (conn->buf[0] - '0') * 100
- + (conn->buf[1] - '0') * 10
- + (conn->buf[2] - '0');
+ conn->err = (conn->line[0] - '0') * 100
+ + (conn->line[1] - '0') * 10
+ + (conn->line[2] - '0');
return (conn->err);
}
@@ -236,8 +237,8 @@
if (conn->err != FTP_WORKING_DIRECTORY &&
conn->err != FTP_FILE_ACTION_OK)
return (FTP_PROTOCOL_ERROR);
- end = conn->buf + conn->buflen;
- src = conn->buf + 4;
+ end = conn->line + conn->linelen;
+ src = conn->line + 4;
if (src >= end || *src++ != '"')
return (FTP_PROTOCOL_ERROR);
for (q = 0, dst = pwd; src < end && pwdlen--; ++src) {
@@ -417,7 +418,7 @@
ftp_seterr(e);
return (-1);
}
- for (ln = conn->buf + 4; *ln && isspace((unsigned char)*ln); ln++)
+ for (ln = conn->line + 4; *ln && isspace((unsigned char)*ln); ln++)
/* nothing */ ;
for (us->size = 0; *ln && isdigit((unsigned char)*ln); ln++)
us->size = us->size * 10 + *ln - '0';
@@ -435,7 +436,7 @@
ftp_seterr(e);
return (-1);
}
- for (ln = conn->buf + 4; *ln && isspace((unsigned char)*ln); ln++)
+ for (ln = conn->line + 4; *ln && isspace((unsigned char)*ln); ln++)
/* nothing */ ;
switch (strspn(ln, "0123456789")) {
case 14:
@@ -688,7 +689,7 @@
* Find address and port number. The reply to the PASV command
* is IMHO the one and only weak point in the FTP protocol.
*/
- ln = conn->buf;
+ ln = conn->line;
switch (e) {
case FTP_PASSIVE_MODE:
case FTP_LPASSIVE_MODE:
diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c
--- a/lib/libfetch/http.c
+++ b/lib/libfetch/http.c
@@ -126,8 +126,7 @@
* I/O functions for decoding chunked streams
*/
-struct httpio
-{
+struct httpio {
conn_t *conn; /* connection */
int chunked; /* chunked mode */
char *buf; /* chunk buffer */
@@ -148,17 +147,14 @@
static int
http_new_chunk(struct httpio *io)
{
- unsigned char *p, *eol;
+ char *p;
if (fetch_getln(io->conn) == -1)
return (-1);
- p = (unsigned char *)io->conn->buf;
- if (io->conn->pos < 2 || !isxdigit(*p))
- return (-1);
-
- eol = (unsigned char *)io->conn->buf + io->conn->pos;
- while (p < eol && *p && !isspace(*p) && *p != ';') {
+ for (p = io->conn->line;
+ *p != '\0' && !isspace((unsigned char)*p) && *p != ';';
+ p++) {
io->chunksize <<= 4;
if (*p >= '0' && *p <= '9')
io->chunksize += *p - '0';
@@ -168,7 +164,6 @@
io->chunksize += 10 + *p - 'a';
else
return (-1);
- p++;
}
#ifndef NDEBUG
@@ -435,9 +430,9 @@
* on finding one, but if we do, insist on it being 1.0 or 1.1.
* We don't care about the reason phrase.
*/
- if (strncmp(conn->buf, "HTTP", 4) != 0)
+ if (conn->linelen < 4 || strncmp(conn->line, "HTTP", 4) != 0)
return (HTTP_PROTOCOL_ERROR);
- p = conn->buf + 4;
+ p = conn->line + 4;
if (*p == '/') {
if (p[1] != '1' || p[2] != '.' || (p[3] != '0' && p[3] != '1'))
return (HTTP_PROTOCOL_ERROR);
@@ -521,17 +516,17 @@
{
unsigned int i, len;
- if (conn->pos == 0 || conn->buf[0] == '\0')
+ if (conn->linelen == 0)
return (hdr_end);
/* Copy the line to the headerbuf */
- if (hbuf->bufsize < conn->pos + 1) {
- if ((hbuf->buf = realloc(hbuf->buf, conn->pos + 1)) == NULL)
+ if (hbuf->bufsize <= conn->linelen) {
+ if ((hbuf->buf = realloc(hbuf->buf, conn->linelen + 1)) == NULL)
return (hdr_syserror);
- hbuf->bufsize = conn->pos + 1;
+ hbuf->bufsize = conn->linelen + 1;
}
- strcpy(hbuf->buf, conn->buf);
- hbuf->buflen = conn->buflen;
+ memcpy(hbuf->buf, conn->line, conn->linelen + 1);
+ hbuf->buflen = conn->linelen;
/*
* Fetch possible continuation lines. Stop at 1st non-continuation
@@ -545,19 +540,19 @@
* Note: we previously considered a pure whitespace line
* equivalent to an empty one. This was incorrect.
*/
- if (conn->buf[0] != ' ' && conn->buf[0] != "\t"[0])
+ if (conn->line[0] != ' ' && conn->line[0] != '\t')
break;
/* Got a continuation line. Concatenate to previous */
- len = hbuf->buflen + conn->buflen;
- if (hbuf->bufsize < len + 1) {
+ len = hbuf->buflen + conn->linelen;
+ if (hbuf->bufsize <= len) {
len *= 2;
if ((hbuf->buf = realloc(hbuf->buf, len + 1)) == NULL)
return (hdr_syserror);
hbuf->bufsize = len + 1;
}
- strcpy(hbuf->buf + hbuf->buflen, conn->buf);
- hbuf->buflen += conn->buflen;
+ memcpy(hbuf->buf + hbuf->buflen, conn->line, conn->linelen + 1);
+ hbuf->buflen += conn->linelen;
}
/*

File Metadata

Mime Type
text/plain
Expires
Tue, Jul 14, 3:42 AM (19 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35020247
Default Alt Text
D58113.id181700.diff (7 KB)

Event Timeline