Skip to content

Commit f240774

Browse files
ShogunPandaRafaelGSS
authored andcommitted
http: stricter Transfer-Encoding and header separator parsing
Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com> PR-URL: nodejs-private/node-private#315 CVE-ID: CVE-2022-32215,CVE-2022-32214,CVE-2022-32212
1 parent dc7af13 commit f240774

11 files changed

+1037
-460
lines changed

deps/llhttp/CMakeLists.txt

+89-27
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,115 @@
11
cmake_minimum_required(VERSION 3.5.1)
22
cmake_policy(SET CMP0069 NEW)
33

4-
project(llhttp C)
4+
project(llhttp VERSION 6.0.5)
5+
include(GNUInstallDirs)
56

67
set(CMAKE_C_STANDARD 99)
78

9+
# By default build in relwithdebinfo type, supports both lowercase and uppercase
10+
if(NOT CMAKE_CONFIGURATION_TYPES)
11+
set(allowableBuileTypes DEBUG RELEASE RELWITHDEBINFO MINSIZEREL)
12+
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${allowableBuileTypes}")
13+
if(NOT CMAKE_BUILD_TYPE)
14+
set(CMAKE_BUILD_TYPE RELWITHDEBINFO CACHE STRING "" FORCE)
15+
else()
16+
string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE)
17+
if(NOT CMAKE_BUILD_TYPE IN_LIST allowableBuileTypes)
18+
message(FATEL_ERROR "Invalid build type: ${CMAKE_BUILD_TYPE}")
19+
endif()
20+
endif()
21+
endif()
22+
823
#
924
# Options
1025
#
1126
# Generic option
12-
option(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so) instead of static ones (.lib/.a)" OFF)
27+
option(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so)" ON)
28+
option(BUILD_STATIC_LIBS "Build static libraries (.lib/.a)" OFF)
1329

1430
# Source code
1531
set(LLHTTP_SOURCES
16-
src/llhttp.c
17-
src/http.c
18-
src/api.c
32+
${CMAKE_CURRENT_SOURCE_DIR}/src/llhttp.c
33+
${CMAKE_CURRENT_SOURCE_DIR}/src/http.c
34+
${CMAKE_CURRENT_SOURCE_DIR}/src/api.c
1935
)
2036

2137
set(LLHTTP_HEADERS
22-
include/llhttp.h
38+
${CMAKE_CURRENT_SOURCE_DIR}/include/llhttp.h
2339
)
2440

25-
add_library(llhttp)
26-
add_library(llhttp::llhttp ALIAS llhttp)
41+
configure_file(
42+
${CMAKE_CURRENT_SOURCE_DIR}/libllhttp.pc.in
43+
${CMAKE_CURRENT_SOURCE_DIR}/libllhttp.pc
44+
@ONLY
45+
)
2746

28-
target_sources(llhttp PRIVATE ${LLHTTP_SOURCES} ${LLHTTP_HEADERS})
47+
function(config_library target)
48+
target_sources(${target} PRIVATE ${LLHTTP_SOURCES} ${LLHTTP_HEADERS})
2949

30-
# On windows with Visual Studio, add a debug postfix so that release
31-
# and debug libraries can coexist.
32-
if(MSVC)
33-
set(CMAKE_DEBUG_POSTFIX "d")
34-
endif()
50+
target_include_directories(${target} PRIVATE
51+
${CMAKE_CURRENT_SOURCE_DIR}/include
52+
)
3553

36-
target_include_directories(llhttp PUBLIC
37-
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
38-
$<INSTALL_INTERFACE:include>
39-
)
54+
set_target_properties(${target} PROPERTIES
55+
OUTPUT_NAME llhttp
56+
VERSION ${PROJECT_VERSION}
57+
SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
58+
PUBLIC_HEADER ${LLHTTP_HEADERS}
59+
)
4060

41-
set_target_properties(llhttp PROPERTIES PUBLIC_HEADER ${LLHTTP_HEADERS})
61+
install(TARGETS ${target}
62+
EXPORT llhttp
63+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
64+
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
65+
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
66+
)
4267

43-
install(TARGETS llhttp
44-
EXPORT llhttp
45-
ARCHIVE DESTINATION lib
46-
PUBLIC_HEADER DESTINATION include/
47-
)
68+
install(FILES
69+
${CMAKE_CURRENT_SOURCE_DIR}/libllhttp.pc
70+
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
71+
)
4872

