Reject chunk size overflow, non-hex chunk size

This commit is contained in:
Alex Hultman
2022-10-31 18:58:01 +01:00
parent 3cfad3584b
commit 399204dbae
2 changed files with 27 additions and 5 deletions
+21 -5
View File
@@ -32,6 +32,12 @@ namespace uWS {
constexpr uint32_t STATE_HAS_SIZE = 0x80000000;
constexpr uint32_t STATE_IS_CHUNKED = 0x40000000;
constexpr uint32_t STATE_SIZE_MASK = 0x3FFFFFFF;
constexpr uint32_t STATE_IS_ERROR = 0xFFFFFFFF;
constexpr uint32_t STATE_SIZE_OVERFLOW = 0x0F000000;
inline unsigned int chunkSize(unsigned int state) {
return state & STATE_SIZE_MASK;
}
/* Reads hex number until CR or out of data to consume. Updates state. Returns bytes consumed. */
inline void consumeHexNumber(std::string_view &data, unsigned int &state) {
@@ -45,10 +51,17 @@ namespace uWS {
digit = (unsigned char) (digit - ('A' - ':'));
}
unsigned int number = ((unsigned int) digit - (unsigned int) '0');
if (number > 16 || (chunkSize(state) & STATE_SIZE_OVERFLOW)) {
state = STATE_IS_ERROR;
return;
}
// extract state bits
unsigned int bits = /*state &*/ STATE_IS_CHUNKED;
state = (state & STATE_SIZE_MASK) * 16u + ((unsigned int) digit - (unsigned int) '0');
state = (state & STATE_SIZE_MASK) * 16u + number;
state |= bits;
data.remove_prefix(1);
@@ -65,10 +78,6 @@ namespace uWS {
}
}
inline unsigned int chunkSize(unsigned int state) {
return state & STATE_SIZE_MASK;
}
inline void decChunkSize(unsigned int &state, unsigned int by) {
//unsigned int bits = state & STATE_IS_CHUNKED;
@@ -87,6 +96,10 @@ namespace uWS {
return state & ~STATE_SIZE_MASK;
}
inline bool isParsingInvalidChunkedEncoding(unsigned int state) {
return state == STATE_IS_ERROR;
}
/* Returns next chunk (empty or not), or if all data was consumed, nullopt is returned. */
static std::optional<std::string_view> getNextChunk(std::string_view &data, unsigned int &state, bool trailer = false) {
@@ -115,6 +128,9 @@ namespace uWS {
if (!hasChunkSize(state)) {
consumeHexNumber(data, state);
if (isParsingInvalidChunkedEncoding(state)) {
return std::nullopt;
}
if (hasChunkSize(state) && chunkSize(state) == 2) {
//printf("Setting state to trailer-parsing and emitting empty chunk\n");
+6
View File
@@ -481,6 +481,9 @@ private:
for (auto chunk : uWS::ChunkIterator(&dataToConsume, &remainingStreamingBytes)) {
dataHandler(user, chunk, chunk.length() == 0);
}
if (isParsingInvalidChunkedEncoding(remainingStreamingBytes)) {
return {0, FULLPTR};
}
unsigned int consumed = (length - (unsigned int) dataToConsume.length());
data = (char *) dataToConsume.data();
length = (unsigned int) dataToConsume.length();
@@ -530,6 +533,9 @@ public:
for (auto chunk : uWS::ChunkIterator(&dataToConsume, &remainingStreamingBytes)) {
dataHandler(user, chunk, chunk.length() == 0);
}
if (isParsingInvalidChunkedEncoding(remainingStreamingBytes)) {
return FULLPTR;
}
data = (char *) dataToConsume.data();
length = (unsigned int) dataToConsume.length();
} else {