From 3b057d4b7a7e6b811245fd03121b428c8940dc60 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 21 Aug 2024 14:58:57 +0200 Subject: [PATCH] test1521: verify setting options to NULL better Previously this test allowed several error values when setting options. This made this test miss #14629. Now, errors are generally not accepted for setopts: - numerical setopts accept CURLE_BAD_FUNCTION_ARGUMENT for funny input - the first setopt to an option accepts CURLE_NOT_BUILT_IN or CURLE_UNKNOWN_OPTION for when they are disabled/not built-in - there is an allowlist concept for some return code for some variables, managed at the top of the mk-lib1521.pl script In curl.h: remove the OBSOLETE named values from the setopt list. Closes #14634 --- include/curl/curl.h | 7 +- lib/setopt.c | 22 ++- lib/url.c | 3 +- lib/urldata.h | 4 + tests/data/test1521 | 3 + tests/libtest/mk-lib1521.pl | 339 ++++++++++++++++++++++++++++++------ 6 files changed, 311 insertions(+), 67 deletions(-) diff --git a/include/curl/curl.h b/include/curl/curl.h index 2890d05e1a..1609ff6cf2 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -1250,8 +1250,7 @@ typedef enum { /* send linked-list of post-transfer QUOTE commands */ CURLOPT(CURLOPT_POSTQUOTE, CURLOPTTYPE_SLISTPOINT, 39), - /* OBSOLETE, do not use! */ - CURLOPT(CURLOPT_OBSOLETE40, CURLOPTTYPE_OBJECTPOINT, 40), + /* 40 is not used */ /* talk a lot */ CURLOPT(CURLOPT_VERBOSE, CURLOPTTYPE_LONG, 41), @@ -1352,9 +1351,7 @@ typedef enum { /* Max amount of cached alive connections */ CURLOPT(CURLOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 71), - /* OBSOLETE, do not use! */ - CURLOPT(CURLOPT_OBSOLETE72, CURLOPTTYPE_LONG, 72), - + /* 72 = OBSOLETE */ /* 73 = OBSOLETE */ /* Set to explicitly use a new connection for the upcoming transfer. diff --git a/lib/setopt.c b/lib/setopt.c index 8832fca126..2e76ec8c10 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -2700,17 +2700,27 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) case CURLOPT_PROTOCOLS_STR: { argptr = va_arg(param, char *); - result = protocol2num(argptr, &data->set.allowed_protocols); - if(result) - return result; + if(argptr) { + result = protocol2num(argptr, &data->set.allowed_protocols); + if(result) + return result; + } + else + /* make a NULL argument reset to default */ + data->set.allowed_protocols = (curl_prot_t) CURLPROTO_ALL; break; } case CURLOPT_REDIR_PROTOCOLS_STR: { argptr = va_arg(param, char *); - result = protocol2num(argptr, &data->set.redir_protocols); - if(result) - return result; + if(argptr) { + result = protocol2num(argptr, &data->set.redir_protocols); + if(result) + return result; + } + else + /* make a NULL argument reset to default */ + data->set.redir_protocols = (curl_prot_t) CURLPROTO_REDIR; break; } diff --git a/lib/url.c b/lib/url.c index 50e2074b8e..effe8ce184 100644 --- a/lib/url.c +++ b/lib/url.c @@ -414,8 +414,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) set->new_file_perms = 0644; /* Default permissions */ set->allowed_protocols = (curl_prot_t) CURLPROTO_ALL; - set->redir_protocols = CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP | - CURLPROTO_FTPS; + set->redir_protocols = CURLPROTO_REDIR; #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) /* diff --git a/lib/urldata.h b/lib/urldata.h index 8cacf1b088..fb5a146d25 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -77,6 +77,10 @@ struct curl_trc_featt; #define CURLPROTO_WSS 0 #endif +/* the default protocols accepting a redirect to */ +#define CURLPROTO_REDIR (CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP | \ + CURLPROTO_FTPS) + /* This should be undefined once we need bit 32 or higher */ #define PROTO_TYPE_SMALL diff --git a/tests/data/test1521 b/tests/data/test1521 index 21d51fdca7..f62f58c5f9 100644 --- a/tests/data/test1521 +++ b/tests/data/test1521 @@ -26,5 +26,8 @@ unused # # Verify data after the test has been "shot" + +ok + diff --git a/tests/libtest/mk-lib1521.pl b/tests/libtest/mk-lib1521.pl index 6fd332240b..4b3921d77a 100755 --- a/tests/libtest/mk-lib1521.pl +++ b/tests/libtest/mk-lib1521.pl @@ -29,11 +29,148 @@ # minimum and maximum long signed values my $minlong = "LONG_MIN"; my $maxlong = "LONG_MAX"; -# maximum long unsigned value -my $maxulong = "ULONG_MAX"; +# maximum curl_off_t +my $maxofft = "CURL_OFF_T_MAX"; my $line = ""; my $incomment = 0; +# Options allowed to return CURLE_BAD_FUNCTION_ARGUMENT if given a string they +# do not recognize as valid +my @bad_function_argument = ( + 'CURLOPT_DNS_LOCAL_IP4', + 'CURLOPT_DNS_LOCAL_IP6', + 'CURLOPT_DNS_SERVERS', + 'CURLOPT_PROXY_TLSAUTH_TYPE', + 'CURLOPT_SSLENGINE', + 'CURLOPT_TLSAUTH_TYPE', +); + +# Options allowed to return CURLE_UNSUPPORTED_PROTOCOL if given a string they +# do not recognize as valid +my @unsupported_protocol = ( + 'CURLOPT_PROTOCOLS_STR', + 'CURLOPT_REDIR_PROTOCOLS_STR', + ); + +# Options allowed to return CURLE_SSL_ENGINE_NOTFOUND if given a string they +# do not recognize as valid +my @ssl_engine_notfound = ( + 'CURLOPT_SSLENGINE', + ); + +# Options allowed to return CURLE_UNSUPPORTED_PROTOCOL if given a bad +# numerical input they do not recognize as valid +my @unsupported_protocol_num = ( + 'CURLOPT_HTTP_VERSION', + ); + +# Options allowed to return CURLE_NOT_BUILT_IN if given a bad +# numerical input they do not recognize as valid +my @not_built_in_num = ( + 'CURLOPT_HTTPAUTH', + 'CURLOPT_PROXYAUTH', + 'CURLOPT_SOCKS5_AUTH', + ); + + +# +# Generate a set of string checks +# + +my $allowedstringerrors = <, et al. + * Copyright (C) Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -72,23 +209,9 @@ struct data { #define LO $minlong #define HI $maxlong #define OFF_LO (curl_off_t) LO -#define OFF_HI (curl_off_t) $maxulong +#define OFF_HI (curl_off_t) $maxofft #define OFF_NO (curl_off_t) 0 -/* Unexpected error. - CURLE_NOT_BUILT_IN - means disabled at build - CURLE_UNKNOWN_OPTION - means no such option (anymore?) - CURLE_SSL_ENGINE_NOTFOUND - set unknown ssl engine - CURLE_UNSUPPORTED_PROTOCOL - set bad HTTP version - CURLE_BAD_FUNCTION_ARGUMENT - unsupported value - */ -#define UNEX(x) ((x) && \\ - ((x) != CURLE_NOT_BUILT_IN) && \\ - ((x) != CURLE_UNKNOWN_OPTION) && \\ - ((x) != CURLE_SSL_ENGINE_NOTFOUND) && \\ - ((x) != CURLE_UNSUPPORTED_PROTOCOL) && \\ - ((x) != CURLE_BAD_FUNCTION_ARGUMENT) ) - static size_t writecb(char *buffer, size_t size, size_t nitems, void *outstream) { @@ -111,18 +234,44 @@ static size_t readcb(char *buffer, return 0; } -static int err(const char *name, CURLcode val, int lineno) +static void errlongzero(const char *name, CURLcode code, int lineno) +{ + printf("%s set to 0 returned %d, \\"%s\\" on line %d\\n", + name, code, curl_easy_strerror(code), lineno); +} + +static void errlong(const char *name, CURLcode code, int lineno) +{ +$allowednumerrors + printf("%s set to non-zero returned %d, \\"%s\\" on line %d\\n", + name, code, curl_easy_strerror(code), lineno); +} + +static void errstring(const char *name, CURLcode code, int lineno) +{ + /* allow this set of options to return CURLE_BAD_FUNCTION_ARGUMENT + when given a strange string input */ +$allowedstringerrors + printf("%s set to a string returned %d, \\"%s\\" on line %d\\n", + name, code, curl_easy_strerror(code), lineno); +} + +static void err(const char *name, CURLcode val, int lineno) +{ + printf("%s returned %d, \\"%s\\" on line %d\\n", + name, val, curl_easy_strerror(val), lineno); +} + +static void errnull(const char *name, CURLcode val, int lineno) { - printf("CURLOPT_%s returned %d, \\"%s\\" on line %d\\n", + printf("%s set to NULL returned %d, \\"%s\\" on line %d\\n", name, val, curl_easy_strerror(val), lineno); - return (int)val; } -static int geterr(const char *name, CURLcode val, int lineno) +static void geterr(const char *name, CURLcode val, int lineno) { printf("CURLINFO_%s returned %d, \\"%s\\" on line %d\\n", name, val, curl_easy_strerror(val), lineno); - return (int)val; } static curl_progress_callback progresscb; @@ -146,6 +295,29 @@ static curl_hstswrite_callback hstswritecb; static curl_resolver_start_callback resolver_start_cb; static curl_prereq_callback prereqcb; +/* long options that are okay to return + CURLE_BAD_FUNCTION_ARGUMENT */ +static bool bad_long(CURLcode res, int check) +{ + if(res != CURLE_BAD_FUNCTION_ARGUMENT) + return 0; /* not okay */ + + if(check < CURLOPTTYPE_OBJECTPOINT) { + /* LONG */ + return 1; + } + else if((check >= CURLOPTTYPE_OFF_T) && + (check < CURLOPTTYPE_BLOB)) { + /* OFF_T */ + return 1; + } + return 0; +} + +/* macro to check the first setopt of an option which then is allowed to get a + non-existing function return code back */ +#define present(x) ((x != CURLE_NOT_BUILT_IN) && (x != CURLE_UNKNOWN_OPTION)) + CURLcode test(char *URL) { CURL *curl = NULL; @@ -180,7 +352,6 @@ CURLcode test(char *URL) res = CURLE_OUT_OF_MEMORY; goto test_cleanup; } - HEADER ; @@ -235,78 +406,136 @@ while() { if($_ =~ /^CURLOPT(?:DEPRECATED)?\(([^ ]*), ([^ ]*), (\d*)[,)]/) { my ($name, $type, $val)=($1, $2, $3); my $w=" "; - my $pref = "${w}res = curl_easy_setopt(curl, $name,"; - my $i = ' ' x (length($w) + 23); - my $check = " if(UNEX(res)) {\n err(\"$name\", res, __LINE__);\n goto test_cleanup;\n }\n"; + my $w2="$w$w"; + my $w3="$w$w$w"; + my $opt = $name; + $opt =~ s/^CURLOPT_//; + my $exists = "${w}{\n"; + # the first check for an option + my $fpref = "${exists}${w2}CURLcode first =\n${w3}curl_easy_setopt(curl, $name,"; + my $ifpresent = "${w2}if(present(first)) {\n"; + my $pref = "${w3}res = curl_easy_setopt(curl, $name,"; + my $i = ' ' x (length($w) + 25); + my $fcheck = <) { ($_ =~ /^CURLINFO_([^ ]*) *= *CURLINFO_([^ ]*)/)) { my ($info, $type)=($1, $2); my $c = " res = curl_easy_getinfo(curl, CURLINFO_$info,"; - my $check = " if(UNEX(res)) {\n geterr(\"$info\", res, __LINE__);\n goto test_cleanup;\n }\n"; + my $check = " if(res)\n geterr(\"$info\", res, __LINE__);\n"; if($type eq "STRING") { print "$c &charp);\n$check"; } @@ -363,6 +592,8 @@ test_cleanup: curl_share_cleanup(share); curl_global_cleanup(); + if(!res) + puts("ok"); return res; } FOOTER -- 2.47.3