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 174print <<HEADER 175/*************************************************************************** 176 * _ _ ____ _ 177 * Project ___| | | | _ \\| | 178 * / __| | | | |_) | | 179 * | (__| |_| | _ <| |___ 180 * \\___|\\___/|_| \\_\\_____| 181 * 182 * Copyright (C) Daniel Stenberg, <daniel\@haxx.se>, et al. 183 * 184 * This software is licensed as described in the file COPYING, which 185 * you should have received as part of this distribution. The terms 186 * are also available at https://curl.se/docs/copyright.html. 187 * 188 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 189 * copies of the Software, and permit persons to whom the Software is 190 * furnished to do so, under the terms of the COPYING file. 191 * 192 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 193 * KIND, either express or implied. 194 * 195 * SPDX-License-Identifier: curl 196 * 197 ***************************************************************************/ 198#include "test.h" 199#include "memdebug.h" 200#include <limits.h> 201 202/* This source code is generated by mk-lib1521.pl ! */ 203 204struct testdata { 205 char *blaha; 206}; 207 208#define LO $minlong 209#define HI $maxlong 210#define OFF_LO (curl_off_t) LO 211#define OFF_HI (curl_off_t) $maxofft 212#define OFF_NO (curl_off_t) 0 213 214static size_t writecb(char *buffer, size_t size, size_t nitems, 215 void *outstream) 216{ 217 (void)buffer; 218 (void)size; 219 (void)nitems; 220 (void)outstream; 221 return 0; 222} 223 224static size_t readcb(char *buffer, 225 size_t size, 226 size_t nitems, 227 void *instream) 228{ 229 (void)buffer; 230 (void)size; 231 (void)nitems; 232 (void)instream; 233 return 0; 234} 235 236static void errlongzero(const char *name, CURLcode code, int lineno) 237{ 238 printf("%s set to 0 returned %d, \\"%s\\" on line %d\\n", 239 name, code, curl_easy_strerror(code), lineno); 240} 241 242static void errlong(const char *name, CURLcode code, int lineno) 243{ 244$allowednumerrors 245 printf("%s set to non-zero returned %d, \\"%s\\" on line %d\\n", 246 name, code, curl_easy_strerror(code), lineno); 247} 248 249static void errstring(const char *name, CURLcode code, int lineno) 250{ 251 /* allow this set of options to return CURLE_BAD_FUNCTION_ARGUMENT 252 when given a strange string input */ 253$allowedstringerrors 254 printf("%s set to a string returned %d, \\"%s\\" on line %d\\n", 255 name, code, curl_easy_strerror(code), lineno); 256} 257 258static void err(const char *name, CURLcode val, int lineno) 259{ 260 printf("%s returned %d, \\"%s\\" on line %d\\n", 261 name, val, curl_easy_strerror(val), lineno); 262} 263 264static void errnull(const char *name, CURLcode val, int lineno) 265{ 266 printf("%s set to NULL returned %d, \\"%s\\" on line %d\\n", 267 name, val, curl_easy_strerror(val), lineno); 268} 269 270static void geterr(const char *name, CURLcode val, int lineno) 271{ 272 printf("CURLINFO_%s returned %d, \\"%s\\" on line %d\\n", 273 name, val, curl_easy_strerror(val), lineno); 274} 275 276static curl_progress_callback progresscb; 277static curl_write_callback headercb; 278static curl_debug_callback debugcb; 279static curl_trailer_callback trailercb; 280static curl_ssl_ctx_callback ssl_ctx_cb; 281static curl_ioctl_callback ioctlcb; 282static curl_sockopt_callback sockoptcb; 283static curl_opensocket_callback opensocketcb; 284static curl_seek_callback seekcb; 285static curl_sshkeycallback ssh_keycb; 286static curl_sshhostkeycallback ssh_hostkeycb; 287static curl_chunk_bgn_callback chunk_bgn_cb; 288static curl_chunk_end_callback chunk_end_cb; 289static curl_fnmatch_callback fnmatch_cb; 290static curl_closesocket_callback closesocketcb; 291static curl_xferinfo_callback xferinfocb; 292static curl_hstsread_callback hstsreadcb; 293static curl_hstswrite_callback hstswritecb; 294static curl_resolver_start_callback resolver_start_cb; 295static curl_prereq_callback prereqcb; 296 297/* long options that are okay to return 298 CURLE_BAD_FUNCTION_ARGUMENT */ 299static bool bad_long(CURLcode res, int check) 300{ 301 if(res != CURLE_BAD_FUNCTION_ARGUMENT) 302 return 0; /* not okay */ 303 304 if(check < CURLOPTTYPE_OBJECTPOINT) { 305 /* LONG */ 306 return 1; 307 } 308 else if((check >= CURLOPTTYPE_OFF_T) && 309 (check < CURLOPTTYPE_BLOB)) { 310 /* OFF_T */ 311 return 1; 312 } 313 return 0; 314} 315 316/* macro to check the first setopt of an option which then is allowed to get a 317 non-existing function return code back */ 318#define present(x) ((x != CURLE_NOT_BUILT_IN) && (x != CURLE_UNKNOWN_OPTION)) 319 320CURLcode test(char *URL) 321{ 322 CURL *curl = NULL; 323 CURL *dep = NULL; 324 CURLSH *share = NULL; 325 char errorbuffer[CURL_ERROR_SIZE]; 326 void *conv_from_network_cb = NULL; 327 void *conv_to_network_cb = NULL; 328 void *conv_from_utf8_cb = NULL; 329 void *interleavecb = NULL; 330 char *stringpointerextra = (char *)"moooo"; 331 struct curl_slist *slist = NULL; 332 struct curl_httppost *httppost = NULL; 333 curl_mime *mimepost = NULL; 334 FILE *stream = stderr; 335 struct testdata object; 336 char *charp; 337 long val; 338 curl_off_t oval; 339 double dval; 340 curl_socket_t sockfd; 341 struct curl_certinfo *certinfo; 342 struct curl_tlssessioninfo *tlssession; 343 struct curl_blob blob = { (void *)"silly", 5, 0}; 344 CURLcode res = CURLE_OK; 345 (void)URL; /* not used */ 346 global_init(CURL_GLOBAL_ALL); 347 easy_init(dep); 348 easy_init(curl); 349 share = curl_share_init(); 350 if(!share) { 351 res = CURLE_OUT_OF_MEMORY; 352 goto test_cleanup; 353 } 354 355 CURL_IGNORE_DEPRECATION( 356HEADER 357 ; 358 359while(<STDIN>) { 360 s/^\s*(.*?)\s*$/$1/; # Trim. 361 # Remove multi-line comment trail. 362 if($incomment) { 363 if($_ !~ /.*?\*\/\s*(.*)$/) { 364 next; 365 } 366 $_ = $1; 367 $incomment = 0; 368 } 369 if($line ne "") { 370 # Unfold line. 371 $_ = "$line $1"; 372 $line = ""; 373 } 374 # Remove comments. 375 while($_ =~ /^(.*?)\/\*.*?\*\/(.*)$/) { 376 $_ = "$1 $2"; 377 } 378 s/^\s*(.*?)\s*$/$1/; # Trim again. 379 if($_ =~ /^(.*)\/\*/) { 380 $_ = $1; 381 $incomment = 1; 382 } 383 # Ignore preprocessor directives and blank lines. 384 if($_ =~ /^(?:#|$)/) { 385 next; 386 } 387 # Handle lines that may be continued as if they were folded. 388 if($_ !~ /[;,{}]$/) { 389 # Folded line. 390 $line = $_; 391 next; 392 } 393 if($_ =~ / CURL_DEPRECATED\(/) { 394 # Drop deprecation info. 395 if($_ !~ /^(.*?) CURL_DEPRECATED\(.*?"\)(.*)$/) { 396 # Needs unfolding. 397 $line = $_; 398 next; 399 } 400 $_ = $1 . $2; 401 } 402 if($_ =~ /^CURLOPT(?:DEPRECATED)?\(/ && $_ !~ /\),$/) { 403 # Multi-line CURLOPTs need unfolding. 404 $line = $_; 405 next; 406 } 407 if($_ =~ /^CURLOPT(?:DEPRECATED)?\(([^ ]*), ([^ ]*), (\d*)[,)]/) { 408 my ($name, $type, $val)=($1, $2, $3); 409 my $w=" "; 410 my $w2="$w$w"; 411 my $w3="$w$w$w"; 412 my $opt = $name; 413 $opt =~ s/^CURLOPT_//; 414 my $exists = "${w}{\n"; 415 # the first check for an option 416 my $fpref = "${exists}${w2}CURLcode first =\n${w3}curl_easy_setopt(curl, $name,"; 417 my $ifpresent = "${w2}if(present(first)) {\n"; 418 my $pref = "${w3}res = curl_easy_setopt(curl, $name,"; 419 my $i = ' ' x (length($w) + 25); 420 my $fcheck = <<MOO 421 if(first && present(first)) /* first setopt check only */ 422 err("$name", first, __LINE__); 423MOO 424 ; 425 my $fstringcheck = <<MOO 426 if(first && present(first)) /* first setopt check only */ 427 errstring("$name", first, __LINE__); 428MOO 429 ; 430 my $check = <<MOO 431 if(res) 432 err("$name", res, __LINE__); 433MOO 434 ; 435 my $flongcheckzero = <<MOO 436 if(first && present(first) && !bad_long(res, 437 $name)) 438 errlongzero("$name", first, __LINE__); 439MOO 440 ; 441 442 my $longcheck = <<MOO 443 if(res && !bad_long(res, $name)) 444 errlong("$name", res, __LINE__); 445MOO 446 ; 447 448 my $nullcheck = <<MOO 449 if(res) 450 errnull(\"$name\", res, __LINE__); 451MOO 452 ; 453 454 print "\n /****** Verify $name ******/\n"; 455 if($type eq "CURLOPTTYPE_STRINGPOINT") { 456 print "${fpref} \"string\");\n$fstringcheck"; 457 print "$ifpresent"; 458 print "${pref} NULL);\n$nullcheck"; 459 } 460 elsif(($type eq "CURLOPTTYPE_LONG") || 461 ($type eq "CURLOPTTYPE_VALUES")) { 462 print "${fpref} 0L);\n$flongcheckzero"; 463 print "$ifpresent"; 464 print "${pref} 22L);\n$longcheck"; 465 print "${pref} LO);\n$longcheck"; 466 print "${pref} HI);\n$longcheck"; 467 } 468 elsif($type eq "CURLOPTTYPE_OFF_T") { 469 print "${fpref} OFF_NO);\n$flongcheckzero"; 470 print "$ifpresent"; 471 my $lvl = " " x 29; 472 print "${pref}\n${lvl}(curl_off_t)22);\n$longcheck"; 473 print "${pref} OFF_HI);\n$longcheck"; 474 print "${pref} OFF_LO);\n$longcheck"; 475 } 476 elsif(($type eq "CURLOPTTYPE_OBJECTPOINT") || 477 ($type eq "CURLOPTTYPE_CBPOINT")) { 478 if($name =~ /DEPENDS/) { 479 print "${fpref} dep);\n$fcheck"; 480 } 481 elsif($name =~ "SHARE") { 482 print "${fpref} share);\n$fcheck"; 483 } 484 elsif($name eq "CURLOPT_ERRORBUFFER") { 485 print "${fpref} errorbuffer);\n$fcheck"; 486 } 487 elsif(($name eq "CURLOPT_POSTFIELDS") || 488 ($name eq "CURLOPT_COPYPOSTFIELDS")) { 489 # set size to zero to avoid it being "illegal" 490 print " (void)curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 0);\n"; 491 print "${fpref} stringpointerextra);\n$fcheck"; 492 } 493 elsif($name eq "CURLOPT_HTTPPOST") { 494 print "${fpref} httppost);\n$fcheck"; 495 } 496 elsif($name eq "CURLOPT_MIMEPOST") { 497 print "${fpref} mimepost);\n$fcheck"; 498 } 499 elsif($name eq "CURLOPT_STDERR") { 500 print "${fpref} stream);\n$fcheck"; 501 } 502 else { 503 print "${fpref} &object);\n$fcheck"; 504 } 505 print "$ifpresent"; 506 print "${pref} NULL);\n$nullcheck"; 507 } 508 elsif($type eq "CURLOPTTYPE_SLISTPOINT") { 509 print "${fpref} slist);\n$fcheck"; 510 print "$ifpresent"; 511 print "${pref} NULL);\n$nullcheck"; 512 } 513 elsif($type eq "CURLOPTTYPE_FUNCTIONPOINT") { 514 if($name =~ /([^ ]*)FUNCTION/) { 515 my $l=lc($1); 516 $l =~ s/^curlopt_//; 517 print "${fpref}\n$i${l}cb);\n$fcheck"; 518 } 519 else { 520 print "${fpref} &func);\n$fcheck"; 521 } 522 print "$ifpresent"; 523 print "${pref} NULL);\n$nullcheck"; 524 } 525 elsif($type eq "CURLOPTTYPE_BLOB") { 526 print "${fpref} &blob);\n$check"; 527 print "$ifpresent"; 528 print "${pref} NULL);\n$nullcheck"; 529 } 530 else { 531 print STDERR "\nUnknown type: $type\n"; 532 exit 22; # exit to make this noticed! 533 } 534 535 print <<MOO 536 } /* end of secondary checks */ 537 } /* end of single setopt */ 538MOO 539 ; 540 } 541 elsif($_ =~ /^CURLINFO_NONE/) { 542 $infomode = 1; 543 } 544 elsif($infomode && 545 ($_ =~ /^CURLINFO_([^ ]*) *= *CURLINFO_([^ ]*)/)) { 546 my ($info, $type)=($1, $2); 547 my $c = " res = curl_easy_getinfo(curl, CURLINFO_$info,"; 548 my $check = " if(res)\n geterr(\"$info\", res, __LINE__);\n"; 549 if($type eq "STRING") { 550 print "$c &charp);\n$check"; 551 } 552 elsif($type eq "LONG") { 553 print "$c &val);\n$check"; 554 } 555 elsif($type eq "OFF_T") { 556 print "$c &oval);\n$check"; 557 } 558 elsif($type eq "DOUBLE") { 559 print "$c &dval);\n$check"; 560 } 561 elsif($type eq "SLIST") { 562 print "$c &slist);\n$check"; 563 print " if(slist)\n curl_slist_free_all(slist);\n"; 564 } 565 elsif($type eq "SOCKET") { 566 print "$c &sockfd);\n$check"; 567 } 568 elsif($type eq "PTR") { 569 if($info eq "CERTINFO") { 570 print "$c &certinfo);\n$check"; 571 } 572 elsif(($info eq "TLS_SESSION") || 573 ($info eq "TLS_SSL_PTR")) { 574 print "$c &tlssession);\n$check"; 575 } 576 else { 577 print STDERR "$info/$type is unsupported\n"; 578 } 579 } 580 else { 581 print STDERR "$type is unsupported\n"; 582 } 583 } 584} 585 586 587print <<FOOTER 588 ) 589 590 curl_easy_setopt(curl, (CURLoption)1, 0); 591 res = CURLE_OK; 592test_cleanup: 593 curl_easy_cleanup(curl); 594 curl_easy_cleanup(dep); 595 curl_share_cleanup(share); 596 curl_global_cleanup(); 597 598 if(!res) 599 puts("ok"); 600 return res; 601} 602FOOTER 603 ; 604