mirror of
https://github.com/ading2210/libcurl.js.git
synced 2025-05-11 13:30:01 -04:00
fix possible double free when requests get aborted
This commit is contained in:
parent
11795d2772
commit
31e4e25f82
7 changed files with 41 additions and 8 deletions
|
@ -1,5 +1,10 @@
|
|||
# Libcurl.js Changelog:
|
||||
|
||||
## v0.6.9 (4/30/24):
|
||||
- Fix a possible double free when requests get aborted
|
||||
- Handle `ReadableStream` objects as the request payload
|
||||
- Support the Clang AddressSanitizer
|
||||
|
||||
## v0.6.8 (4/30/24):
|
||||
- Add support for relative URLs in HTTP sessions
|
||||
- Better error handling for invalid URLs
|
||||
|
|
|
@ -59,8 +59,11 @@ sudo apt install make cmake emscripten autoconf automake libtool pkg-config wget
|
|||
The build script will generate `client/out/libcurl.js` as well as `client/out/libcurl.mjs`, which is an ES6 module. You can supply the following arguments to the build script to control the build:
|
||||
- `release` - Use all optimizations.
|
||||
- `single_file` - Include the WASM binary in the outputted JS using base64.
|
||||
- `asan` - Use the Clang AddressSanitizer to catch possible memory bugs
|
||||
- `all` - Build twice, once normally, and once as a single file.
|
||||
|
||||
Note: non-release builds will have the `-dev` version suffix and ASan builds will have the `-asan` suffix.
|
||||
|
||||
## Javascript API:
|
||||
|
||||
### Importing the Library:
|
||||
|
|
|
@ -28,7 +28,7 @@ EXPORTED_FUNCS="${EXPORTED_FUNCS:1}"
|
|||
#compile options
|
||||
RUNTIME_METHODS="addFunction,removeFunction,allocate,ALLOC_NORMAL"
|
||||
COMPILER_OPTIONS="-o $MODULE_FILE -lcurl -lwolfssl -lcjson -lz -lbrotlidec -lbrotlicommon -lnghttp2 -I $INCLUDE_DIR -L $LIB_DIR"
|
||||
EMSCRIPTEN_OPTIONS="-lwebsocket.js -sENVIRONMENT=worker,web -sASSERTIONS=1 -sLLD_REPORT_UNDEFINED -sALLOW_TABLE_GROWTH -sALLOW_MEMORY_GROWTH -sEXPORTED_FUNCTIONS=$EXPORTED_FUNCS -sEXPORTED_RUNTIME_METHODS=$RUNTIME_METHODS"
|
||||
EMSCRIPTEN_OPTIONS="-lwebsocket.js -sENVIRONMENT=worker,web -sASSERTIONS=1 -sLLD_REPORT_UNDEFINED -sALLOW_TABLE_GROWTH -sALLOW_MEMORY_GROWTH -sNO_EXIT_RUNTIME -sEXPORTED_FUNCTIONS=$EXPORTED_FUNCS -sEXPORTED_RUNTIME_METHODS=$RUNTIME_METHODS"
|
||||
|
||||
#clean output dir
|
||||
rm -rf $OUT_DIR
|
||||
|
@ -50,8 +50,13 @@ if [[ "$*" == *"release"* ]]; then
|
|||
COMPILER_OPTIONS="-Oz -flto $COMPILER_OPTIONS"
|
||||
echo "note: building with release optimizations"
|
||||
else
|
||||
COMPILER_OPTIONS="$COMPILER_OPTIONS --profiling -g"
|
||||
EMSCRIPTEN_OPTIONS="$EMSCRIPTEN_OPTIONS -sSTACK_OVERFLOW_CHECK=2 -sSAFE_HEAP=1"
|
||||
COMPILER_OPTIONS="$COMPILER_OPTIONS --profiling -g "
|
||||
EMSCRIPTEN_OPTIONS="$EMSCRIPTEN_OPTIONS -sSTACK_OVERFLOW_CHECK=2"
|
||||
fi
|
||||
|
||||
if [[ "$*" == *"asan"* ]]; then
|
||||
COMPILER_OPTIONS="$COMPILER_OPTIONS -fsanitize=address"
|
||||
echo "note: building with asan, performance will suffer"
|
||||
fi
|
||||
|
||||
if [[ "$*" == *"single_file"* ]]; then
|
||||
|
@ -78,6 +83,8 @@ rm $MODULE_FILE
|
|||
|
||||
#add version number and copyright notice
|
||||
VERSION=$(cat package.json | jq -r '.version')
|
||||
[[ "$*" != *"release"* ]] && VERSION="$VERSION-dev"
|
||||
[[ "$*" == *"asan"* ]] && VERSION="$VERSION-asan"
|
||||
sed -i "s/__library_version__/$VERSION/" $OUT_FILE
|
||||
WISP_VERSION=$(cat $WISP_CLIENT/package.json | jq -r '.version')
|
||||
sed -i "s/__wisp_version__/$WISP_VERSION/" $OUT_FILE
|
||||
|
|
|
@ -41,9 +41,9 @@ class HTTPSession extends CurlSession {
|
|||
|
||||
request_async(url, params, body) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let http_handle;
|
||||
let http_handle = null;
|
||||
let body_ptr = null;
|
||||
|
||||
|
||||
let headers_callback = (stream) => {
|
||||
let response_json = c_func_str(_http_get_info, [http_handle]);
|
||||
let response = this.constructor.create_response(stream, JSON.parse(response_json));
|
||||
|
@ -59,6 +59,12 @@ class HTTPSession extends CurlSession {
|
|||
_free(body_ptr);
|
||||
body_ptr = null;
|
||||
}
|
||||
if (http_handle == null) {
|
||||
//a race condition with aborting requests may lead to this state
|
||||
//if the request gets cancelled right before it finishes normally, this function gets called twice
|
||||
//fortunately, we can just return here to prevent anything bad from happening
|
||||
return;
|
||||
}
|
||||
if (error > 0) {
|
||||
error_msg(`Request "${url}" failed with error code ${error}: ${get_error_str(error)}`);
|
||||
reject(`Request failed with error code ${error}: ${get_error_str(error)}`);
|
||||
|
@ -70,6 +76,7 @@ class HTTPSession extends CurlSession {
|
|||
reject("Request failed because redirects were disallowed.");
|
||||
}
|
||||
this.remove_request(http_handle);
|
||||
http_handle = null;
|
||||
}
|
||||
|
||||
body_ptr = body ? allocate_array(body) : null;
|
||||
|
@ -94,9 +101,15 @@ class HTTPSession extends CurlSession {
|
|||
params.headers = params.headers || Object.fromEntries(resource.headers);
|
||||
params.method = params.method || resource.method;
|
||||
}
|
||||
else {
|
||||
else if (typeof url === "string" || url instanceof String) {
|
||||
url = (new URL(url, this.base_url)).href;
|
||||
}
|
||||
else if (url instanceof URL) {
|
||||
url = url.href;
|
||||
}
|
||||
else {
|
||||
url = "" + url;
|
||||
}
|
||||
let body = await this.constructor.create_options(params);
|
||||
return await this.request_async(url, params, body);
|
||||
}
|
||||
|
|
|
@ -166,6 +166,8 @@ class CurlSession {
|
|||
}
|
||||
catch (e) {
|
||||
//the readable stream has been closed elsewhere, so cancel the request
|
||||
if (aborted) return;
|
||||
aborted = true;
|
||||
if (e instanceof TypeError) {
|
||||
end_callback(-1);
|
||||
}
|
||||
|
|
|
@ -110,4 +110,7 @@ char* http_get_info(CURL* http_handle) {
|
|||
cJSON_Delete(response_json);
|
||||
|
||||
return response_json_str;
|
||||
}
|
||||
}
|
||||
|
||||
//the address sanitizer falsely flags any malloc operation as a memory leak
|
||||
const char* __asan_default_options() { return "detect_leaks=false"; }
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "libcurl.js",
|
||||
"version": "0.6.8",
|
||||
"version": "0.6.9",
|
||||
"description": "An experimental port of libcurl to WebAssembly for use in the browser.",
|
||||
"main": "libcurl.mjs",
|
||||
"exports": {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue