From: Daniel Stenberg Date: Fri, 22 Aug 2025 13:54:10 +0000 (+0200) Subject: typecheck-gcc: add type checks for curl_multi_setopt() X-Git-Tag: curl-8_16_0~118 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=844c385812efe22f979a9be0dcf75b2ee69b2ef4;p=thirdparty%2Fcurl.git typecheck-gcc: add type checks for curl_multi_setopt() Test 745 verifies that all options are tested. Closes #18357 --- diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h index d053332032..a0b41aeb24 100644 --- a/include/curl/typecheck-gcc.h +++ b/include/curl/typecheck-gcc.h @@ -193,11 +193,68 @@ curl_easy_getinfo(handle, info, arg); \ }) +#define curl_multi_setopt(handle, option, value) \ + __extension__({ \ + if(__builtin_constant_p(option)) { \ + if(curlcheck_long_option(option)) \ + if(!curlcheck_long(value)) \ + _curl_multi_setopt_err_long(); \ + if(curlcheck_off_t_option(option)) \ + if(!curlcheck_off_t(value)) \ + _curl_multi_setopt_err_curl_off_t(); \ + if(curlcheck_multicb_data_option(option)) \ + if(!curlcheck_cb_data(value)) \ + _curl_multi_setopt_err_cb_data(); \ + if(curlcheck_charpp_option(option)) \ + if(!curlcheck_ptrptr(value, char)) \ + _curl_multi_setopt_err_charpp(); \ + if((option) == CURLMOPT_PUSHFUNCTION) \ + if(!curlcheck_multipush_cb(value)) \ + _curl_multi_setopt_err_pushcb(); \ + if((option) == CURLMOPT_SOCKETFUNCTION) \ + if(!curlcheck_multisocket_cb(value)) \ + _curl_multi_setopt_err_socketcb(); \ + if((option) == CURLMOPT_TIMERFUNCTION) \ + if(!curlcheck_multitimer_cb(value)) \ + _curl_multi_setopt_err_timercb(); \ + } \ + curl_multi_setopt(handle, option, value); \ + }) + +/* evaluates to true if the option takes a data argument to pass to a + callback */ +#define curlcheck_multicb_data_option(option) \ + ((option) == CURLMOPT_PUSHDATA || \ + (option) == CURLMOPT_SOCKETDATA || \ + (option) == CURLMOPT_TIMERDATA || \ + 0) + +/* evaluates to true if the option takes a char ** argument */ +#define curlcheck_charpp_option(option) \ + ((option) == CURLMOPT_PIPELINING_SERVER_BL || \ + (option) == CURLMOPT_PIPELINING_SITE_BL || \ + 0) + +/* evaluates to true if expr is of type curl_multi_timer_callback */ +#define curlcheck_multitimer_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_multi_timer_callback)) + +/* evaluates to true if expr is of type curl_socket_callback */ +#define curlcheck_multisocket_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_socket_callback)) + +/* evaluates to true if expr is of type curl_push_callback */ +#define curlcheck_multipush_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_push_callback)) + /* * For now, just make sure that the functions are called with three arguments */ #define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) -#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) + /* the actual warnings, triggered by calling the _curl_easy_setopt_err* * functions */ @@ -208,6 +265,21 @@ __attribute__((__unused__)) __attribute__((__noinline__)) \ id(void) { __asm__(""); } +CURLWARNING(_curl_multi_setopt_err_long, + "curl_multi_setopt expects a long argument") +CURLWARNING(_curl_multi_setopt_err_curl_off_t, + "curl_multi_setopt expects a curl_off_t argument") +CURLWARNING(_curl_multi_setopt_err_cb_data, + "curl_multi_setopt expects a 'void *' argument") +CURLWARNING(_curl_multi_setopt_err_charpp, + "curl_multi_setopt expects a 'char **' argument") +CURLWARNING(_curl_multi_setopt_err_pushcb, + "curl_multi_setopt expects a curl_push_callback argument") +CURLWARNING(_curl_multi_setopt_err_socketcb, + "curl_multi_setopt expects a curl_socket_callback argument") +CURLWARNING(_curl_multi_setopt_err_timercb, + "curl_multi_setopt expects a curl_multi_timer_callback argument") + CURLWARNING(_curl_easy_setopt_err_long, "curl_easy_setopt expects a long argument") CURLWARNING(_curl_easy_setopt_err_curl_off_t, @@ -534,6 +606,14 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t, __builtin_types_compatible_p(__typeof__(expr), type *) || \ __builtin_types_compatible_p(__typeof__(expr), const type *)) +/* evaluates to true if expr is type**, const type** or NULL */ +#define curlcheck_ptrptr(expr, type) \ + (curlcheck_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), type **) || \ + __builtin_types_compatible_p(__typeof__(expr), type *[]) || \ + __builtin_types_compatible_p(__typeof__(expr), const type *[]) || \ + __builtin_types_compatible_p(__typeof__(expr), const type **)) + /* evaluates to true if expr is one of type[], type*, NULL or const type* */ #define curlcheck_arr(expr, type) \ (curlcheck_ptr((expr), type) || \ diff --git a/tests/test745.pl b/tests/test745.pl index 02ed3be5c3..faddda429f 100755 --- a/tests/test745.pl +++ b/tests/test745.pl @@ -60,6 +60,18 @@ sub getinclude { $enum{"CURLOPT_CONV_FROM_UTF8_FUNCTION"}++; $enum{"CURLOPT_CONV_TO_NETWORK_FUNCTION"}++; close($f); + + open(my $f, "<", "$root/include/curl/multi.h") + || die "no curl.h"; + while(<$f>) { + if($_ =~ /\((CURLMOPT[^,]*), (CURLOPTTYPE_[^,]*)/) { + my ($opt, $type) = ($1, $2); + if($type !~ /LONG|OFF_T/) { + $enum{$opt}++; + } + } + } + close($f); } gettypecheck();