Skip to content

Undefined behavior in curl_share_setopt() UNSHARE path: bit shift before validation #21224

@bird

Description

@bird

I did this

Called curl_share_setopt() with CURLSHOPT_UNSHARE and an out-of-range type value:

#include <curl/curl.h>
int main(void) {
    CURLSH *share = curl_share_init();
    curl_share_setopt(share, CURLSHOPT_UNSHARE, 32);
    curl_share_cleanup(share);
}

To reproduce (libcurl must be built with UBSan — system libcurl won't show the issue):

git clone --branch curl-8_19_0 --depth 1 https://github.com/curl/curl.git && cd curl
autoreconf -fi
CC=gcc CFLAGS="-fsanitize=undefined -g -O1" LDFLAGS="-fsanitize=undefined" \
  ./configure --disable-shared --without-ssl --without-libpsl \
  --without-brotli --without-zstd --without-nghttp2 \
  --without-libidn2 --without-librtmp --disable-ldap
make -j$(nproc)

gcc -fsanitize=undefined -g -I include test.c lib/.libs/libcurl.a -lz -lpthread -o test
./test

I expected the following

No undefined behavior. The SHARE path in the same function validates type inside the switch before using it in a bit shift. The UNSHARE path at line 150 evaluates 1 << type before the switch validates the value. When type >= 32, this is UB per the C standard.

UBSan output:

curl_share.c:150:43: runtime error: shift exponent 32 is too large for 32-bit type 'int'
    #0 curl_share_setopt /lib/curl_share.c:150
    #1 main /test_share_ub.c:47

The fix is to move the bit shift after the switch, matching the SHARE path's validate-then-shift pattern. Not a security issue- type is developer-supplied, not from untrusted input.

curl/libcurl version

curl 8.19.0 (also confirmed on current HEAD)

operating system

Linux 6.19.11-1-cachyos x86_64

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions