mk-lib1521.pl (17145B)
1 #!/usr/bin/env perl 2 #*************************************************************************** 3 # _ _ ____ _ 4 # Project ___| | | | _ \| | 5 # / __| | | | |_) | | 6 # | (__| |_| | _ <| |___ 7 # \___|\___/|_| \_\_____| 8 # 9 # Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 10 # 11 # This software is licensed as described in the file COPYING, which 12 # you should have received as part of this distribution. The terms 13 # are also available at https://curl.se/docs/copyright.html. 14 # 15 # You may opt to use, copy, modify, merge, publish, distribute and/or sell 16 # copies of the Software, and permit persons to whom the Software is 17 # furnished to do so, under the terms of the COPYING file. 18 # 19 # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 20 # KIND, either express or implied. 21 # 22 # SPDX-License-Identifier: curl 23 # 24 ########################################################################### 25 26 # Usage: 27 # perl mk-lib1521.pl < ../../include/curl/curl.h lib1521.c 28 29 # minimum and maximum long signed values 30 my $minlong = "LONG_MIN"; 31 my $maxlong = "LONG_MAX"; 32 # maximum curl_off_t 33 my $maxofft = "CURL_OFF_T_MAX"; 34 my $line = ""; 35 my $incomment = 0; 36 37 # Options allowed to return CURLE_BAD_FUNCTION_ARGUMENT if given a string they 38 # do not recognize as valid 39 my @bad_function_argument = ( 40 'CURLOPT_DNS_LOCAL_IP4', 41 'CURLOPT_DNS_LOCAL_IP6', 42 'CURLOPT_DNS_SERVERS', 43 'CURLOPT_PROXY_TLSAUTH_TYPE', 44 'CURLOPT_SSLENGINE', 45 'CURLOPT_TLSAUTH_TYPE', 46 ); 47 48 # Options allowed to return CURLE_UNSUPPORTED_PROTOCOL if given a string they 49 # do not recognize as valid 50 my @unsupported_protocol = ( 51 'CURLOPT_PROTOCOLS_STR', 52 'CURLOPT_REDIR_PROTOCOLS_STR', 53 ); 54 55 # Options allowed to return CURLE_SSL_ENGINE_NOTFOUND if given a string they 56 # do not recognize as valid 57 my @ssl_engine_notfound = ( 58 'CURLOPT_SSLENGINE', 59 ); 60 61 # Options allowed to return CURLE_UNSUPPORTED_PROTOCOL if given a bad 62 # numerical input they do not recognize as valid 63 my @unsupported_protocol_num = ( 64 'CURLOPT_HTTP_VERSION', 65 ); 66 67 # Options allowed to return CURLE_NOT_BUILT_IN if given a bad 68 # numerical input they do not recognize as valid 69 my @not_built_in_num = ( 70 'CURLOPT_HTTPAUTH', 71 'CURLOPT_PROXYAUTH', 72 'CURLOPT_SOCKS5_AUTH', 73 ); 74 75 76 # 77 # Generate a set of string checks 78 # 79 80 my $allowedstringerrors = <<MOO 81 switch(code) { 82 case CURLE_BAD_FUNCTION_ARGUMENT: 83 MOO 84 ; 85 86 for my $o (@bad_function_argument) { 87 $allowedstringerrors .= <<MOO 88 if(!strcmp("$o", name)) 89 return; 90 MOO 91 ; 92 } 93 94 $allowedstringerrors .= <<MOO 95 break; 96 MOO 97 ; 98 99 $allowedstringerrors .= <<MOO 100 case CURLE_UNSUPPORTED_PROTOCOL: 101 MOO 102 ; 103 for my $o (@unsupported_protocol) { 104 $allowedstringerrors .= <<MOO 105 if(!strcmp("$o", name)) 106 return; 107 MOO 108 ; 109 } 110 $allowedstringerrors .= <<MOO 111 break; 112 MOO 113 ; 114 115 $allowedstringerrors .= <<MOO 116 case CURLE_SSL_ENGINE_NOTFOUND: 117 MOO 118 ; 119 for my $o (@ssl_engine_notfound) { 120 $allowedstringerrors .= <<MOO 121 if(!strcmp("$o", name)) 122 return; 123 MOO 124 ; 125 } 126 $allowedstringerrors .= <<MOO 127 break; 128 default: 129 break; 130 } 131 MOO 132 ; 133 134 # 135 # Generate a set of string checks 136 # 137 138 my $allowednumerrors = <<MOO 139 switch(code) { 140 case CURLE_UNSUPPORTED_PROTOCOL: 141 MOO 142 ; 143 144 for my $o (@unsupported_protocol_num) { 145 $allowednumerrors .= <<MOO 146 if(!strcmp("$o", name)) 147 return; 148 MOO 149 ; 150 } 151 152 $allowednumerrors .= <<MOO 153 break; 154 case CURLE_NOT_BUILT_IN: 155 MOO 156 ; 157 158 for my $o (@not_built_in_num) { 159 $allowednumerrors .= <<MOO 160 if(!strcmp("$o", name)) 161 return; 162 MOO 163 ; 164 } 165 166 $allowednumerrors .= <<MOO 167 break; 168 default: 169 break; 170 } 171 MOO 172 ; 173 174 if(!$ARGV[0]) { 175 die "missing target file name"; 176 } 177 178 use File::Temp qw/ :mktemp /; 179 180 my ($fh, $tempfile) = mkstemp("lib1521-XXXXX"); 181 182 print $fh <<HEADER 183 /*************************************************************************** 184 * _ _ ____ _ 185 * Project ___| | | | _ \\| | 186 * / __| | | | |_) | | 187 * | (__| |_| | _ <| |___ 188 * \\___|\\___/|_| \\_\\_____| 189 * 190 * Copyright (C) Daniel Stenberg, <daniel\@haxx.se>, et al. 191 * 192 * This software is licensed as described in the file COPYING, which 193 * you should have received as part of this distribution. The terms 194 * are also available at https://curl.se/docs/copyright.html. 195 * 196 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 197 * copies of the Software, and permit persons to whom the Software is 198 * furnished to do so, under the terms of the COPYING file. 199 * 200 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 201 * KIND, either express or implied. 202 * 203 * SPDX-License-Identifier: curl 204 * 205 ***************************************************************************/ 206 #include "first.h" 207 #include "memdebug.h" 208 209 /* This source code is generated by mk-lib1521.pl ! */ 210 211 struct t1521_testdata { 212 char *blaha; 213 }; 214 215 #define LO $minlong 216 #define HI $maxlong 217 #define OFF_LO (curl_off_t) LO 218 #define OFF_HI (curl_off_t) $maxofft 219 #define OFF_NO (curl_off_t) 0 220 221 static size_t writecb(char *buffer, size_t size, size_t nitems, 222 void *outstream) 223 { 224 (void)buffer; 225 (void)size; 226 (void)nitems; 227 (void)outstream; 228 return 0; 229 } 230 231 static size_t readcb(char *buffer, 232 size_t size, 233 size_t nitems, 234 void *instream) 235 { 236 (void)buffer; 237 (void)size; 238 (void)nitems; 239 (void)instream; 240 return 0; 241 } 242 243 static void errlongzero(const char *name, CURLcode code, int lineno) 244 { 245 curl_mprintf("%s set to 0 returned %d, \\"%s\\" on line %d\\n", 246 name, code, curl_easy_strerror(code), lineno); 247 } 248 249 static void errlong(const char *name, CURLcode code, int lineno) 250 { 251 $allowednumerrors 252 curl_mprintf("%s set to non-zero returned %d, \\"%s\\" on line %d\\n", 253 name, code, curl_easy_strerror(code), lineno); 254 } 255 256 static void errstring(const char *name, CURLcode code, int lineno) 257 { 258 /* allow this set of options to return CURLE_BAD_FUNCTION_ARGUMENT 259 when given a strange string input */ 260 $allowedstringerrors 261 curl_mprintf("%s set to a string returned %d, \\"%s\\" on line %d\\n", 262 name, code, curl_easy_strerror(code), lineno); 263 } 264 265 static void err(const char *name, CURLcode val, int lineno) 266 { 267 curl_mprintf("%s returned %d, \\"%s\\" on line %d\\n", 268 name, val, curl_easy_strerror(val), lineno); 269 } 270 271 static void errnull(const char *name, CURLcode val, int lineno) 272 { 273 curl_mprintf("%s set to NULL returned %d, \\"%s\\" on line %d\\n", 274 name, val, curl_easy_strerror(val), lineno); 275 } 276 277 static void t1521_geterr(const char *name, CURLcode val, int lineno) 278 { 279 curl_mprintf("CURLINFO_%s returned %d, \\"%s\\" on line %d\\n", 280 name, val, curl_easy_strerror(val), lineno); 281 } 282 283 static curl_progress_callback progresscb; 284 static curl_write_callback headercb; 285 static curl_debug_callback debugcb; 286 static curl_trailer_callback trailercb; 287 static curl_ssl_ctx_callback ssl_ctx_cb; 288 static curl_ioctl_callback ioctlcb; 289 static curl_sockopt_callback sockoptcb; 290 static curl_opensocket_callback opensocketcb; 291 static curl_seek_callback seekcb; 292 static curl_sshkeycallback ssh_keycb; 293 static curl_sshhostkeycallback ssh_hostkeycb; 294 static curl_chunk_bgn_callback chunk_bgn_cb; 295 static curl_chunk_end_callback chunk_end_cb; 296 static curl_fnmatch_callback fnmatch_cb; 297 static curl_closesocket_callback closesocketcb; 298 static curl_xferinfo_callback xferinfocb; 299 static curl_hstsread_callback hstsreadcb; 300 static curl_hstswrite_callback hstswritecb; 301 static curl_resolver_start_callback resolver_start_cb; 302 static curl_prereq_callback prereqcb; 303 304 /* long options that are okay to return 305 CURLE_BAD_FUNCTION_ARGUMENT */ 306 static bool bad_long(CURLcode res, int check) 307 { 308 if(res != CURLE_BAD_FUNCTION_ARGUMENT) 309 return 0; /* not okay */ 310 311 if(check < CURLOPTTYPE_OBJECTPOINT) { 312 /* LONG */ 313 return 1; 314 } 315 else if((check >= CURLOPTTYPE_OFF_T) && 316 (check < CURLOPTTYPE_BLOB)) { 317 /* OFF_T */ 318 return 1; 319 } 320 return 0; 321 } 322 323 /* macro to check the first setopt of an option which then is allowed to get a 324 non-existing function return code back */ 325 #define present(x) ((x != CURLE_NOT_BUILT_IN) && (x != CURLE_UNKNOWN_OPTION)) 326 327 static CURLcode test_lib1521(char *URL) 328 { 329 CURL *curl = NULL; 330 CURL *dep = NULL; 331 CURLSH *share = NULL; 332 char errorbuffer[CURL_ERROR_SIZE]; 333 void *conv_from_network_cb = NULL; 334 void *conv_to_network_cb = NULL; 335 void *conv_from_utf8_cb = NULL; 336 void *interleavecb = NULL; 337 char *stringpointerextra = (char *)CURL_UNCONST("moooo"); 338 struct curl_slist *slist = NULL; 339 struct curl_httppost *httppost = NULL; 340 curl_mime *mimepost = NULL; 341 FILE *stream = stderr; 342 struct t1521_testdata object; 343 CURLU *curlu = (CURLU *)&object; 344 char *charp; 345 long val; 346 curl_off_t oval; 347 double dval; 348 curl_socket_t sockfd; 349 struct curl_certinfo *certinfo; 350 struct curl_tlssessioninfo *tlssession; 351 struct curl_blob blob = { CURL_UNCONST("silly"), 5, 0}; 352 CURLcode res = CURLE_OK; 353 (void)URL; /* not used */ 354 global_init(CURL_GLOBAL_ALL); 355 easy_init(dep); 356 easy_init(curl); 357 share = curl_share_init(); 358 if(!share) { 359 res = CURLE_OUT_OF_MEMORY; 360 goto test_cleanup; 361 } 362 363 HEADER 364 ; 365 366 while(<STDIN>) { 367 s/^\s*(.*?)\s*$/$1/; # Trim. 368 # Remove multi-line comment trail. 369 if($incomment) { 370 if($_ !~ /.*?\*\/\s*(.*)$/) { 371 next; 372 } 373 $_ = $1; 374 $incomment = 0; 375 } 376 if($line ne "") { 377 # Unfold line. 378 $_ = "$line $1"; 379 $line = ""; 380 } 381 # Remove comments. 382 while($_ =~ /^(.*?)\/\*.*?\*\/(.*)$/) { 383 $_ = "$1 $2"; 384 } 385 s/^\s*(.*?)\s*$/$1/; # Trim again. 386 if($_ =~ /^(.*)\/\*/) { 387 $_ = $1; 388 $incomment = 1; 389 } 390 # Ignore preprocessor directives and blank lines. 391 if($_ =~ /^(?:#|$)/) { 392 next; 393 } 394 # Handle lines that may be continued as if they were folded. 395 if($_ !~ /[;,{}]$/) { 396 # Folded line. 397 $line = $_; 398 next; 399 } 400 if($_ =~ / CURL_DEPRECATED\(/) { 401 # Drop deprecation info. 402 if($_ !~ /^(.*?) CURL_DEPRECATED\(.*?"\)(.*)$/) { 403 # Needs unfolding. 404 $line = $_; 405 next; 406 } 407 $_ = $1 . $2; 408 } 409 if($_ =~ /^CURLOPT(?:DEPRECATED)?\(/ && $_ !~ /\),$/) { 410 # Multi-line CURLOPTs need unfolding. 411 $line = $_; 412 next; 413 } 414 if($_ =~ /^CURLOPT(?:DEPRECATED)?\(([^ ]*), ([^ ]*), (\d*)[,)]/) { 415 my ($name, $type, $val)=($1, $2, $3); 416 my $w=" "; 417 my $w2="$w$w"; 418 my $w3="$w$w$w"; 419 my $opt = $name; 420 $opt =~ s/^CURLOPT_//; 421 my $exists = "${w}{\n"; 422 # the first check for an option 423 my $fpref = "${exists}${w2}CURLcode first =\n${w3}curl_easy_setopt(curl, $name,"; 424 my $ifpresent = "${w2}if(present(first)) {\n"; 425 my $pref = "${w3}res = curl_easy_setopt(curl, $name,"; 426 my $i = ' ' x (length($w) + 25); 427 my $fcheck = <<MOO 428 if(first && present(first)) /* first setopt check only */ 429 err("$name", first, __LINE__); 430 MOO 431 ; 432 my $fstringcheck = <<MOO 433 if(first && present(first)) /* first setopt check only */ 434 errstring("$name", first, __LINE__); 435 MOO 436 ; 437 my $check = <<MOO 438 if(res) 439 err("$name", res, __LINE__); 440 MOO 441 ; 442 my $flongcheckzero = <<MOO 443 if(first && present(first) && !bad_long(first, 444 $name)) 445 errlongzero("$name", first, __LINE__); 446 MOO 447 ; 448 449 my $longcheck = <<MOO 450 if(res && !bad_long(res, $name)) 451 errlong("$name", res, __LINE__); 452 MOO 453 ; 454 455 my $nullcheck = <<MOO 456 if(res) 457 errnull(\"$name\", res, __LINE__); 458 MOO 459 ; 460 461 print $fh "\n /****** Verify $name ******/\n"; 462 if($type eq "CURLOPTTYPE_STRINGPOINT") { 463 print $fh "${fpref} \"string\");\n$fstringcheck"; 464 print $fh "$ifpresent"; 465 print $fh "${pref} NULL);\n$nullcheck"; 466 } 467 elsif(($type eq "CURLOPTTYPE_LONG") || 468 ($type eq "CURLOPTTYPE_VALUES")) { 469 print $fh "${fpref} 0L);\n$flongcheckzero"; 470 print $fh "$ifpresent"; 471 print $fh "${pref} 22L);\n$longcheck"; 472 print $fh "${pref} LO);\n$longcheck"; 473 print $fh "${pref} HI);\n$longcheck"; 474 } 475 elsif($type eq "CURLOPTTYPE_OFF_T") { 476 print $fh "${fpref} OFF_NO);\n$flongcheckzero"; 477 print $fh "$ifpresent"; 478 my $lvl = " " x 29; 479 print $fh "${pref}\n${lvl}(curl_off_t)22);\n$longcheck"; 480 print $fh "${pref} OFF_HI);\n$longcheck"; 481 print $fh "${pref} OFF_LO);\n$longcheck"; 482 } 483 elsif(($type eq "CURLOPTTYPE_OBJECTPOINT") || 484 ($type eq "CURLOPTTYPE_CBPOINT")) { 485 if($name =~ /DEPENDS/) { 486 print $fh "${fpref} dep);\n$fcheck"; 487 } 488 elsif($name =~ "SHARE") { 489 print $fh "${fpref} share);\n$fcheck"; 490 } 491 elsif($name eq "CURLOPT_ERRORBUFFER") { 492 print $fh "${fpref} errorbuffer);\n$fcheck"; 493 } 494 elsif(($name eq "CURLOPT_POSTFIELDS") || 495 ($name eq "CURLOPT_COPYPOSTFIELDS")) { 496 # set size to zero to avoid it being "illegal" 497 print $fh " (void)curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 0L);\n"; 498 print $fh "${fpref} stringpointerextra);\n$fcheck"; 499 } 500 elsif($name eq "CURLOPT_HTTPPOST") { 501 print $fh "${fpref} httppost);\n$fcheck"; 502 } 503 elsif($name eq "CURLOPT_MIMEPOST") { 504 print $fh "${fpref} mimepost);\n$fcheck"; 505 } 506 elsif($name eq "CURLOPT_STDERR") { 507 print $fh "${fpref} stream);\n$fcheck"; 508 } 509 elsif($name eq "CURLOPT_CURLU") { 510 print $fh "${fpref} curlu);\n$fcheck"; 511 } 512 else { 513 print $fh "${fpref} &object);\n$fcheck"; 514 } 515 print $fh "$ifpresent"; 516 print $fh "${pref} NULL);\n$nullcheck"; 517 } 518 elsif($type eq "CURLOPTTYPE_SLISTPOINT") { 519 print $fh "${fpref} slist);\n$fcheck"; 520 print $fh "$ifpresent"; 521 print $fh "${pref} NULL);\n$nullcheck"; 522 } 523 elsif($type eq "CURLOPTTYPE_FUNCTIONPOINT") { 524 if($name =~ /([^ ]*)FUNCTION/) { 525 my $l=lc($1); 526 $l =~ s/^curlopt_//; 527 print $fh "${fpref}\n$i${l}cb);\n$fcheck"; 528 } 529 else { 530 print $fh "${fpref} &func);\n$fcheck"; 531 } 532 print $fh "$ifpresent"; 533 print $fh "${pref} NULL);\n$nullcheck"; 534 } 535 elsif($type eq "CURLOPTTYPE_BLOB") { 536 print $fh "${fpref} &blob);\n$check"; 537 print $fh "$ifpresent"; 538 print $fh "${pref} NULL);\n$nullcheck"; 539 } 540 else { 541 print STDERR "\nUnknown type: $type\n"; 542 exit 22; # exit to make this noticed! 543 } 544 545 print $fh <<MOO 546 } /* end of secondary checks */ 547 } /* end of single setopt */ 548 MOO 549 ; 550 } 551 elsif($_ =~ /^CURLINFO_NONE/) { 552 $infomode = 1; 553 } 554 elsif($infomode && 555 ($_ =~ /^CURLINFO_([^ ]*) *= *CURLINFO_([^ ]*)/)) { 556 my ($info, $type)=($1, $2); 557 my $c = " res = curl_easy_getinfo(curl, CURLINFO_$info,"; 558 my $check = " if(res)\n t1521_geterr(\"$info\", res, __LINE__);\n"; 559 if($type eq "STRING") { 560 print $fh "$c &charp);\n$check"; 561 } 562 elsif($type eq "LONG") { 563 print $fh "$c &val);\n$check"; 564 } 565 elsif($type eq "OFF_T") { 566 print $fh "$c &oval);\n$check"; 567 } 568 elsif($type eq "DOUBLE") { 569 print $fh "$c &dval);\n$check"; 570 } 571 elsif($type eq "SLIST") { 572 print $fh "$c &slist);\n$check"; 573 print $fh " if(slist)\n curl_slist_free_all(slist);\n"; 574 } 575 elsif($type eq "SOCKET") { 576 print $fh "$c &sockfd);\n$check"; 577 } 578 elsif($type eq "PTR") { 579 if($info eq "CERTINFO") { 580 print $fh "$c &certinfo);\n$check"; 581 } 582 elsif(($info eq "TLS_SESSION") || 583 ($info eq "TLS_SSL_PTR")) { 584 print $fh "$c &tlssession);\n$check"; 585 } 586 else { 587 print STDERR "$info/$type is unsupported\n"; 588 } 589 } 590 else { 591 print STDERR "$type is unsupported\n"; 592 } 593 } 594 } 595 596 597 print $fh <<FOOTER 598 599 /* NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange) */ 600 curl_easy_setopt(curl, (CURLoption)1, 0L); 601 res = CURLE_OK; 602 test_cleanup: 603 curl_easy_cleanup(curl); 604 curl_easy_cleanup(dep); 605 curl_share_cleanup(share); 606 curl_global_cleanup(); 607 608 if(!res) 609 puts("ok"); 610 return res; 611 } 612 FOOTER 613 ; 614 615 close($fh); 616 rename($tempfile, $ARGV[0]);