Skip to content

Commit

Permalink
Merge pull request #2075 from nghttp2/bump-llhttp
Browse files Browse the repository at this point in the history
Bump llhttp to 48588093ca4219b5f689acfc9ebea9e4c8c37663
  • Loading branch information
tatsuhiro-t committed Feb 16, 2024
2 parents ab8ee3f + 3792c57 commit d2ca281
Show file tree
Hide file tree
Showing 5 changed files with 1,630 additions and 931 deletions.
23 changes: 21 additions & 2 deletions third-party/llhttp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,16 @@ With this flag only a CR is required to terminate such sections.
**Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!**
### `void llhttp_set_lenient_optional_cr_before_lf(llhttp_t* parser, int enabled)`
Enables/disables lenient handling of line separators.
Normally `llhttp` would error when a LF is not preceded by CR when terminating the
request line, the status line, the headers, a chunk header or a chunk data.
With this flag only a LF is required to terminate such sections.
**Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!**
### `void llhttp_set_lenient_optional_crlf_after_chunk(llhttp_t* parser, int enabled)`
Enables/disables lenient handling of chunks not separated via CRLF.
Expand All @@ -373,12 +383,21 @@ With this flag the new chunk can start immediately after the previous one.
**Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!**
### `void llhttp_set_lenient_spaces_after_chunk_size(llhttp_t* parser, int enabled)`
Enables/disables lenient handling of spaces after chunk size.
Normally `llhttp` would error when after a chunk size is followed by one or more spaces are present instead of a CRLF or `;`.
With this flag this check is disabled.
**Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!**
## Build Instructions
Make sure you have [Node.js](https://nodejs.org/), npm and npx installed. Then under project directory run:
```sh
npm install
npm ci
make
```

Expand Down Expand Up @@ -432,7 +451,7 @@ _Note that using the git repo directly (e.g., via a git repo url and tag) will n

1. Ensure that `Clang` and `make` are in your system path.
2. Using Git Bash, clone the repo to your preferred location.
3. Cd into the cloned directory and run `npm install`
3. Cd into the cloned directory and run `npm ci`
5. Run `make`
6. Your `repo/build` directory should now have `libllhttp.a` and `libllhttp.so` static and dynamic libraries.
7. When building your executable, you can link to these libraries. Make sure to set the build folder as an include path when building so you can reference the declarations in `repo/build/llhttp.h`.
Expand Down
44 changes: 38 additions & 6 deletions third-party/llhttp/include/llhttp.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
#define INCLUDE_LLHTTP_H_

#define LLHTTP_VERSION_MAJOR 9
#define LLHTTP_VERSION_MINOR 0
#define LLHTTP_VERSION_PATCH 1
#define LLHTTP_VERSION_MINOR 2
#define LLHTTP_VERSION_PATCH 0

#ifndef INCLUDE_LLHTTP_ITSELF_H_
#define INCLUDE_LLHTTP_ITSELF_H_
Expand All @@ -30,7 +30,7 @@ struct llhttp__internal_s {
uint8_t http_major;
uint8_t http_minor;
uint8_t header_state;
uint8_t lenient_flags;
uint16_t lenient_flags;
uint8_t upgrade;
uint8_t finish;
uint16_t flags;
Expand Down Expand Up @@ -115,7 +115,9 @@ enum llhttp_lenient_flags {
LENIENT_VERSION = 0x10,
LENIENT_DATA_AFTER_CLOSE = 0x20,
LENIENT_OPTIONAL_LF_AFTER_CR = 0x40,
LENIENT_OPTIONAL_CRLF_AFTER_CHUNK = 0x80
LENIENT_OPTIONAL_CRLF_AFTER_CHUNK = 0x80,
LENIENT_OPTIONAL_CR_BEFORE_LF = 0x100,
LENIENT_SPACES_AFTER_CHUNK_SIZE = 0x200
};
typedef enum llhttp_lenient_flags llhttp_lenient_flags_t;

Expand Down Expand Up @@ -179,7 +181,8 @@ enum llhttp_method {
HTTP_SET_PARAMETER = 42,
HTTP_REDIRECT = 43,
HTTP_RECORD = 44,
HTTP_FLUSH = 45
HTTP_FLUSH = 45,
HTTP_QUERY = 46
};
typedef enum llhttp_method llhttp_method_t;

Expand Down Expand Up @@ -360,6 +363,7 @@ typedef enum llhttp_status llhttp_status_t;
XX(31, LINK, LINK) \
XX(32, UNLINK, UNLINK) \
XX(33, SOURCE, SOURCE) \
XX(46, QUERY, QUERY) \


#define RTSP_METHOD_MAP(XX) \
Expand Down Expand Up @@ -426,6 +430,7 @@ typedef enum llhttp_status llhttp_status_t;
XX(43, REDIRECT, REDIRECT) \
XX(44, RECORD, RECORD) \
XX(45, FLUSH, FLUSH) \
XX(46, QUERY, QUERY) \


#define HTTP_STATUS_MAP(XX) \
Expand Down Expand Up @@ -545,6 +550,8 @@ extern "C" {

#if defined(__wasm__)
#define LLHTTP_EXPORT __attribute__((visibility("default")))
#elif defined(_WIN32)
#define LLHTTP_EXPORT __declspec(dllexport)
#else
#define LLHTTP_EXPORT
#endif
Expand Down Expand Up @@ -807,7 +814,7 @@ void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled);
* avoid request smuggling.
* With this flag the extra value will be parsed normally.
*
* **Enabling this flag can pose a security issue since you will be exposed to
* **Enabling this flag can pose a security issue since you will be exposed to
* request smuggling attacks. USE WITH CAUTION!**
*/
LLHTTP_EXPORT
Expand Down Expand Up @@ -850,6 +857,19 @@ void llhttp_set_lenient_data_after_close(llhttp_t* parser, int enabled);
LLHTTP_EXPORT
void llhttp_set_lenient_optional_lf_after_cr(llhttp_t* parser, int enabled);

/*
* Enables/disables lenient handling of line separators.
*
* Normally `llhttp` would error when a LF is not preceded by CR when terminating the
* request line, the status line, the headers, a chunk header or a chunk data.
* With this flag only a LF is required to terminate such sections.
*
* **Enabling this flag can pose a security issue since you will be exposed to
* request smuggling attacks. USE WITH CAUTION!**
*/
LLHTTP_EXPORT
void llhttp_set_lenient_optional_cr_before_lf(llhttp_t* parser, int enabled);

/* Enables/disables lenient handling of chunks not separated via CRLF.
*
* Normally `llhttp` would error when after a chunk data a CRLF is missing before
Expand All @@ -862,6 +882,18 @@ void llhttp_set_lenient_optional_lf_after_cr(llhttp_t* parser, int enabled);
LLHTTP_EXPORT
void llhttp_set_lenient_optional_crlf_after_chunk(llhttp_t* parser, int enabled);

/* Enables/disables lenient handling of spaces after chunk size.
*
* Normally `llhttp` would error when after a chunk size is followed by one or more
* spaces are present instead of a CRLF or `;`.
* With this flag this check is disabled.
*
* **Enabling this flag can pose a security issue since you will be exposed to
* request smuggling attacks. USE WITH CAUTION!**
*/
LLHTTP_EXPORT
void llhttp_set_lenient_spaces_after_chunk_size(llhttp_t* parser, int enabled);

#ifdef __cplusplus
} /* extern "C" */
#endif
Expand Down
18 changes: 17 additions & 1 deletion third-party/llhttp/src/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ void llhttp_reset(llhttp_t* parser) {
llhttp_type_t type = parser->type;
const llhttp_settings_t* settings = parser->settings;
void* data = parser->data;
uint8_t lenient_flags = parser->lenient_flags;
uint16_t lenient_flags = parser->lenient_flags;

llhttp__internal_init(parser);

Expand Down Expand Up @@ -315,6 +315,22 @@ void llhttp_set_lenient_optional_crlf_after_chunk(llhttp_t* parser, int enabled)
}
}

