From d7242f4757de67f02b13fac850c3472598f999ca Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 2 Mar 2020 07:42:54 +0100 Subject: Revert "mime: do not perform more than one read in a row" This reverts commit ed0f357f7d25566110d4302f33759f4ffb5a6f83. --- lib/mime.c | 196 ++++++++++++++++--------------------------------------------- 1 file changed, 49 insertions(+), 147 deletions(-) (limited to 'lib/mime.c') diff --git a/lib/mime.c b/lib/mime.c index 7d754e63b..5f928a171 100644 --- a/lib/mime.c +++ b/lib/mime.c @@ -26,7 +26,6 @@ #include "mime.h" #include "non-ascii.h" -#include "warnless.h" #include "urldata.h" #include "sendf.h" @@ -53,10 +52,6 @@ #define READ_ERROR ((size_t) -1) -#define STOP_FILLING ((size_t) -2) - -static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems, - void *instream, bool *hasread); /* Encoders. */ static size_t encoder_nop_read(char *buffer, size_t size, bool ateof, @@ -359,15 +354,10 @@ static size_t encoder_nop_read(char *buffer, size_t size, bool ateof, (void) ateof; - if(!size) - return STOP_FILLING; - if(size > insize) size = insize; - if(size) memcpy(buffer, st->buf, size); - st->bufbeg += size; return size; } @@ -387,9 +377,6 @@ static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof, (void) ateof; - if(!size) - return STOP_FILLING; - if(size > cursize) size = cursize; @@ -417,11 +404,8 @@ static size_t encoder_base64_read(char *buffer, size_t size, bool ateof, /* Line full ? */ if(st->pos > MAX_ENCODED_LINE_LENGTH - 4) { /* Yes, we need 2 characters for CRLF. */ - if(size < 2) { - if(!cursize) - return STOP_FILLING; + if(size < 2) break; - } *ptr++ = '\r'; *ptr++ = '\n'; st->pos = 0; @@ -430,12 +414,7 @@ static size_t encoder_base64_read(char *buffer, size_t size, bool ateof, } /* Be sure there is enough space and input data for a base64 group. */ - if(size < 4) { - if(!cursize) - return STOP_FILLING; - break; - } - if(st->bufend - st->bufbeg < 3) + if(size < 4 || st->bufend - st->bufbeg < 3) break; /* Encode three bytes as four characters. */ @@ -452,31 +431,25 @@ static size_t encoder_base64_read(char *buffer, size_t size, bool ateof, } /* If at eof, we have to flush the buffered data. */ - if(ateof) { - if(size < 4) { - if(!cursize) - return STOP_FILLING; - } - else { - /* Buffered data size can only be 0, 1 or 2. */ - ptr[2] = ptr[3] = '='; - i = 0; - switch(st->bufend - st->bufbeg) { - case 2: - i = (st->buf[st->bufbeg + 1] & 0xFF) << 8; - /* FALLTHROUGH */ - case 1: - i |= (st->buf[st->bufbeg] & 0xFF) << 16; - ptr[0] = base64[(i >> 18) & 0x3F]; - ptr[1] = base64[(i >> 12) & 0x3F]; - if(++st->bufbeg != st->bufend) { - ptr[2] = base64[(i >> 6) & 0x3F]; - st->bufbeg++; - } - cursize += 4; - st->pos += 4; - break; + if(ateof && size >= 4) { + /* Buffered data size can only be 0, 1 or 2. */ + ptr[2] = ptr[3] = '='; + i = 0; + switch(st->bufend - st->bufbeg) { + case 2: + i = (st->buf[st->bufbeg + 1] & 0xFF) << 8; + /* FALLTHROUGH */ + case 1: + i |= (st->buf[st->bufbeg] & 0xFF) << 16; + ptr[0] = base64[(i >> 18) & 0x3F]; + ptr[1] = base64[(i >> 12) & 0x3F]; + if(++st->bufbeg != st->bufend) { + ptr[2] = base64[(i >> 6) & 0x3F]; + st->bufbeg++; } + cursize += 4; + st->pos += 4; + break; } } @@ -608,11 +581,8 @@ static size_t encoder_qp_read(char *buffer, size_t size, bool ateof, } /* If the output buffer would overflow, do not store. */ - if(len > size) { - if(!cursize) - return STOP_FILLING; + if(len > size) break; - } /* Append to output buffer. */ memcpy(ptr, buf, len); @@ -642,18 +612,16 @@ static size_t mime_mem_read(char *buffer, size_t size, size_t nitems, void *instream) { curl_mimepart *part = (curl_mimepart *) instream; - size_t sz = curlx_sotouz(part->datasize - part->state.offset); + size_t sz = (size_t) part->datasize - part->state.offset; (void) size; /* Always 1.*/ - if(!nitems) - return STOP_FILLING; - if(sz > nitems) sz = nitems; if(sz) - memcpy(buffer, part->data + curlx_sotouz(part->state.offset), sz); + memcpy(buffer, (char *) &part->data[part->state.offset], sz); + part->state.offset += sz; return sz; } @@ -673,7 +641,7 @@ static int mime_mem_seek(void *instream, curl_off_t offset, int whence) if(offset < 0 || offset > part->datasize) return CURL_SEEKFUNC_FAIL; - part->state.offset = offset; + part->state.offset = (size_t) offset; return CURL_SEEKFUNC_OK; } @@ -700,9 +668,6 @@ static size_t mime_file_read(char *buffer, size_t size, size_t nitems, { curl_mimepart *part = (curl_mimepart *) instream; - if(!nitems) - return STOP_FILLING; - if(mime_open_file(part)) return READ_ERROR; @@ -746,16 +711,15 @@ static size_t readback_bytes(mime_state *state, const char *trail) { size_t sz; - size_t offset = curlx_sotouz(state->offset); - if(numbytes > offset) { - sz = numbytes - offset; - bytes += offset; + if(numbytes > state->offset) { + sz = numbytes - state->offset; + bytes += state->offset; } else { size_t tsz = strlen(trail); - sz = offset - numbytes; + sz = state->offset - numbytes; if(sz >= tsz) return 0; bytes = trail + sz; @@ -772,7 +736,7 @@ static size_t readback_bytes(mime_state *state, /* Read a non-encoded part content. */ static size_t read_part_content(curl_mimepart *part, - char *buffer, size_t bufsize, bool *hasread) + char *buffer, size_t bufsize) { size_t sz = 0; @@ -781,70 +745,26 @@ static size_t read_part_content(curl_mimepart *part, case CURL_READFUNC_ABORT: case CURL_READFUNC_PAUSE: case READ_ERROR: - return part->lastreadstatus; - default: - break; - } - - /* If we can determine we are at end of part data, spare a read. */ - if(part->datasize != (curl_off_t) -1 && - part->state.offset >= part->datasize) { - /* sz is already zero. */ - } - else { - switch(part->kind) { - case MIMEKIND_MULTIPART: - /* - * Cannot be processed as other kinds since read function requires - * an additional parameter and is highly recursive. - */ - sz = mime_subparts_read(buffer, 1, bufsize, part->arg, hasread); - break; - case MIMEKIND_FILE: - if(part->fp && feof(part->fp)) - break; /* At EOF. */ - /* FALLTHROUGH */ - default: - if(part->readfunc) { - if(!(part->flags & MIME_FAST_READ)) { - if(*hasread) - return STOP_FILLING; - *hasread = TRUE; - } - sz = part->readfunc(buffer, 1, bufsize, part->arg); - } - break; - } - } - - switch(sz) { - case STOP_FILLING: - break; - case 0: - case CURL_READFUNC_ABORT: - case CURL_READFUNC_PAUSE: - case READ_ERROR: - part->lastreadstatus = sz; break; default: - part->state.offset += sz; + if(part->readfunc) + sz = part->readfunc(buffer, 1, bufsize, part->arg); part->lastreadstatus = sz; break; } - - return sz; + return part->lastreadstatus; } /* Read and encode part content. */ -static size_t read_encoded_part_content(curl_mimepart *part, char *buffer, - size_t bufsize, bool *hasread) +static size_t read_encoded_part_content(curl_mimepart *part, + char *buffer, size_t bufsize) { mime_encoder_state *st = &part->encstate; size_t cursize = 0; size_t sz; bool ateof = FALSE; - for(;;) { + while(bufsize) { if(st->bufbeg < st->bufend || ateof) { /* Encode buffered data. */ sz = part->encoder->encodefunc(buffer, bufsize, ateof, part); @@ -853,8 +773,9 @@ static size_t read_encoded_part_content(curl_mimepart *part, char *buffer, if(ateof) return cursize; break; + case CURL_READFUNC_ABORT: + case CURL_READFUNC_PAUSE: case READ_ERROR: - case STOP_FILLING: return cursize? cursize: sz; default: cursize += sz; @@ -876,7 +797,7 @@ static size_t read_encoded_part_content(curl_mimepart *part, char *buffer, if(st->bufend >= sizeof(st->buf)) return cursize? cursize: READ_ERROR; /* Buffer full. */ sz = read_part_content(part, st->buf + st->bufend, - sizeof(st->buf) - st->bufend, hasread); + sizeof(st->buf) - st->bufend); switch(sz) { case 0: ateof = TRUE; @@ -884,7 +805,6 @@ static size_t read_encoded_part_content(curl_mimepart *part, char *buffer, case CURL_READFUNC_ABORT: case CURL_READFUNC_PAUSE: case READ_ERROR: - case STOP_FILLING: return cursize? cursize: sz; default: st->bufend += sz; @@ -892,12 +812,12 @@ static size_t read_encoded_part_content(curl_mimepart *part, char *buffer, } } - /* NOTREACHED */ + return cursize; } /* Readback a mime part. */ static size_t readback_part(curl_mimepart *part, - char *buffer, size_t bufsize, bool *hasread) + char *buffer, size_t bufsize) { size_t cursize = 0; #ifdef CURL_DOES_CONVERSIONS @@ -956,9 +876,9 @@ static size_t readback_part(curl_mimepart *part, break; case MIMESTATE_CONTENT: if(part->encoder) - sz = read_encoded_part_content(part, buffer, bufsize, hasread); + sz = read_encoded_part_content(part, buffer, bufsize); else - sz = read_part_content(part, buffer, bufsize, hasread); + sz = read_part_content(part, buffer, bufsize); switch(sz) { case 0: mimesetstate(&part->state, MIMESTATE_END, NULL); @@ -971,7 +891,6 @@ static size_t readback_part(curl_mimepart *part, case CURL_READFUNC_ABORT: case CURL_READFUNC_PAUSE: case READ_ERROR: - case STOP_FILLING: return cursize? cursize: sz; } break; @@ -1000,9 +919,9 @@ static size_t readback_part(curl_mimepart *part, return cursize; } -/* Readback from mime. Warning: not a read callback function. */ +/* Readback from mime. */ static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems, - void *instream, bool *hasread) + void *instream) { curl_mime *mime = (curl_mime *) instream; size_t cursize = 0; @@ -1023,7 +942,7 @@ static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems, #endif mimesetstate(&mime->state, MIMESTATE_BOUNDARY1, mime->firstpart); /* The first boundary always follows the header termination empty line, - so is always preceded by a CRLF. We can then spare 2 characters + so is always preceded by a CRLK. We can then spare 2 characters by skipping the leading CRLF in boundary. */ mime->state.offset += 2; break; @@ -1053,12 +972,11 @@ static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems, mimesetstate(&mime->state, MIMESTATE_END, NULL); break; } - sz = readback_part(part, buffer, nitems, hasread); + sz = readback_part(part, buffer, nitems); switch(sz) { case CURL_READFUNC_ABORT: case CURL_READFUNC_PAUSE: case READ_ERROR: - case STOP_FILLING: return cursize? cursize: sz; case 0: #ifdef CURL_DOES_CONVERSIONS @@ -1166,7 +1084,6 @@ static void cleanup_part_content(curl_mimepart *part) part->datasize = (curl_off_t) 0; /* No size yet. */ cleanup_encoder_state(&part->encstate); part->kind = MIMEKIND_NONE; - part->flags &= ~MIME_FAST_READ; part->lastreadstatus = 1; /* Successful read status. */ } @@ -1424,7 +1341,6 @@ CURLcode curl_mime_data(curl_mimepart *part, part->readfunc = mime_mem_read; part->seekfunc = mime_mem_seek; part->freefunc = mime_mem_free; - part->flags |= MIME_FAST_READ; part->kind = MIMEKIND_DATA; } @@ -1599,7 +1515,7 @@ CURLcode Curl_mime_set_subparts(curl_mimepart *part, } subparts->parent = part; - /* Subparts are processed internally: no read callback. */ + part->readfunc = mime_subparts_read; part->seekfunc = mime_subparts_seek; part->freefunc = take_ownership? mime_subparts_free: mime_subparts_unbind; part->arg = subparts; @@ -1621,23 +1537,9 @@ CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts) size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream) { curl_mimepart *part = (curl_mimepart *) instream; - size_t ret; - bool hasread; (void) size; /* Always 1. */ - - do { - hasread = FALSE; - ret = readback_part(part, buffer, nitems, &hasread); - /* - * If this is not possible to get some data without calling more than - * one read callback (probably because a content encoder is not able to - * deliver a new bunch for the few data accumulated so far), force another - * read until we get enough data or a special exit code. - */ - } while(ret == STOP_FILLING); - - return ret; + return readback_part(part, buffer, nitems); } /* Rewind mime stream. */ -- cgit v1.2.1