Make that in batch
This commit is contained in:
+36
-8
@@ -203,17 +203,43 @@ private:
|
|||||||
((x > 96) & (x < '{'));
|
((x > 96) & (x < '{'));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool hasLess(uint64_t word) {
|
static inline uint64_t hasLess(uint64_t x, uint64_t n) {
|
||||||
return (word - ~0UL / 255 * 32) & ~word & ~0UL / 255 * 128;
|
return (((x)-~0UL/255*(n))&~(x)&~0UL/255*128);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint64_t hasMore(uint64_t x, uint64_t n) {
|
||||||
|
return (((x)+~0UL/255*(127-(n))|(x))&~0UL/255*128);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint64_t hasBetween(uint64_t x, uint64_t m, uint64_t n) {
|
||||||
|
return ((~0UL/255*(127+(n))-((x)&~0UL/255*127)&~(x)&((x)&~0UL/255*127)+~0UL/255*(127-(m)))&~0UL/255*128);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool notFieldNameWord(uint64_t x) {
|
||||||
|
return hasLess(x, '-') |
|
||||||
|
hasBetween(x, '-', '0') |
|
||||||
|
hasBetween(x, '9', 'A') |
|
||||||
|
hasBetween(x, 'Z', 'a') |
|
||||||
|
hasMore(x, 'z');
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *consumeFieldName(char *p) {
|
||||||
|
for (; true; p += 8) {
|
||||||
|
if (notFieldNameWord(*(uint64_t *)p)) {
|
||||||
|
while (isFieldNameByte(*(unsigned char *)p)) p++;
|
||||||
|
return (void *)p;
|
||||||
|
}
|
||||||
|
(*(uint64_t *)p) |= 0x2020202020202020ull;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RFC 9110: 5.5 Field Values (TLDR; anything above 31 is allowed; htab (9) is also allowed)
|
/* RFC 9110: 5.5 Field Values (TLDR; anything above 31 is allowed; htab (9) is also allowed)
|
||||||
* Field values are usually constrained to the range of US-ASCII characters [...]
|
* Field values are usually constrained to the range of US-ASCII characters [...]
|
||||||
* Field values containing CR, LF, or NUL characters are invalid and dangerous [...]
|
* Field values containing CR, LF, or NUL characters are invalid and dangerous [...]
|
||||||
* Field values containing other CTL characters are also invalid. */
|
* Field values containing other CTL characters are also invalid. */
|
||||||
static inline void *find_less(char *p, char */*end*/) {
|
static inline void *tryConsumeFieldValue(char *p) {
|
||||||
for (; true; p += 8) {
|
for (; true; p += 8) {
|
||||||
if (hasLess(*(uint64_t *)p)) {
|
if (hasLess(*(uint64_t *)p), 32) {
|
||||||
while (*(unsigned char *)p > 31) p++;
|
while (*(unsigned char *)p > 31) p++;
|
||||||
return (void *)p;
|
return (void *)p;
|
||||||
}
|
}
|
||||||
@@ -250,9 +276,11 @@ private:
|
|||||||
* which is then removed, and our counters to flip due to overflow and we end up with a crash */
|
* which is then removed, and our counters to flip due to overflow and we end up with a crash */
|
||||||
|
|
||||||
for (unsigned int i = 0; i < HttpRequest::MAX_HEADERS - 1; i++) {
|
for (unsigned int i = 0; i < HttpRequest::MAX_HEADERS - 1; i++) {
|
||||||
/* Lower case and short scan until ':', or stop at \r (from previous scan) */
|
/* Lower case and consume the field name */
|
||||||
for (preliminaryKey = postPaddedBuffer; isFieldNameByte(*postPaddedBuffer); *(postPaddedBuffer++) |= 32);
|
preliminaryKey = postPaddedBuffer;
|
||||||
|
postPaddedBuffer = (char *) consumeFieldName(postPaddedBuffer);
|
||||||
headers->key = std::string_view(preliminaryKey, (size_t) (postPaddedBuffer - preliminaryKey));
|
headers->key = std::string_view(preliminaryKey, (size_t) (postPaddedBuffer - preliminaryKey));
|
||||||
|
|
||||||
/* Assume colon, space follows (this is fine as we have at least 2 bytes past) */
|
/* Assume colon, space follows (this is fine as we have at least 2 bytes past) */
|
||||||
if (postPaddedBuffer[0] == ':' && postPaddedBuffer[1] == ' ') {
|
if (postPaddedBuffer[0] == ':' && postPaddedBuffer[1] == ' ') {
|
||||||
postPaddedBuffer += 2;
|
postPaddedBuffer += 2;
|
||||||
@@ -265,9 +293,9 @@ private:
|
|||||||
for (; (*postPaddedBuffer == ':' || *(unsigned char *)postPaddedBuffer < 33) && *postPaddedBuffer != '\r'; postPaddedBuffer++);
|
for (; (*postPaddedBuffer == ':' || *(unsigned char *)postPaddedBuffer < 33) && *postPaddedBuffer != '\r'; postPaddedBuffer++);
|
||||||
}
|
}
|
||||||
preliminaryValue = postPaddedBuffer;
|
preliminaryValue = postPaddedBuffer;
|
||||||
/* The goal of this call is to find next "\r\n", fast */
|
/* The goal of this call is to find next "\r\n", or any invalid field value chars, fast */
|
||||||
retry:
|
retry:
|
||||||
postPaddedBuffer = (char *) find_less(postPaddedBuffer, end);
|
postPaddedBuffer = (char *) tryConsumeFieldValue(postPaddedBuffer);
|
||||||
/* If this is not CR then we caught some stinky invalid char on the way */
|
/* If this is not CR then we caught some stinky invalid char on the way */
|
||||||
if (postPaddedBuffer[0] != '\r') {
|
if (postPaddedBuffer[0] != '\r') {
|
||||||
/* If TAB then keep searching */
|
/* If TAB then keep searching */
|
||||||
|
|||||||
Reference in New Issue
Block a user