From 6f3166c15b7fc951b10ba7cb2607527065264f0e Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Tue, 18 Mar 2008 08:14:37 +0000 Subject: - Added curl_easy_getinfo typechecker. - Added macros for curl_share_setopt and curl_multi_setopt to check at least the correct number of arguments. --- CHANGES | 6 ++++ RELEASE-NOTES | 9 +++--- include/curl/curl.h | 7 +++-- include/curl/typecheck-gcc.h | 75 ++++++++++++++++++++++++++++++++++++++------ lib/easy.c | 1 + lib/multi.c | 1 + lib/share.c | 1 + 7 files changed, 85 insertions(+), 15 deletions(-) diff --git a/CHANGES b/CHANGES index 4a424581f..f8245c6b2 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,12 @@ Changelog +Michal Marek (18 Mar 2008) +- Added curl_easy_getinfo typechecker. + +- Added macros for curl_share_setopt and curl_multi_setopt to check at least + the correct number of arguments. + Daniel Fandrich (13 Mar 2008) - Added tests 622-625 to test SFTP/SCP uploads. Test 625 was an attempt to reproduce the --ftp-create-dirs problem reported by Brian Ulm, but that diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 02d4c36ed..64e13b642 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -17,10 +17,11 @@ This release includes the following changes: o the test509-style setting URL in callback is officially no longer supported o support a full chain of certificates in a given PKCS12 certificate o resumed transfers work with SFTP - o added a type checking macro for curl_easy_setopt(), watch out for new - warnings in code using libcurl (needs gcc-4.3 and currently only works - in C mode) - o curl_easy_setopt() uses are now checked to use three arguments + o added type checking macros for curl_easy_setopt() and curl_easy_getinfo(), + watch out for new warnings in code using libcurl (needs gcc-4.3 and + currently only works in C mode) + o curl_easy_setopt(), curl_easy_getinfo(), curl_share_setopt() and + curl_multi_setopt() uses are now checked to use exactly three arguments This release includes the following bugfixes: diff --git a/include/curl/curl.h b/include/curl/curl.h index 4af714291..b4ed5d0f0 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -1798,9 +1798,12 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); #else #if defined(__STDC__) && (__STDC__ >= 1) /* This preprocessor magic that replaces a call with the exact same call is - only done to make sure application authors use exactly three arguments - to this function. */ + only done to make sure application authors pass exactly three arguments + to these functions. */ #define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param) +#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg) +#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) #endif /* __STDC__ >= 1 */ #endif /* gcc >= 4.3 && !__cplusplus */ diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h index c6475b735..969e2bbe4 100644 --- a/include/curl/typecheck-gcc.h +++ b/include/curl/typecheck-gcc.h @@ -76,10 +76,10 @@ __extension__ ({ \ if (_curl_is_postfields_option(_curl_opt) && !_curl_is_postfields(value)) \ _curl_easy_setopt_err_postfields(); \ if ((_curl_opt) == CURLOPT_HTTPPOST && \ - !_curl_is_ptr((value), struct curl_httppost)) \ + !_curl_is_arr((value), struct curl_httppost)) \ _curl_easy_setopt_err_curl_httpost(); \ if (_curl_is_slist_option(_curl_opt) && \ - !_curl_is_ptr((value), struct curl_slist)) \ + !_curl_is_arr((value), struct curl_slist)) \ _curl_easy_setopt_err_curl_slist(); \ if ((_curl_opt) == CURLOPT_SHARE && !_curl_is_ptr((value), CURLSH)) \ _curl_easy_setopt_err_CURLSH(); \ @@ -87,10 +87,37 @@ __extension__ ({ \ curl_easy_setopt(handle, _curl_opt, value); \ }) +/* wraps curl_easy_getinfo() with typechecking */ +/* FIXME: don't allow const pointers */ +#define curl_easy_getinfo(handle, info, arg) \ +__extension__ ({ \ + __typeof__ (info) _curl_info = info; \ + if (__builtin_constant_p(_curl_info)) { \ + if (_curl_is_string_info(_curl_info) && !_curl_is_arr((arg), char *)) \ + _curl_easy_getinfo_err_string(); \ + if (_curl_is_long_info(_curl_info) && !_curl_is_arr((arg), long)) \ + _curl_easy_getinfo_err_long(); \ + if (_curl_is_double_info(_curl_info) && !_curl_is_arr((arg), double)) \ + _curl_easy_getinfo_err_double(); \ + if (_curl_is_slist_info(_curl_info) && \ + !_curl_is_arr((arg), struct curl_slist *)) \ + _curl_easy_getinfo_err_curl_slist(); \ + } \ + curl_easy_getinfo(handle, _curl_info, arg); \ +}) + +/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(), + * 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 */ -/* To define a new warning, use _CURL_WARNING(identifier, "message"); */ +/* To define a new warning, use _CURL_WARNING(identifier, "message") */ #define _CURL_WARNING(id, message) \ static void __attribute__((warning(message))) __attribute__((unused)) \ __attribute__((noinline)) id(void) { __asm__(""); } @@ -136,7 +163,16 @@ _CURL_WARNING(_curl_easy_setopt_err_curl_slist, _CURL_WARNING(_curl_easy_setopt_err_CURLSH, "curl_easy_setopt expects a CURLSH* argument for this option") -/* groups of options that take the same type of argument */ +_CURL_WARNING(_curl_easy_getinfo_err_string, + "curl_easy_getinfo expects a pointer to char * for this info") +_CURL_WARNING(_curl_easy_getinfo_err_long, + "curl_easy_getinfo expects a pointer to long for this info") +_CURL_WARNING(_curl_easy_getinfo_err_double, + "curl_easy_getinfo expects a pointer to double for this info") +_CURL_WARNING(_curl_easy_getinfo_err_curl_slist, + "curl_easy_getinfo expects a pointer to struct curl_slist * for this info") + +/* groups of curl_easy_setops options that take the same type of argument */ /* To add a new option to one of the groups, just add * (option) == CURLOPT_SOMETHING @@ -230,13 +266,34 @@ _CURL_WARNING(_curl_easy_setopt_err_CURLSH, (option) == CURLOPT_TELNETOPTIONS || \ 0) +/* groups of curl_easy_getinfo infos that take the same type of argument */ + +/* evaluates to true if info expects a pointer to char * argument */ +#define _curl_is_string_info(info) \ + (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG) + +/* evaluates to true if info expects a pointer to long argument */ +#define _curl_is_long_info(info) \ + (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE) + +/* evaluates to true if info expects a pointer to double argument */ +#define _curl_is_double_info(info) \ + (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST) + +/* evaluates to true if info expects a pointer to struct curl_slist * argument */ +#define _curl_is_slist_info(info) \ + (CURLINFO_SLIST < (info)) + + /* typecheck helpers -- check whether given expression has requested type*/ -/* For pointers, you can use the _curl_is_ptr macro, otherwise define a new - * macro. Search for __builtin_types_compatible_p in the GCC manual. NOTE: - * these macros MUST NOT EVALUATE their arguments! The argument is the actual - * expression passed to the curl_easy_setopt macro. This means that you can - * only apply the sizeof and __typeof__ operators, no == or whatsoever. +/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros, + * otherwise define a new macro. Search for __builtin_types_compatible_p + * in the GCC manual. + * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is + * the actual expression passed to the curl_easy_setopt macro. This + * means that you can only apply the sizeof and __typeof__ operators, no + * == or whatsoever. */ /* XXX: should evaluate to true iff expr is a pointer */ diff --git a/lib/easy.c b/lib/easy.c index 018aeab6e..cfa6c41b1 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -548,6 +548,7 @@ void Curl_easy_initHandleData(struct SessionHandle *data) * curl_easy_getinfo() is an external interface that allows an app to retrieve * information from a performed transfer and similar. */ +#undef curl_easy_getinfo CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...) { va_list arg; diff --git a/lib/multi.c b/lib/multi.c index a29b6a0ae..73e8e7e3d 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -1778,6 +1778,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi, return result; } +#undef curl_multi_setopt CURLMcode curl_multi_setopt(CURLM *multi_handle, CURLMoption option, ...) { diff --git a/lib/share.c b/lib/share.c index eb2ee78ce..3a5f072bd 100644 --- a/lib/share.c +++ b/lib/share.c @@ -46,6 +46,7 @@ curl_share_init(void) return share; } +#undef curl_share_setopt CURLSHcode curl_share_setopt(CURLSH *sh, CURLSHoption option, ...) { -- cgit v1.2.3