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 30my $minlong = "LONG_MIN"; 31my $maxlong = "LONG_MAX"; 32# maximum curl_off_t 33my $maxofft = "CURL_OFF_T_MAX"; 34my $line = ""; 35my $incomment = 0; 36 37# Options allowed to return CURLE_BAD_FUNCTION_ARGUMENT if given a string they 38# do not recognize as valid 39my @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 50my @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 57my @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 63my @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 69my @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 80my $allowedstringerrors = <<MOO 81 switch(code) { 82 case CURLE_BAD_FUNCTION_ARGUMENT: 83MOO 84 ; 85 86for my $o (@bad_function_argument) { 87 $allowedstringerrors .= <<MOO 88 if(!strcmp("$o", name)) 89 return; 90MOO 91 ; 92} 93 94$allowedstringerrors .= <<MOO 95 break; 96MOO 97 ; 98 99$allowedstringerrors .= <<MOO 100 case CURLE_UNSUPPORTED_PROTOCOL: 101MOO 102 ; 103for my $o (@unsupported_protocol) { 104 $allowedstringerrors .= <<MOO 105 if(!strcmp("$o", name)) 106 return; 107MOO 108 ; 109} 110$allowedstringerrors .= <<MOO 111 break; 112MOO 113 ; 114 115$allowedstringerrors .= <<MOO 116 case CURLE_SSL_ENGINE_NOTFOUND: 117MOO 118 ; 119for my $o (@ssl_engine_notfound) { 120 $allowedstringerrors .= <<MOO 121 if(!strcmp("$o", name)) 122 return; 123MOO 124 ; 125} 126$allowedstringerrors .= <<MOO 127 break; 128 default: 129 break; 130 } 131MOO 132 ; 133 134# 135# Generate a set of string checks 136# 137 138my $allowednumerrors = <<MOO 139 switch(code) { 140 case CURLE_UNSUPPORTED_PROTOCOL: 141MOO 142 ; 143 144for my $o (@unsupported_protocol_num) { 145 $allowednumerrors .= <<MOO 146 if(!strcmp("$o", name)) 147 return; 148MOO 149 ; 150} 151 152$allowednumerrors .= <<MOO 153 break; 154 case CURLE_NOT_BUILT_IN: 155MOO 156 ; 157 158for my $o (@not_built_in_num) { 159 $allowednumerrors .= <<MOO 160 if(!strcmp("$o", name)) 161 return; 162MOO 163 ; 164} 165 166$allowednumerrors .= <<MOO 167 break; 168 default: 169 break; 170 } 171MOO 172 ; 173 174if(!$ARGV[0]) { 175 die "missing target file name"; 176} 177 178use File::Temp qw/ :mktemp /; 179 180my ($fh, $tempfile) = mkstemp("lib1521-XXXXX"); 181 182print $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 "test.h" 207#include "memdebug.h" 208#include <limits.h> 209 210/* This source code is generated by mk-lib1521.pl ! */ 211 212struct testdata { 213 char *blaha; 214}; 215 216#define LO $minlong 217#define HI $maxlong 218#define OFF_LO (curl_off_t) LO 219#define OFF_HI (curl_off_t) $maxofft 220#define OFF_NO (curl_off_t) 0 221 222static size_t writecb(char *buffer, size_t size, size_t nitems, 223 void *outstream) 224{ 225 (void)buffer; 226 (void)size; 227 (void)nitems; 228 (void)outstream; 229 return 0; 230} 231 232static size_t readcb(char *buffer, 233 size_t size, 234 size_t nitems, 235 void *instream) 236{ 237 (void)buffer; 238 (void)size; 239 (void)nitems; 240 (void)instream; 241 return 0; 242} 243 244static void errlongzero(const char *name, CURLcode code, int lineno) 245{ 246 printf("%s set to 0 returned %d, \\"%s\\" on line %d\\n", 247 name, code, curl_easy_strerror(code), lineno); 248} 249 250static void errlong(const char *name, CURLcode code, int lineno) 251{ 252$allowednumerrors 253 printf("%s set to non-zero returned %d, \\"%s\\" on line %d\\n", 254 name, code, curl_easy_strerror(code), lineno); 255} 256 257static void errstring(const char *name, CURLcode code, int lineno) 258{ 259 /* allow this set of options to return CURLE_BAD_FUNCTION_ARGUMENT 260 when given a strange string input */ 261$allowedstringerrors 262 printf("%s set to a string returned %d, \\"%s\\" on line %d\\n", 263 name, code, curl_easy_strerror(code), lineno); 264} 265 266static void err(const char *name, CURLcode val, int lineno) 267{ 268 printf("%s returned %d, \\"%s\\" on line %d\\n", 269 name, val, curl_easy_strerror(val), lineno); 270} 271 272static void errnull(const char *name, CURLcode val, int lineno) 273{ 274 printf("%s set to NULL returned %d, \\"%s\\" on line %d\\n", 275 name, val, curl_easy_strerror(val), lineno); 276} 277 278static void geterr(const char *name, CURLcode val, int lineno) 279{ 280 printf("CURLINFO_%s returned %d, \\"%s\\" on line %d\\n", 281 name, val, curl_easy_strerror(val), lineno); 282} 283 284static curl_progress_callback progresscb; 285static curl_write_callback headercb; 286static curl_debug_callback debugcb; 287static curl_trailer_callback trailercb; 288static curl_ssl_ctx_callback ssl_ctx_cb; 289static curl_ioctl_callback ioctlcb; 290static curl_sockopt_callback sockoptcb; 291static curl_opensocket_callback opensocketcb; 292static curl_seek_callback seekcb; 293static curl_sshkeycallback ssh_keycb; 294static curl_sshhostkeycallback ssh_hostkeycb; 295static curl_chunk_bgn_callback chunk_bgn_cb; 296static curl_chunk_end_callback chunk_end_cb; 297static curl_fnmatch_callback fnmatch_cb; 298static curl_closesocket_callback closesocketcb; 299static curl_xferinfo_callback xferinfocb; 300static curl_hstsread_callback hstsreadcb; 301static curl_hstswrite_callback hstswritecb; 302static curl_resolver_start_callback resolver_start_cb; 303static curl_prereq_callback prereqcb; 304 305/* long options that are okay to return 306 CURLE_BAD_FUNCTION_ARGUMENT */ 307static bool bad_long(CURLcode res, int check) 308{ 309 if(res != CURLE_BAD_FUNCTION_ARGUMENT) 310 return 0; /* not okay */ 311 312 if(check < CURLOPTTYPE_OBJECTPOINT) { 313 /* LONG */ 314 return 1; 315 } 316 else if((check >= CURLOPTTYPE_OFF_T) && 317 (check < CURLOPTTYPE_BLOB)) { 318 /* OFF_T */ 319 return 1; 320 } 321 return 0; 322} 323 324/* macro to check the first setopt of an option which then is allowed to get a 325 non-existing function return code back */ 326#define present(x) ((x != CURLE_NOT_BUILT_IN) && (x != CURLE_UNKNOWN_OPTION)) 327 328CURLcode test(char *URL) 329{ 330 CURL *curl = NULL; 331 CURL *dep = NULL; 332 CURLSH *share = NULL; 333 char errorbuffer[CURL_ERROR_SIZE]; 334 void *conv_from_network_cb = NULL; 335 void *conv_to_network_cb = NULL; 336 void *conv_from_utf8_cb = NULL; 337 void *interleavecb = NULL; 338 char *stringpointerextra = (char *)"moooo"; 339 struct curl_slist *slist = NULL; 340 struct curl_httppost *httppost = NULL; 341 curl_mime *mimepost = NULL; 342 FILE *stream = stderr; 343 struct testdata 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 = { (void *)"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 CURL_IGNORE_DEPRECATION( 364HEADER 365 ; 366 367while(<STDIN>) { 368 s/^\s*(.*?)\s*$/$1/; # Trim. 369 # Remove multi-line comment trail. 370 if($incomment) { 371 if($_ !~ /.*?\*\/\s*(.*)$/) { 372 next; 373 } 374 $_ = $1; 375 $incomment = 0; 376 } 377 if($line ne "") { 378 # Unfold line. 379 $_ = "$line $1"; 380 $line = ""; 381 } 382 # Remove comments. 383 while($_ =~ /^(.*?)\/\*.*?\*\/(.*)$/) { 384 $_ = "$1 $2"; 385 } 386 s/^\s*(.*?)\s*$/$1/; # Trim again. 387 if($_ =~ /^(.*)\/\*/) { 388 $_ = $1; 389 $incomment = 1; 390 } 391 # Ignore preprocessor directives and blank lines. 392 if($_ =~ /^(?:#|$)/) { 393 next; 394 } 395 # Handle lines that may be continued as if they were folded. 396 if($_ !~ /[;,{}]$/) { 397 # Folded line. 398 $line = $_; 399 next; 400 } 401 if($_ =~ / CURL_DEPRECATED\(/) { 402 # Drop deprecation info. 403 if($_ !~ /^(.*?) CURL_DEPRECATED\(.*?"\)(.*)$/) { 404 # Needs unfolding. 405 $line = $_; 406 next; 407 } 408 $_ = $1 . $2; 409 } 410 if($_ =~ /^CURLOPT(?:DEPRECATED)?\(/ && $_ !~ /\),$/) { 411 # Multi-line CURLOPTs need unfolding. 412 $line = $_; 413 next; 414 } 415 if($_ =~ /^CURLOPT(?:DEPRECATED)?\(([^ ]*), ([^ ]*), (\d*)[,)]/) { 416 my ($name, $type, $val)=($1, $2, $3); 417 my $w=" "; 418 my $w2="$w$w"; 419 my $w3="$w$w$w"; 420 my $opt = $name; 421 $opt =~ s/^CURLOPT_//; 422 my $exists = "${w}{\n"; 423 # the first check for an option 424 my $fpref = "${exists}${w2}CURLcode first =\n${w3}curl_easy_setopt(curl, $name,"; 425 my $ifpresent = "${w2}if(present(first)) {\n"; 426 my $pref = "${w3}res = curl_easy_setopt(curl, $name,"; 427 my $i = ' ' x (length($w) + 25); 428 my $fcheck = <<MOO 429 if(first && present(first)) /* first setopt check only */ 430 err("$name", first, __LINE__); 431MOO 432 ; 433 my $fstringcheck = <<MOO 434 if(first && present(first)) /* first setopt check only */ 435 errstring("$name", first, __LINE__); 436MOO 437 ; 438 my $check = <<MOO 439 if(res) 440 err("$name", res, __LINE__); 441MOO 442 ; 443 my $flongcheckzero = <<MOO 444 if(first && present(first) && !bad_long(first, 445 $name)) 446 errlongzero("$name", first, __LINE__); 447MOO 448 ; 449 450 my $longcheck = <<MOO 451 if(res && !bad_long(res, $name)) 452 errlong("$name", res, __LINE__); 453MOO 454 ; 455 456 my $nullcheck = <<MOO 457 if(res) 458 errnull(\"$name\", res, __LINE__); 459MOO 460 ; 461 462 print $fh "\n /****** Verify $name ******/\n"; 463 if($type eq "CURLOPTTYPE_STRINGPOINT") { 464 print $fh "${fpref} \"string\");\n$fstringcheck"; 465 print $fh "$ifpresent"; 466 print $fh "${pref} NULL);\n$nullcheck"; 467 } 468 elsif(($type eq "CURLOPTTYPE_LONG") || 469 ($type eq "CURLOPTTYPE_VALUES")) { 470 print $fh "${fpref} 0L);\n$flongcheckzero"; 471 print $fh "$ifpresent"; 472 print $fh "${pref} 22L);\n$longcheck"; 473 print $fh "${pref} LO);\n$longcheck"; 474 print $fh "${pref} HI);\n$longcheck"; 475 } 476 elsif($type eq "CURLOPTTYPE_OFF_T") { 477 print $fh "${fpref} OFF_NO);\n$flongcheckzero"; 478 print $fh "$ifpresent"; 479 my $lvl = " " x 29; 480 print $fh "${pref}\n${lvl}(curl_off_t)22);\n$longcheck"; 481 print $fh "${pref} OFF_HI);\n$longcheck"; 482 print $fh "${pref} OFF_LO);\n$longcheck"; 483 } 484 elsif(($type eq "CURLOPTTYPE_OBJECTPOINT") || 485 ($type eq "CURLOPTTYPE_CBPOINT")) { 486 if($name =~ /DEPENDS/) { 487 print $fh "${fpref} dep);\n$fcheck"; 488 } 489 elsif($name =~ "SHARE") { 490 print $fh "${fpref} share);\n$fcheck"; 491 } 492 elsif($name eq "CURLOPT_ERRORBUFFER") { 493 print $fh "${fpref} errorbuffer);\n$fcheck"; 494 } 495 elsif(($name eq "CURLOPT_POSTFIELDS") || 496 ($name eq "CURLOPT_COPYPOSTFIELDS")) { 497 # set size to zero to avoid it being "illegal" 498 print $fh " (void)curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 0);\n"; 499 print $fh "${fpref} stringpointerextra);\n$fcheck"; 500 } 501 elsif($name eq "CURLOPT_HTTPPOST") { 502 print $fh "${fpref} httppost);\n$fcheck"; 503 } 504 elsif($name eq "CURLOPT_MIMEPOST") { 505 print $fh "${fpref} mimepost);\n$fcheck"; 506 } 507 elsif($name eq "CURLOPT_STDERR") { 508 print $fh "${fpref} stream);\n$fcheck"; 509 } 510 else { 511 print $fh "${fpref} &object);\n$fcheck"; 512 } 513 print $fh "$ifpresent"; 514 print $fh "${pref} NULL);\n$nullcheck"; 515 } 516 elsif($type eq "CURLOPTTYPE_SLISTPOINT") { 517 print $fh "${fpref} slist);\n$fcheck"; 518 print $fh "$ifpresent"; 519 print $fh "${pref} NULL);\n$nullcheck"; 520 } 521 elsif($type eq "CURLOPTTYPE_FUNCTIONPOINT") { 522 if($name =~ /([^ ]*)FUNCTION/) { 523 my $l=lc($1); 524 $l =~ s/^curlopt_//; 525 print $fh "${fpref}\n$i${l}cb);\n$fcheck"; 526 } 527 else { 528 print $fh "${fpref} &func);\n$fcheck"; 529 } 530 print $fh "$ifpresent"; 531 print $fh "${pref} NULL);\n$nullcheck"; 532 } 533 elsif($type eq "CURLOPTTYPE_BLOB") { 534 print $fh "${fpref} &blob);\n$check"; 535 print $fh "$ifpresent"; 536 print $fh "${pref} NULL);\n$nullcheck"; 537 } 538 else { 539 print STDERR "\nUnknown type: $type\n"; 540 exit 22; # exit to make this noticed! 541 } 542 543 print $fh <<MOO 544 } /* end of secondary checks */ 545 } /* end of single setopt */ 546MOO 547 ; 548 } 549 elsif($_ =~ /^CURLINFO_NONE/) { 550 $infomode = 1; 551 } 552 elsif($infomode && 553 ($_ =~ /^CURLINFO_([^ ]*) *= *CURLINFO_([^ ]*)/)) { 554 my ($info, $type)=($1, $2); 555 my $c = " res = curl_easy_getinfo(curl, CURLINFO_$info,"; 556 my $check = " if(res)\n geterr(\"$info\", res, __LINE__);\n"; 557 if($type eq "STRING") { 558 print $fh "$c &charp);\n$check"; 559 } 560 elsif($type eq "LONG") { 561 print $fh "$c &val);\n$check"; 562 } 563 elsif($type eq "OFF_T") { 564 print $fh "$c &oval);\n$check"; 565 } 566 elsif($type eq "DOUBLE") { 567 print $fh "$c &dval);\n$check"; 568 } 569 elsif($type eq "SLIST") { 570 print $fh "$c &slist);\n$check"; 571 print $fh " if(slist)\n curl_slist_free_all(slist);\n"; 572 } 573 elsif($type eq "SOCKET") { 574 print $fh "$c &sockfd);\n$check"; 575 } 576 elsif($type eq "PTR") { 577 if($info eq "CERTINFO") { 578 print $fh "$c &certinfo);\n$check"; 579 } 580 elsif(($info eq "TLS_SESSION") || 581 ($info eq "TLS_SSL_PTR")) { 582 print $fh "$c &tlssession);\n$check"; 583 } 584 else { 585 print STDERR "$info/$type is unsupported\n"; 586 } 587 } 588 else { 589 print STDERR "$type is unsupported\n"; 590 } 591 } 592} 593 594 595print $fh <<FOOTER 596 ) 597 curl_easy_setopt(curl, (CURLoption)1, 0); 598 res = CURLE_OK; 599test_cleanup: 600 curl_easy_cleanup(curl); 601 curl_easy_cleanup(dep); 602 curl_share_cleanup(share); 603 curl_global_cleanup(); 604 605 if(!res) 606 puts("ok"); 607 return res; 608} 609FOOTER 610 ; 611 612close($fh); 613rename($tempfile, $ARGV[0]); 614