49-
# This is required to work with FetchContent
50-
install(EXPORT llhttp
73+
# This is required to work with FetchContent
74+
install(EXPORT llhttp
5175
FILE llhttp-config.cmake
5276
NAMESPACE llhttp::
53-
DESTINATION lib/cmake/llhttp)
77+
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/llhttp)
78+
endfunction(config_library target)
79+
80+
if(BUILD_SHARED_LIBS)
81+
add_library(llhttp_shared SHARED
82+
${llhttp_src}
83+
)
84+
add_library(llhttp::llhttp ALIAS llhttp_shared)
85+
config_library(llhttp_shared)
86+
endif()
87+
88+
if(BUILD_STATIC_LIBS)
89+
add_library(llhttp_static STATIC
90+
${llhttp_src}
91+
)
92+
if(BUILD_SHARED_LIBS)
93+
add_library(llhttp::llhttp ALIAS llhttp_shared)
94+
else()
95+
add_library(llhttp::llhttp ALIAS llhttp_static)
96+
endif()
97+
config_library(llhttp_static)
98+
endif()
99+
100+
# On windows with Visual Studio, add a debug postfix so that release
101+
# and debug libraries can coexist.
102+
if(MSVC)
103+
set(CMAKE_DEBUG_POSTFIX "d")
104+
endif()
105+
106+
# Print project configure summary
107+
message(STATUS "")
108+
message(STATUS "")
109+
message(STATUS "Project configure summary:")
110+
message(STATUS "")
111+
message(STATUS " CMake build type .................: ${CMAKE_BUILD_TYPE}")
112+
message(STATUS " Install prefix ...................: ${CMAKE_INSTALL_PREFIX}")
113+
message(STATUS " Build shared library .............: ${BUILD_SHARED_LIBS}")
114+
message(STATUS " Build static library .............: ${BUILD_STATIC_LIBS}")
115+
message(STATUS "")

deps/llhttp/README.md

+33-3
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,16 @@ if (err == HPE_OK) {
9090
parser.reason);
9191
}
9292
```
93-
For more information on API usage, please refer to [src/native/api.h](https://github.com/nodejs/llhttp/blob/master/src/native/api.h).
93+
For more information on API usage, please refer to [src/native/api.h](https://github.com/nodejs/llhttp/blob/main/src/native/api.h).
94+
95+
## Build Instructions
96+
97+
Make sure you have [Node.js](https://nodejs.org/), npm and npx installed. Then under project directory run:
98+
99+
```sh
100+
npm install
101+
make
102+
```
94103

95104
---
96105

@@ -99,20 +108,41 @@ For more information on API usage, please refer to [src/native/api.h](https://gi
99108
* Python: [pallas/pyllhttp][8]
100109
* Ruby: [metabahn/llhttp][9]
101110

102-
103111
### Using with CMake
104112

105113
If you want to use this library in a CMake project you can use the snippet below.
106114

107115
```
108116
FetchContent_Declare(llhttp
109-
URL "https://github.com/nodejs/llhttp/releases/download/v6.0.4/llhttp-release-v6.0.4.tar.gz") # Using version 6.0.4
117+
URL "https://github.com/nodejs/llhttp/releases/download/v6.0.5/llhttp-release-v6.0.5.tar.gz") # Using version 6.0.5
110118
111119
FetchContent_MakeAvailable(llhttp)
112120
113121
target_link_libraries(${EXAMPLE_PROJECT_NAME} ${PROJECT_LIBRARIES} llhttp ${PROJECT_NAME})
114122
```
115123

124+
## Building on Windows
125+
126+
### Installation
127+
128+
* `choco install git`
129+
* `choco install node`
130+
* `choco install llvm` (or install the `C++ Clang tools for Windows` optional package from the Visual Studio 2019 installer)
131+
* `choco install make` (or if you have MinGW, it comes bundled)
132+
133+
1. Ensure that `Clang` and `make` are in your system path.
134+
2. Using Git Bash, clone the repo to your preferred location.
135+
3. Cd into the cloned directory and run `npm install`
136+
5. Run `make`
137+
6. Your `repo/build` directory should now have `libllhttp.a` and `libllhttp.so` static and dynamic libraries.
138+
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`.
139+
140+
### A simple example on linking with the library:
141+
142+
Assuming you have an executable `main.cpp` in your current working directory, you would run: `clang++ -Os -g3 -Wall -Wextra -Wno-unused-parameter -I/path/to/llhttp/build main.cpp /path/to/llhttp/build/libllhttp.a -o main.exe`.
143+
144+
If you are getting `unresolved external symbol` linker errors you are likely attempting to build `llhttp.c` without linking it with object files from `api.c` and `http.c`.
145+
116146
#### LICENSE
117147

118148
This software is licensed under the MIT License.

deps/llhttp/include/llhttp.h

+18-6
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
#define LLHTTP_VERSION_MAJOR 6
55
#define LLHTTP_VERSION_MINOR 0
6-
#define LLHTTP_VERSION_PATCH 6
6+
#define LLHTTP_VERSION_PATCH 7
77

