I did this
I built the current curl master branch (87704c4) with Clang UBSan and ran curl with --progress-bar, a one-byte upload, and a server response containing Content-Length: 9223372036854775807.
Server:
from http.server import BaseHTTPRequestHandler, HTTPServer
import time
class Handler(BaseHTTPRequestHandler):
def do_POST(self):
self.rfile.read(int(self.headers.get("Content-Length", "0")))
self.send_response(200)
self.send_header("Content-Length", "9223372036854775807")
self.end_headers()
time.sleep(3)
def log_message(self, *args):
pass
HTTPServer(("127.0.0.1", 18080), Handler).handle_request()
Build:
cmake -S . -B build-ubsan -G Ninja \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_C_FLAGS="-O1 -g -fsanitize=undefined -fno-sanitize-recover=undefined -fno-omit-frame-pointer" \
-DCMAKE_EXE_LINKER_FLAGS="-fsanitize=undefined"
cmake --build build-ubsan --target curl
Command:
UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 \
./src/curl --http1.1 --progress-bar --max-time 1 \
--data-binary x http://127.0.0.1:18080/ -o /dev/null
UBSan reports:
runtime error: signed integer overflow: 9223372036854775807 + 1 cannot be represented in type 'curl_off_t' (aka 'long')
#0 0x000100b6a698 in tool_progress_cb tool_cb_prg.c
#1 0x000100e10814 in pgrs_update progress.c:706
#2 0x000100e10d78 in Curl_pgrsCheck progress.c:718
#3 0x000100e31440 in Curl_sendrecv transfer.c:380
#4 0x000100e05488 in multi_runsingle multi.c:2837
#5 0x000100e01f30 in multi_perform multi.c:2914
#6 0x000100dbefec in curl_easy_perform easy.c:820
#7 0x000100b7800c in run_all_transfers tool_operate.c:2341
#8 0x000100b77d0c in operate tool_operate.c:2505
#9 0x000100b77534 in main tool_main.c:189
#10 0x000184983dfc in start+0x1b4c (dyld:arm64+0xbdfc)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /omitted/curl-master/src/tool_cb_prg.c:143:59
[1] 39438 abort UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 ./build-ubsan/src/curl 1
The overflow occurs in the overflow check itself:
else if((CURL_OFF_T_MAX - bar->initial_size) < (dltotal + ultotal))
Here, dltotal is CURL_OFF_T_MAX from the response Content-Length, and ultotal is 1.
I expected the following
The progress-bar size calculation should avoid signed overflow.
curl/libcurl version
curl master branch (87704c4)
operating system
macOS arm64
ProductName: macOS
ProductVersion: 26.5.2
BuildVersion: 25F84
I did this
I built the current curl master branch (87704c4) with Clang UBSan and ran curl with
--progress-bar, a one-byte upload, and a server response containingContent-Length: 9223372036854775807.Server:
Build:
Command:
UBSan reports:
The overflow occurs in the overflow check itself:
Here,
dltotalisCURL_OFF_T_MAXfrom the responseContent-Length, andultotalis1.I expected the following
The progress-bar size calculation should avoid signed overflow.
curl/libcurl version
curl master branch (87704c4)
operating system
macOS arm64
ProductName: macOS
ProductVersion: 26.5.2
BuildVersion: 25F84