WebRequestBuffer::RequestComplete fixed

master
Steffen Pohle 3 weeks ago
parent 8e3ca2fb34
commit 58ff5bee62

@ -1,5 +1,9 @@
Version 0.4:
=============
2026-06-09:
- WebRequestBuffer::RequestComplete did not check the content lenght and the
data size correctly.
2026-04-19:
- JSONElement: adding SetArray function to create an valid empty array

@ -18,7 +18,7 @@ noconfig: help
endif
all: dep $(TARGET) test-udp test-tcpserver test-tcpclient test-ssl test-json test-webserver test-getrandom test-base64
all: dep $(TARGET) test-udp test-tcpserver test-tcpclient test-ssl test-json test-webserver test-getrandom test-base64 test-webbuffer
-include .depend
@ -58,6 +58,9 @@ test-udp: $(TARGET) test-udp.o
test-json: $(TARGET) test-json.o
$(CXX) test-json.o -o $@ -lUDPTCPNetwork -L./ -I./ $(LDFLAGS)
test-webbuffer: $(TARGET) test-webbuffer.o
$(CXX) test-webbuffer.o -o $@ -lUDPTCPNetwork -L./ -I./ $(LDFLAGS)
keygen:
# openssl req -nodes -new -newkey rsa:2048 -sha256 -out csr.pem -keyout privkey.pem
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout privkey.pem -out cert.pem
@ -89,6 +92,7 @@ clean:
rm test-tcpclient -rf
rm test-webserver -rf
rm test-getrandom -rf
rm test-webbuffer -rf
rm test-base64 -rf
rm test-json -rf
rm test-udp -rf