88
#ifndef LLHTTP_STRICT_MODE
99
# define LLHTTP_STRICT_MODE 0
@@ -59,6 +59,7 @@ enum llhttp_errno {
5959
HPE_OK = 0,
6060
HPE_INTERNAL = 1,
6161
HPE_STRICT = 2,
62+
HPE_CR_EXPECTED = 25,
6263
HPE_LF_EXPECTED = 3,
6364
HPE_UNEXPECTED_CONTENT_LENGTH = 4,
6465
HPE_CLOSED_CONNECTION = 5,
@@ -100,7 +101,8 @@ typedef enum llhttp_flags llhttp_flags_t;
100101
enum llhttp_lenient_flags {
101102
LENIENT_HEADERS = 0x1,
102103
LENIENT_CHUNKED_LENGTH = 0x2,
103-
LENIENT_KEEP_ALIVE = 0x4
104+
LENIENT_KEEP_ALIVE = 0x4,
105+
LENIENT_TRANSFER_ENCODING = 0x8
104106
};
105107
typedef enum llhttp_lenient_flags llhttp_lenient_flags_t;
106108

@@ -172,6 +174,7 @@ typedef enum llhttp_method llhttp_method_t;
172174
XX(0, OK, OK) \
173175
XX(1, INTERNAL, INTERNAL) \
174176
XX(2, STRICT, STRICT) \
177+
XX(25, CR_EXPECTED, CR_EXPECTED) \
175178
XX(3, LF_EXPECTED, LF_EXPECTED) \
176179
XX(4, UNEXPECTED_CONTENT_LENGTH, UNEXPECTED_CONTENT_LENGTH) \
177180
XX(5, CLOSED_CONNECTION, CLOSED_CONNECTION) \
@@ -374,8 +377,6 @@ LLHTTP_EXPORT
374377
void llhttp_init(llhttp_t* parser, llhttp_type_t type,
375378
const llhttp_settings_t* settings);
376379

377-
#if defined(__wasm__)
378-
379380
LLHTTP_EXPORT
380381
llhttp_t* llhttp_alloc(llhttp_type_t type);
381382

@@ -400,8 +401,6 @@ int llhttp_get_status_code(llhttp_t* parser);
400401
LLHTTP_EXPORT
401402
uint8_t llhttp_get_upgrade(llhttp_t* parser);
402403

403-
#endif // defined(__wasm__)
404-
405404
/* Reset an already initialized parser back to the start state, preserving the
406405
* existing parser type, callback settings, user data, and lenient flags.
407406
*/
@@ -556,6 +555,19 @@ void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled);
556555
*/
557556
void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled);
558557

558+
/* Enables/disables lenient handling of `Transfer-Encoding` header.
559+
*
560+
* Normally `llhttp` would error when a `Transfer-Encoding` has `chunked` value
561+
* and another value after it (either in a single header or in multiple
562+
* headers whose value are internally joined using `, `).
563+
* This is mandated by the spec to reliably determine request body size and thus
564+
* avoid request smuggling.
565+
* With this flag the extra value will be parsed normally.
566+
*
567+
* **(USE AT YOUR OWN RISK)**
568+
*/
569+
void llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled);
570+
559571
#ifdef __cplusplus
560572
} /* extern "C" */
561573
#endif

deps/llhttp/libllhttp.pc.in

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
prefix=@CMAKE_INSTALL_PREFIX@
2+
exec_prefix=@CMAKE_INSTALL_PREFIX@
3+
libdir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@
4+
includedir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@
5+
6+
Name: libllhttp
7+
Description: Node.js llhttp Library
8+
Version: @PROJECT_VERSION@
9+
Libs: -L${libdir} -lllhttp
10+
Cflags: -I${includedir}

deps/llhttp/src/api.c

+8
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,14 @@ void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled) {
253253
}
254254
}
255255

256+
void llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled) {
257+
if (enabled) {
258+
parser->lenient_flags |= LENIENT_TRANSFER_ENCODING;
259+
} else {
260+
parser->lenient_flags &= ~LENIENT_TRANSFER_ENCODING;
261+
}
262+
}
263+
256264
/* Callbacks */
257265

258266

deps/llhttp/src/http.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ int llhttp__after_headers_complete(llhttp_t* parser, const char* p,
5252
return 2;
5353
} else if (parser->flags & F_TRANSFER_ENCODING) {
5454
if (parser->type == HTTP_REQUEST &&
55-
(parser->lenient_flags & LENIENT_CHUNKED_LENGTH) == 0) {
55+
(parser->lenient_flags & LENIENT_CHUNKED_LENGTH) == 0 &&
56+
(parser->lenient_flags & LENIENT_TRANSFER_ENCODING) == 0) {
5657
/* RFC 7230 3.3.3 */
5758

5859
/* If a Transfer-Encoding header field

0 commit comments

Comments
 (0)