Fix bugs with Redbean Fetch() uploading

This change makes Fetch() work correctly when large bodies are supplied,
or bodies containing NUL characters are supplied.

Fixes #573
This commit is contained in:
Justine Tunney 2023-01-05 09:50:24 -08:00
parent eb69a42863
commit d73523864a
No known key found for this signature in database
GPG key ID: BE714B4575D6E328

View file

@ -12,13 +12,13 @@ static int LuaFetch(lua_State *L) {
uint32_t ip; uint32_t ip;
struct Url url; struct Url url;
int t, ret, sock, methodidx, hdridx; int t, ret, sock, methodidx, hdridx;
char *host, *port; char *host, *port, *request;
struct TlsBio *bio; struct TlsBio *bio;
struct addrinfo *addr; struct addrinfo *addr;
struct Buffer inbuf; // shadowing intentional struct Buffer inbuf; // shadowing intentional
struct HttpMessage msg; // shadowing intentional struct HttpMessage msg; // shadowing intentional
struct HttpUnchunker u; struct HttpUnchunker u;
const char *urlarg, *request, *body, *method; const char *urlarg, *body, *method;
char *conlenhdr = ""; char *conlenhdr = "";
char *headers = 0; char *headers = 0;
char *hosthdr = 0; char *hosthdr = 0;
@ -26,7 +26,7 @@ static int LuaFetch(lua_State *L) {
char *key, *val, *hdr; char *key, *val, *hdr;
size_t keylen, vallen; size_t keylen, vallen;
size_t urlarglen, requestlen, paylen, bodylen; size_t urlarglen, requestlen, paylen, bodylen;
size_t g, n, hdrsize; size_t i, g, n, hdrsize;
int imethod, numredirects = 0, maxredirects = 5; int imethod, numredirects = 0, maxredirects = 5;
bool followredirect = true; bool followredirect = true;
struct addrinfo hints = {.ai_family = AF_INET, struct addrinfo hints = {.ai_family = AF_INET,
@ -169,15 +169,19 @@ static int LuaFetch(lua_State *L) {
/* /*
* Create HTTP message. * Create HTTP message.
*/ */
request = _gc(xasprintf("%s %s HTTP/1.1\r\n" request = 0;
appendf(&request,
"%s %s HTTP/1.1\r\n"
"Host: %s\r\n" "Host: %s\r\n"
"Connection: close\r\n" "Connection: close\r\n"
"User-Agent: %s\r\n" "User-Agent: %s\r\n"
"%s%s" "%s%s"
"\r\n%s", "\r\n",
method, _gc(EncodeUrl(&url, 0)), hosthdr, agenthdr, method, _gc(EncodeUrl(&url, 0)), hosthdr, agenthdr, conlenhdr,
conlenhdr, headers ? headers : "", body)); headers ? headers : "");
requestlen = strlen(request); appendd(&request, body, bodylen);
requestlen = appendz(request).i;
_gc(request);
/* /*
* Perform DNS lookup. * Perform DNS lookup.
@ -244,20 +248,22 @@ static int LuaFetch(lua_State *L) {
* Send HTTP Message. * Send HTTP Message.
*/ */
DEBUGF("(ftch) client sending %s request", method); DEBUGF("(ftch) client sending %s request", method);
for (i = 0; i < requestlen; i += rc) {
#ifndef UNSECURE #ifndef UNSECURE
if (usingssl) { if (usingssl) {
ret = mbedtls_ssl_write(&sslcli, request, requestlen); rc = mbedtls_ssl_write(&sslcli, request + i, requestlen - i);
if (ret != requestlen) { if (rc <= 0) {
if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) goto VerifyFailed; if (rc == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) goto VerifyFailed;
close(sock); close(sock);
return LuaNilTlsError(L, "write", ret); return LuaNilTlsError(L, "write", rc);
} }
} else } else
#endif #endif
if (WRITE(sock, request, requestlen) != requestlen) { if ((rc = WRITE(sock, request + i, requestlen - i)) <= 0) {
close(sock); close(sock);
return LuaNilError(L, "write error: %s", strerror(errno)); return LuaNilError(L, "write error: %s", strerror(errno));
} }
}
if (logmessages) { if (logmessages) {
LogMessage("sent", request, requestlen); LogMessage("sent", request, requestlen);
} }