void llhttp_set_lenient_optional_cr_before_lf(llhttp_t* parser, int enabled) {
if (enabled) {
parser->lenient_flags |= LENIENT_OPTIONAL_CR_BEFORE_LF;
} else {
parser->lenient_flags &= ~LENIENT_OPTIONAL_CR_BEFORE_LF;
}
}

void llhttp_set_lenient_spaces_after_chunk_size(llhttp_t* parser, int enabled) {
if (enabled) {
parser->lenient_flags |= LENIENT_SPACES_AFTER_CHUNK_SIZE;
} else {
parser->lenient_flags &= ~LENIENT_SPACES_AFTER_CHUNK_SIZE;
}
}

/* Callbacks */


Expand Down
26 changes: 23 additions & 3 deletions third-party/llhttp/src/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,33 @@ int llhttp__after_headers_complete(llhttp_t* parser, const char* p,
int hasBody;

hasBody = parser->flags & F_CHUNKED || parser->content_length > 0;
if (parser->upgrade && (parser->method == HTTP_CONNECT ||
(parser->flags & F_SKIPBODY) || !hasBody)) {
if (
(parser->upgrade && (parser->method == HTTP_CONNECT ||
(parser->flags & F_SKIPBODY) || !hasBody)) ||
/* See RFC 2616 section 4.4 - 1xx e.g. Continue */
(parser->type == HTTP_RESPONSE && parser->status_code == 101)
) {
/* Exit, the rest of the message is in a different protocol. */
return 1;
}

if (parser->flags & F_SKIPBODY) {
if (parser->type == HTTP_RESPONSE && parser->status_code == 100) {
/* No body, restart as the message is complete */
return 0;
}

/* See RFC 2616 section 4.4 */
if (
parser->flags & F_SKIPBODY || /* response to a HEAD request */
(
parser->type == HTTP_RESPONSE && (
parser->status_code == 102 || /* Processing */
parser->status_code == 103 || /* Early Hints */
parser->status_code == 204 || /* No Content */
parser->status_code == 304 /* Not Modified */
)
)
) {
return 0;
} else if (parser->flags & F_CHUNKED) {
/* chunked encoding - ignore Content-Length header, prepare for a chunk */
Expand Down

0 comments on commit d2ca281

Please sign in to comment.