@ -13,6 +13,10 @@ enum { // request types
WEB_REQUEST_UNSUPPORTED,
WEB_REQUEST_GET,
WEB_REQUEST_POST,
WEB_REQUEST_PUT,
WEB_REQUEST_PATCH,
WEB_REQUEST_DELETE,
WEB_REQUEST_HEAD,
WEB_REQUEST_MAX // not set
};
@ -45,13 +49,14 @@ class WebRequestBuffer {
std::string protocol_version;
std::list<WebHeaderLine> headerlines;
int buffer_pos_data;
public:
WebRequestBuffer();
~WebRequestBuffer();
int AddBuffer (char *b, int len);
int GetBuffer (char **dstptr, int *max);
int GetBuffer (char **dstptr, int *max); // get the current buffer (incl. Headers), resize if needed
int GetData (char **dstptr, int *max); // get the data part of the buffer, resize if needed
bool RequestComplete();
void Clear() { buffer_len = 0; };
int GetType() { return request_type; };

@ -0,0 +1,66 @@
#include <string>
#include "UDPTCPNetwork.h"
int test_fragmentedbuffer() {
std::string buf1;
WebRequestBuffer buffer;
buffer.Clear();
buf1 = "POST /get/newvalues HTTP/1.1\r\n";
buf1 += "Host: localhost:11001\r\n";
buf1 += "Connection: keep-alive\r\n";
buf1 += "Content-Length: 20\r\n";
buf1 += "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36\r\n";
buf1 += "Accept: *//*\r\n";
buf1 += "Origin: http://localhost:11001\r\n";
buf1 += "Sec-Fetch-Site: same-origin\r\n";
buf1 += "Referer: http://localhost:11001/index.html\r\n";
buf1 += "Accept-Encoding: gzip, deflate, br, zstd\r\n";
buf1 += "Accept-Language: de-DE,de;q=0.9,en-DE;q=0.8,en;q=0.7,en-US;q=0.6\r\n";
buf1 += "\r\n";
buffer.AddBuffer((char*)buf1.c_str(), strlen(buf1.c_str()));
if (buffer.RequestComplete()) {
debug ("header added: request is marked as complete but it isn't");
return 0;
};
buf1 = "0123456789";
buffer.AddBuffer((char*)buf1.c_str(), strlen(buf1.c_str()));
if (buffer.RequestComplete()) {
char *ptr = NULL;
int max = 0;
debug ("first 10 bytes: request is marked as complete but it isn't");
buffer.GetBuffer(&ptr, &max);
debug ("buffer:'%s'", ptr);
return 0;
};
buf1 = "0123456789";
buffer.AddBuffer((char*)buf1.c_str(), strlen(buf1.c_str()));
if (!buffer.RequestComplete()) {
char *ptr = NULL;
int max = 0;
debug ("second 10 bytes: request is not marked as complete but it is");
buffer.GetBuffer(&ptr, &max);
debug ("buffer:'%s'", ptr);
return 0;
};
return 1;
};
int main(int argc, char** argv) {
debug ("test: buffer with fragmented header and content");
if (!test_fragmentedbuffer()) exit(1);
debug ("all tests passed");
return 0;
};

@ -34,7 +34,7 @@ WebRequestBuffer::~WebRequestBuffer () {
/// @return 0 on error, 1 on success
int WebRequestBuffer::AddBuffer (char *buffer, int len) {
//
// if needed allocate enought buffer, to the next kB
// if needed allocate enought buffer, to the next kB, add 1 for the null termination.
if (buffer_ptr == NULL || buffer_size <= buffer_len+len) {
buffer_size = 1024 * (1 + ((buffer_len + len) / 1024));
if (buffer_ptr == NULL) buffer_ptr = (char*) malloc (buffer_size);
@ -49,15 +49,14 @@ int WebRequestBuffer::AddBuffer (char *buffer, int len) {
memcpy (buffer_ptr + buffer_len, buffer, len);
buffer_len += len;
buffer_ptr[buffer_len] = 0;
// debug("buffer:'%s'\n", buffer_ptr);
if (buffer_len >= buffer_size) errorexit ("buffer_size < buffer_len");
return 1;
};
/// @brief copy the current buffer to the destination, resize destination if needed
/// @brief the buffer includes the header and the data part, use GetData to get only the data part
/// @param dstptr pointer to the destination pointer, in case of a reallocation
/// @param max pointer to current allocated size of the pointer
/// @return > 0 - len in bytes of the buffer, = -1 error occured
@ -70,10 +69,10 @@ int WebRequestBuffer::GetBuffer (char **dstptr, int *max) {
}
// check: size and reallocate
if (*max < buffer_len || *max < 0) {
char *tb = (char*) realloc (*dstptr, buffer_len);
if (*max < buffer_len+1 || *max < 0) {
*max = (1024*(1+((buffer_len+1)/1024)));
char *tb = (char*) realloc (*dstptr, (*max));
*dstptr = tb;
*max = buffer_size;
}
// check: could alloc memory
@ -88,8 +87,41 @@ int WebRequestBuffer::GetBuffer (char **dstptr, int *max) {
};
/// @brief copy the data part of the buffer to the destination, resize destination if needed
/// @param dstptr pointer to the destination pointer, in case of a reallocation
/// @param max pointer to current allocated size of the pointer
/// @return > 0 - len in bytes of the buffer, = -1 error occured
int WebRequestBuffer::GetData (char **dstptr, int *max) {
// check: valid pointers
if (dstptr == NULL || max == NULL) {
fprintf (stderr, "%s:%d no pointer to buffer or no pointer to a lenght set\n",
__FILE__, __LINE__);
return -1;
}
// check: size and reallocate
if (*max < buffer_len+1 || *max < 0) {
*max = (1024*(1+((buffer_len+1)/1024)));
char *tb = (char*) realloc (*dstptr, (*max));
*dstptr = tb;
}
// check: could alloc memory
if (*dstptr == NULL) {
fprintf (stderr, "%s:%d no destination pointer set\n",
__FILE__, __LINE__);
return -1;
}
memcpy (*dstptr, buffer_ptr + buffer_pos_data, buffer_len - buffer_pos_data);
return buffer_len - buffer_pos_data;
};
/// @brief Check if the Request is Complete. In this case the request_type and the request can
/// @brief be read with GetRequest and GetType(). For a new request Clear() must be called.
/// @brief The request is complete if the header is complete and if the content length is reached (if content length is set).
/// @return 0 . not complete, 1 . request complete
bool WebRequestBuffer::RequestComplete() {
int i = 0;
@ -111,7 +143,7 @@ bool WebRequestBuffer::RequestComplete() {
if (buffer_ptr[i] == '\n') {
if (hl.value.length() == 0 && hl.parameter.length() == 0) {
buffer_pos_data = i+1; // save position of first data byte
return true;
break;
}
// the first line holds the request type and the location/path.
@ -119,6 +151,10 @@ bool WebRequestBuffer::RequestComplete() {
hl.parameter = string_to_upper(hl.parameter);
if (hl.parameter.compare("GET") == 0) request_type = WEB_REQUEST_GET;
if (hl.parameter.compare("POST") == 0) request_type = WEB_REQUEST_POST;
if (hl.parameter.compare("PUT") == 0) request_type = WEB_REQUEST_PUT;
if (hl.parameter.compare("PATCH") == 0) request_type = WEB_REQUEST_PATCH;
if (hl.parameter.compare("DELETE") == 0) request_type = WEB_REQUEST_DELETE;
if (hl.parameter.compare("HEAD") == 0) request_type = WEB_REQUEST_HEAD;
request = string_to_lower(hl.value);
}
@ -143,7 +179,21 @@ bool WebRequestBuffer::RequestComplete() {
}
}
return false;
// abort if no header end was found, or unsuppoerted request type
if (buffer_pos_data == -1) return false;
if (request_type == WEB_REQUEST_UNSUPPORTED) return false;
// check if content length is set and if the content is complete
if (request_type == WEB_REQUEST_POST || request_type == WEB_REQUEST_PUT || request_type == WEB_REQUEST_PATCH) {
std::string cl = GetHeader("Content-Length");
if (cl.length() == 0) return false; // content length is missing, request is not complete
i = atoi(cl.c_str());
if (i == 0) return true; // no content, request is complete
if (buffer_len - buffer_pos_data == i) return true; // content length is reached, request is complete
return false;
}
return true; // for GET, DELETE, HEAD there is no content, so the request is complete
}

Loading…
Cancel
Save