I did this
I reproduced this with a UBSan instrumented static build of the current curl master (87704c4) on macOS arm64.
1. Build a UBSan instrumented static libcurl
From the curl source directory:
cmake -S . -B build-ubsan-static \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_BUILD_TYPE=Debug \
-DBUILD_SHARED_LIBS=OFF \
-DBUILD_STATIC_LIBS=ON \
-DBUILD_CURL_EXE=OFF \
-DBUILD_TESTING=OFF \
-DBUILD_EXAMPLES=OFF \
-DCMAKE_C_FLAGS="-O1 -g -fsanitize=undefined -fno-sanitize-recover=undefined -fno-omit-frame-pointer"
Build the static libcurl target:
cmake --build build-ubsan-static \
--target libcurl_static \
-j
The resulting static library was:
build-ubsan-static/lib/libcurl-d.a
2. Create the reproducer
I saved the following as mime_ubsan.c in the curl source directory:
#include <curl/curl.h>
#include <stdint.h>
#include <stdio.h>
static size_t read_cb(char *buffer, size_t size, size_t nitems, void *arg)
{
(void)buffer;
(void)size;
(void)nitems;
(void)arg;
return 0;
}
int main(void)
{
CURL *curl;
curl_mime *mime;
curl_mimepart *part;
CURLcode result;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
mime = curl_mime_init(curl);
part = curl_mime_addpart(mime);
curl_mime_name(part, "data");
curl_mime_data_cb(part, (curl_off_t)INT64_MAX,
read_cb, NULL, NULL, NULL);
curl_mime_encoder(part, "base64");
curl_easy_setopt(curl, CURLOPT_URL,
"http://127.0.0.1:18080/");
curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
result = curl_easy_perform(curl);
fprintf(stderr, "curl_easy_perform: %s\n",
curl_easy_strerror(result));
curl_mime_free(mime);
curl_easy_cleanup(curl);
curl_global_cleanup();
return 0;
}
3. Link the reproducer against the local static libcurl
I placed the build directory first in PKG_CONFIG_PATH so that pkg-config used the libcurl.pc generated by this curl build:
export PKG_CONFIG_PATH="$PWD/build-ubsan-static:/opt/homebrew/lib/pkgconfig:/opt/homebrew/share/pkgconfig"
then:
bash <<'EOF'
set -e
clang \
-O1 \
-g \
-fsanitize=undefined \
-fno-sanitize-recover=undefined \
-fno-omit-frame-pointer \
-DCURL_STATICLIB \
-I"$PWD/include" \
"$PWD/mime_ubsan.c" \
"$PWD/build-ubsan-static/lib/libcurl-d.a" \
-L"$(brew --prefix libunistring)/lib" \
$(pkg-config --static --libs libcurl | sed 's/-lcurl//g') \
-o "$PWD/mime_ubsan"
EOF
4. Run the reproducer
I started a local HTTP server:
python3 -m http.server 18080
In another terminal, I ran:
UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 \
./mime_ubsan
UBSan reported:
/omitted/curl-master/lib/mime.c:430:12:
runtime error: signed integer overflow:
4 * 3074457345618258603 cannot be represented in type
'curl_off_t' (aka 'long')
#0 encoder_base64_size mime.c:430
#1 mime_size mime.c:1597
#2 mime_size mime.c:1592
#3 Curl_creader_set_mime mime.c:2165
#4 Curl_http http.c:3091
#5 multi_runsingle multi.c:2813
#6 multi_perform multi.c:2914
#7 curl_easy_perform easy.c:820
#8 main mime_ubsan.c:36
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior
lib/mime.c:430:12
The overflow occurs in:
size = 4 * (1 + ((size - 1) / 3));
The MIME size is calculated before the read callback is called, so the reproducer does not allocate or transfer INT64_MAX bytes.
I expected the following
The Base64 encoded size calculation should detect that the encoded size cannot be represented by curl_off_t and return an unknown size or an error without performing signed overflowing arithmetic.
curl/libcurl version
curl master (87704c4)
operating system
ProductName: macOS
ProductVersion: 26.5.2
BuildVersion: 25F84
I did this
I reproduced this with a UBSan instrumented static build of the current curl master (87704c4) on macOS arm64.
1. Build a UBSan instrumented static libcurl
From the curl source directory:
Build the static libcurl target:
The resulting static library was:
2. Create the reproducer
I saved the following as
mime_ubsan.cin the curl source directory:3. Link the reproducer against the local static libcurl
I placed the build directory first in
PKG_CONFIG_PATHso thatpkg-configused thelibcurl.pcgenerated by this curl build:then:
4. Run the reproducer
I started a local HTTP server:
In another terminal, I ran:
UBSan reported:
The overflow occurs in:
The MIME size is calculated before the read callback is called, so the reproducer does not allocate or transfer
INT64_MAXbytes.I expected the following
The Base64 encoded size calculation should detect that the encoded size cannot be represented by curl_off_t and return an unknown size or an error without performing signed overflowing arithmetic.
curl/libcurl version
curl master (87704c4)
operating system
ProductName: macOS
ProductVersion: 26.5.2
BuildVersion: 25F84