Memory Leak
What the report claims
Memory leak in getstr() via strdup() in tool_getparam.c
Compare with curl's recorded outcome
Labeled AI slop
curl's maintainer lists this report as AI slop
Shown for comparison after analysis. The pipeline did not see this label.
ProveIt's finding
The code does what the report says, but curl's own policy may exclude it. A maintainer decides.
curl policy: Small memory leaksSee the withdrawn model reasoning
The following reasoning failed the citation check and does not support the final finding.
- curl is a command-line tool that runs once and exits; the OS reclaims all memory on process termination
- The project policy explicitly states: 'We do not consider a small memory leak a security problem' for long-living applications, and a CLI tool that exits is an even clearer case
- The leak does not give an attacker any access, data, code execution, or denial of service they should not have
- The allocation occurs once per option parsing and persists only until main() returns; there is no repeated allocation loop that could cause unbounded growth during a single run
- The ASAN-detected leak of 2 bytes in 1 allocation is a one-time cleanup omission at program exit, not a security vulnerability
How this analysis ran 5 claims · 9 citations verified
Evidence check: the behavior is real; the project's policy section 'Small memory leaks' may exclude it
Checked against curl master on 2025-05-09 (cd7904f5a970). Dev evaluation split. Citation verification checks that a referenced line was in the evidence; it does not prove the model interpreted it correctly.
Inspect the withdrawn draft reply
This draft belongs to the withdrawn judgment. It may contain unsupported claims.
Thank you for the report. The memory allocation you identified in getstr() (src/tool_getparam.c:57) does persist until program exit, but curl is a command-line tool that runs once and terminates. The operating system reclaims all process memory on exit, so this does not constitute a security vulnerability. Our policy explicitly states that small memory leaks are not considered security issues, especially for short-lived CLI tools. The ASAN detection is accurate for a one-time cleanup omission, but it does not enable any attack.
Inspect all claims and source code 5 claims · 11 code excerpts
This model judgment was withdrawn. The claim assessments below are preserved for inspection and may be wrong.
Report claims
strdup() is used without a corresponding free() before program termination, causing a memory leak
Read the reasoning
The code confirms strdup() is used in getstr() to allocate strings for config fields. The provided code snippets do not show a cleanup function that frees these allocations before main() returns. However, the leak only persists until process termination.
Line 2754 in src/tool_getparam.c, inside getstr() function
Read the reasoning
The report references line 2754 in getparameter(), but the provided code shows getstr() at lines 47-62 with strdup at line 57. Line numbers differ between versions, but the function and allocation site are correctly identified.
User-provided configuration values that reach getparameter() → parseconfig() → getstr()
Read the reasoning
User-provided configuration values from config files or command line reach getparameter() via parseconfig() and parse_args(), which then call getstr() for string-type options.
Persistent heap allocation that is never freed, leading to uncontrolled heap growth
Read the reasoning
The allocated strings remain in the config structures until program exit. The ASAN output confirms a 2-byte leak. However, this is a one-time allocation per program run, not uncontrolled heap growth during execution.
Run curl with ASAN_OPTIONS="detect_leaks=1:verbosity=2:malloc_context_size=50" ./curl -K <crash-file> to trigger the leak
Read the reasoning
The reproduction command uses AddressSanitizer with leak detection enabled, which would detect the allocation from strdup() in getstr() when processing a config file via -K flag.
Read the original report (excerpt)
Source code
| 1676 | ParameterError getparameter(const char *flag, /* f or -long-flag */ |
| 1677 | const char *nextarg, /* NULL if unset */ |
| 1678 | argv_item_t cleararg1, |
| 1679 | argv_item_t cleararg2, |
| 1680 | bool *usedarg, /* set to TRUE if the arg |
| 1681 | has been used */ |
| 1682 | struct GlobalConfig *global, |
| 1683 | struct OperationConfig *config) |
| 1684 | { |
| 1685 | const char *parse = NULL; |
| 1686 | bool longopt = FALSE; |
| 1687 | bool singleopt = FALSE; /* when true means '-o foo' used '-ofoo' */ |
| 1688 | size_t nopts = 0; /* options processed in `flag`*/ |
| 1689 | ParameterError err = PARAM_OK; |
| 1690 | bool toggle = TRUE; /* how to switch boolean options, on or off. Controlled |
| 1691 | by using --OPTION or --no-OPTION */ |
| 1692 | bool nextalloc = FALSE; /* if nextarg is allocated */ |
| 1693 | static const char *redir_protos[] = { |
| 1694 | "http", |
| 1695 | "https", |
| 1696 | "ftp", |
| 1697 | "ftps", |
| 1698 | NULL |
| 1699 | }; |
| 1700 | const struct LongShort *a = NULL; |
| 1701 | curl_off_t value; |
| 1702 | #ifdef HAVE_WRITABLE_ARGV |
| 1703 | argv_item_t clearthis = NULL; |
| 1704 | #else |
| 1705 | (void)cleararg1; |
| 1706 | (void)cleararg2; |
| 1707 | #endif |
| 1708 | |
| 1709 | *usedarg = FALSE; /* default is that we do not use the arg */ |
| 1710 | |
| 1711 | if(('-' != flag[0]) || ('-' == flag[1])) { |
| 1712 | /* this should be a long name */ |
| 1713 | const char *word = ('-' == flag[0]) ? flag + 2 : flag; |
| 1714 | bool noflagged = FALSE; |
| 1715 | bool expand = FALSE; |
| 1716 | |
| 1717 | if(!strncmp(word, "no-", 3)) { |
| 1718 | /* disable this option but ignore the "no-" part when looking for it */ |
| 1719 | word += 3; |
| 1720 | toggle = FALSE; |
| 1721 | noflagged = TRUE; |
| 1722 | } |
| 1723 | else if(!strncmp(word, "expand-", 7)) { |
| 1724 | /* variable expansions is to be done on the argument */ |
| 1725 | word += 7; |
| 1726 | expand = TRUE; |
| 1727 | } |
| 1728 | |
| 1729 | a = findlongopt(word); |
| 1730 | if(a) { |
| 1731 | longopt = TRUE; |
| 1732 | } |
| 1733 | else { |
| 1734 | err = PARAM_OPTION_UNKNOWN; |
| 1735 | goto error; |
| 1736 | } |
| 1737 | if(noflagged && (ARGTYPE(a->desc) != ARG_BOOL)) { |
| 1738 | /* --no- prefixed an option that is not boolean! */ |
| 1739 | err = PARAM_NO_NOT_BOOLEAN; |
| 1740 | goto error; |
| 1741 | } |
| 1742 | else if(expand && nextarg) { |
| 1743 | struct dynbuf nbuf; |
| 1744 | bool replaced; |
| 1745 | |
| 1746 | if((ARGTYPE(a->desc) != ARG_STRG) && |
| 1747 | (ARGTYPE(a->desc) != ARG_FILE)) { |
| 1748 | /* --expand on an option that is not a string or a filename */ |
| 1749 | err = PARAM_EXPAND_ERROR; |
| 1750 | goto error; |
| 1751 | } |
| 1752 | err = varexpand(global, nextarg, &nbuf, &replaced); |
| 1753 | if(err) { |
| 1754 | curlx_dyn_free(&nbuf); |
| 1755 | goto error; |
| 1756 | } |
| 1757 | if(replaced) { |
| 1758 | nextarg = curlx_dyn_ptr(&nbuf); |
| 1759 | nextalloc = TRUE; |
| 1760 | } |
| 1761 | } |
| 1762 | } |
| 1763 | else { |
| 1764 | flag++; /* prefixed with one dash, pass it */ |
| 1765 | parse = flag; |
| 1766 | } |
| 1767 | |
| 1768 | do { |
| 1769 | /* we can loop here if we have multiple single-letters */ |
| 1770 | cmdline_t cmd; |
| 1771 | |
| 1772 | if(!longopt && !a) { |
| 1773 | a = findshortopt(*parse); |
| 1774 | if(!a) { |
| 1775 | err = PARAM_OPTION_UNKNOWN; |
| 1776 | break; |
| 1777 | } |
| 1778 | } |
| 1779 | cmd = (cmdline_t)a->cmd; |
| 1780 | if(ARGTYPE(a->desc) >= ARG_STRG) { |
| 1781 | /* this option requires an extra parameter */ |
| 1782 | if(!longopt && parse[1]) { |
| 1783 | nextarg = &parse[1]; /* this is the actual extra parameter */ |
| 1784 | singleopt = TRUE; /* do not loop anymore after this */ |
| 1785 | #ifdef HAVE_WRITABLE_ARGV |
| 1786 | if(cleararg1) |
| 1787 | clearthis = &cleararg1[parse + 2 - flag]; |
| 1788 | #endif |
| 1789 | } |
| 1790 | else if(!nextarg) { |
| 1791 | err = PARAM_REQUIRES_PARAMETER; |
| 1792 | break; |
| 1793 | } |
| 1794 | else { |
| 1795 | #ifdef HAVE_WRITABLE_ARGV |
| 1796 | if(cleararg2) |
| 1797 | clearthis = cleararg2; |
| 1798 | #endif |
| 1799 | *usedarg = TRUE; /* mark it as used */ |
| 1800 | } |
| 1801 | |
| 1802 | if((ARGTYPE(a->desc) == ARG_FILE) && |
| 1803 | (nextarg[0] == '-') && nextarg[1]) { |
| 1804 | /* if the filename looks like a command line option */ |
| 1805 | warnf(global, "The filename argument '%s' looks like a flag.", |
| 1806 | nextarg); |
| 1807 | } |
| 1808 | else if(!strncmp("\xe2\x80\x9c", nextarg, 3)) { |
| 1809 | warnf(global, "The argument '%s' starts with a Unicode quote where " |
| 1810 | "maybe an ASCII \" was intended?", |
| 1811 | nextarg); |
| 1812 | } |
| 1813 | } |
| 1814 | else if((ARGTYPE(a->desc) == ARG_NONE) && !toggle) { |
| 1815 | err = PARAM_NO_PREFIX; |
| 1816 | break; |
| 1817 | } |
| 1818 | else if((a->desc & ARG_TLS) && !feature_ssl) { |
| 1819 | err = PARAM_LIBCURL_DOESNT_SUPPORT; |
| 1820 | break; |
| 1821 | } |
| 1822 | |
| 1823 | if(!nextarg) |
| 1824 | /* this is a precaution mostly to please scan-build, as all arguments |
| 1825 | that use nextarg should be marked as such and they will check that |
| 1826 | nextarg is set before continuing, but code analyzers are not always |
| 1827 | that aware of that state */ |
| 1828 | nextarg = ""; |
| 1829 | |
| 1830 | switch(cmd) { |
| C3: getparameter() switch statement handles various options that call getstr() for string parameters | |
| 1831 | case C_RANDOM_FILE: /* --random-file */ |
| 1832 | case C_EGD_FILE: /* --egd-file */ |
| 1833 | case C_NTLM_WB: /* --ntlm-wb */ |
| 1834 | warnf(global, "--%s is deprecated and has no function anymore", |
| 1835 | a->lname); |
| 1836 | break; |
| 47 | static ParameterError getstr(char **str, const char *val, bool allowblank) |
| C2: getstr() function definition starts at line 47 | |
| 48 | { |
| 49 | if(*str) { |
| C1: getstr() frees previous *str at lines 49-51 before allocating new memory, but no cleanup function is shown in provided code that frees these strings at program exit | |
| 50 | free(*str); |
| 51 | *str = NULL; |
| 52 | } |
| 53 | if(val) { |
| 54 | if(!allowblank && !val[0]) |
| 55 | return PARAM_BLANK_STRING; |
| 56 | |
| 57 | *str = strdup(val); |
| C1: getstr() calls strdup(val) at line 57, allocating memory that is assigned to *str | |
| C2: strdup() call at line 57 inside getstr() | |
| C4: strdup() allocates memory that persists in config struct fields | |
| C5: strdup() allocation site detected by ASAN | |
| 58 | if(!*str) |
| 59 | return PARAM_NO_MEM; |
| 60 | } |
| 61 | return PARAM_OK; |
| 62 | } |
| 238 | int main(int argc, char *argv[]) |
| 239 | #endif |
| 240 | { |
| 241 | CURLcode result = CURLE_OK; |
| 242 | struct GlobalConfig global; |
| 243 | memset(&global, 0, sizeof(global)); |
| 244 | |
| 245 | tool_init_stderr(); |
| 246 | |
| 247 | #if defined(_WIN32) && !defined(UNDER_CE) |
| 248 | /* Undocumented diagnostic option to list the full paths of all loaded |
| 249 | modules. This is purposely pre-init. */ |
| 250 | if(argc == 2 && !_tcscmp(argv[1], _T("--dump-module-paths"))) { |
| 251 | struct curl_slist *item, *head = GetLoadedModulePaths(); |
| 252 | for(item = head; item; item = item->next) |
| 253 | printf("%s\n", item->data); |
| 254 | curl_slist_free_all(head); |
| 255 | return head ? 0 : 1; |
| 256 | } |
| 257 | #endif |
| 258 | #ifdef _WIN32 |
| 259 | /* win32_init must be called before other init routines. */ |
| 260 | result = win32_init(); |
| 261 | if(result) { |
| 262 | errorf(&global, "(%d) Windows-specific init failed", result); |
| 263 | return (int)result; |
| 264 | } |
| 265 | #endif |
| 266 | |
| 267 | if(main_checkfds()) { |
| 268 | errorf(&global, "out of file descriptors"); |
| 269 | return CURLE_FAILED_INIT; |
| 270 | } |
| 271 | |
| 272 | #if defined(HAVE_SIGNAL) && defined(SIGPIPE) |
| 273 | (void)signal(SIGPIPE, SIG_IGN); |
| 274 | #endif |
| 275 | |
| 276 | /* Initialize memory tracking */ |
| 277 | memory_tracking_init(); |
| 278 | |
| 279 | /* Initialize the curl library - do not call any libcurl functions before |
| 280 | this point */ |
| 281 | result = main_init(&global); |
| 282 | if(!result) { |
| 283 | /* Start our curl operation */ |
| 284 | result = operate(&global, argc, argv); |
| 285 | |
| 286 | /* Perform the main cleanup */ |
| 287 | main_free(&global); |
| C4: main() calls main_free(&global) but its implementation is not shown in provided code | |
| 288 | } |
| 289 | |
| 290 | #ifdef _WIN32 |
| 291 | /* Flush buffers of all streams opened in write or update mode */ |
| 292 | fflush(NULL); |
| 293 | #endif |
| 294 | |
| 295 | #ifdef __VMS |
| 296 | vms_special_exit(result, vms_show); |
| 297 | #else |
| 298 | return (int)result; |
| 299 | #endif |
| 300 | } |
| 45 | int parseconfig(const char *filename, struct GlobalConfig *global) |
| 46 | { |
| 47 | FILE *file = NULL; |
| 48 | bool usedarg = FALSE; |
| 49 | int rc = 0; |
| 50 | struct OperationConfig *operation = global->last; |
| 51 | char *pathalloc = NULL; |
| 52 | |
| 53 | if(!filename) { |
| 54 | /* NULL means load .curlrc from homedir! */ |
| 55 | char *curlrc = findfile(".curlrc", CURLRC_DOTSCORE); |
| 56 | if(curlrc) { |
| 57 | file = fopen(curlrc, FOPEN_READTEXT); |
| 58 | if(!file) { |
| 59 | free(curlrc); |
| 60 | return 1; |
| 61 | } |
| 62 | filename = pathalloc = curlrc; |
| 63 | } |
| 64 | #if defined(_WIN32) && !defined(UNDER_CE) |
| 65 | else { |
| 66 | char *fullp; |
| 67 | /* check for .curlrc then _curlrc in the dir of the executable */ |
| 68 | file = tool_execpath(".curlrc", &fullp); |
| 69 | if(!file) |
| 70 | file = tool_execpath("_curlrc", &fullp); |
| 71 | if(file) |
| 72 | /* this is the filename we read from */ |
| 73 | filename = fullp; |
| 74 | } |
| 75 | #endif |
| 76 | } |
| 77 | else { |
| 78 | if(strcmp(filename, "-")) |
| 79 | file = fopen(filename, FOPEN_READTEXT); |
| 80 | else |
| 81 | file = stdin; |
| 82 | } |
| 83 | |
| 84 | if(file) { |
| 85 | char *line; |
| 86 | char *option; |
| 87 | char *param; |
| 88 | int lineno = 0; |
| 89 | bool dashed_option; |
| 90 | struct dynbuf buf; |
| 91 | bool fileerror = FALSE; |
| 92 | curlx_dyn_init(&buf, MAX_CONFIG_LINE_LENGTH); |
| 93 | DEBUGASSERT(filename); |
| 94 | |
| 95 | while(!rc && my_get_line(file, &buf, &fileerror)) { |
| 96 | ParameterError res; |
| 97 | bool alloced_param = FALSE; |
| 98 | lineno++; |
| 99 | line = curlx_dyn_ptr(&buf); |
| 100 | if(!line) { |
| 101 | rc = 1; /* out of memory */ |
| 102 | break; |
| 103 | } |
| 104 | |
| 105 | /* the option keywords starts here */ |
| 106 | option = line; |
| 107 | |
| 108 | /* the option starts with a dash? */ |
| 109 | dashed_option = (option[0] == '-'); |
| 110 | |
| 111 | while(*line && !ISBLANK(*line) && !ISSEP(*line, dashed_option)) |
| 112 | line++; |
| 113 | /* ... and has ended here */ |
| 114 | |
| 115 | if(*line) |
| 116 | *line++ = '\0'; /* null-terminate, we have a local copy of the data */ |
| 117 | |
| 118 | #ifdef DEBUG_CONFIG |
| 119 | fprintf(tool_stderr, "GOT: %s\n", option); |
| 120 | #endif |
| 121 | |
| 122 | /* pass spaces and separator(s) */ |
| 123 | while(ISBLANK(*line) || ISSEP(*line, dashed_option)) |
| 124 | line++; |
| 125 | |
| 126 | /* the parameter starts here (unless quoted) */ |
| 127 | if(*line == '\"') { |
| 128 | /* quoted parameter, do the quote dance */ |
| 129 | line++; |
| 130 | param = malloc(strlen(line) + 1); /* parameter */ |
| 131 | if(!param) { |
| 132 | /* out of memory */ |
| 133 | rc = 1; |
| 134 | break; |
| 135 | } |
| 136 | alloced_param = TRUE; |
| 137 | (void)unslashquote(line, param); |
| 138 | } |
| 139 | else { |
| 140 | param = line; /* parameter starts here */ |
| 141 | while(*line && !ISSPACE(*line)) /* stop also on CRLF */ |
| 142 | line++; |
| 143 | |
| 144 | if(*line) { |
| 145 | *line = '\0'; /* null-terminate */ |
| 146 | |
| 147 | /* to detect mistakes better, see if there is data following */ |
| 148 | line++; |
| 149 | /* pass all spaces */ |
| 150 | while(ISBLANK(*line)) |
| 151 | line++; |
| 152 | |
| 153 | switch(*line) { |
| 154 | case '\0': |
| 155 | case '\r': |
| 156 | case '\n': |
| 157 | case '#': /* comment */ |
| 158 | break; |
| 159 | default: |
| 160 | warnf(operation->global, "%s:%d: warning: '%s' uses unquoted " |
| 161 | "whitespace", filename, lineno, option); |
| 162 | warnf(operation->global, "This may cause side-effects. " |
| 163 | "Consider using double quotes?"); |
| 164 | } |
| 165 | } |
| 166 | if(!*param) |
| 167 | /* do this so getparameter can check for required parameters. |
| 168 | Otherwise it always thinks there is a parameter. */ |
| 169 | param = NULL; |
| 170 | } |
| 171 | |
| 172 | #ifdef DEBUG_CONFIG |
| 173 | fprintf(tool_stderr, "PARAM: \"%s\"\n",(param ? param : "(null)")); |
| 174 | #endif |
| 175 | res = getparameter(option, param, NULL, NULL, |
| C3: parseconfig() calls getparameter() at line 175 with user-provided config values | |
| 176 | &usedarg, global, operation); |
| 177 | operation = global->last; |
| 178 | |
| 179 | if(!res && param && *param && !usedarg) |
| 180 | /* we passed in a parameter that was not used! */ |
| 181 | res = PARAM_GOT_EXTRA_PARAMETER; |
| 182 | |
| 183 | if(res == PARAM_NEXT_OPERATION) { |
| 184 | if(operation->url_list && operation->url_list->url) { |
| 185 | /* Allocate the next config */ |
| 186 | operation->next = malloc(sizeof(struct OperationConfig)); |
| 187 | if(operation->next) { |
| 188 | /* Initialise the newly created config */ |
| 189 | config_init(operation->next); |
| 190 | |
| 191 | /* Set the global config pointer */ |
| 192 | operation->next->global = global; |
| 193 | |
| 194 | /* Update the last operation pointer */ |
| 195 | global->last = operation->next; |
| 196 | |
| 197 | /* Move onto the new config */ |
| 198 | operation->next->prev = operation; |
| 199 | operation = operation->next; |
| 200 | } |
| 201 | else |
| 202 | res = PARAM_NO_MEM; |
| 203 | } |
| 204 | } |
| 205 |
Show 161 lines (not cited by the judge)
| 1678 | ParameterError getparameter(const char *flag, /* f or -long-flag */ |
| 1679 | const char *nextarg, /* NULL if unset */ |
| 1680 | argv_item_t cleararg1, |
| 1681 | argv_item_t cleararg2, |
| 1682 | bool *usedarg, /* set to TRUE if the arg |
| 1683 | has been used */ |
| 1684 | struct GlobalConfig *global, |
| 1685 | struct OperationConfig *config) |
| 1686 | { |
| 1687 | const char *parse = NULL; |
| 1688 | bool longopt = FALSE; |
| 1689 | bool singleopt = FALSE; /* when true means '-o foo' used '-ofoo' */ |
| 1690 | size_t nopts = 0; /* options processed in `flag`*/ |
| 1691 | ParameterError err = PARAM_OK; |
| 1692 | bool toggle = TRUE; /* how to switch boolean options, on or off. Controlled |
| 1693 | by using --OPTION or --no-OPTION */ |
| 1694 | bool nextalloc = FALSE; /* if nextarg is allocated */ |
| 1695 | static const char *redir_protos[] = { |
| 1696 | "http", |
| 1697 | "https", |
| 1698 | "ftp", |
| 1699 | "ftps", |
| 1700 | NULL |
| 1701 | }; |
| 1702 | const struct LongShort *a = NULL; |
| 1703 | curl_off_t value; |
| 1704 | #ifdef HAVE_WRITABLE_ARGV |
| 1705 | argv_item_t clearthis = NULL; |
| 1706 | #else |
| 1707 | (void)cleararg1; |
| 1708 | (void)cleararg2; |
| 1709 | #endif |
| 1710 | |
| 1711 | *usedarg = FALSE; /* default is that we do not use the arg */ |
| 1712 | |
| 1713 | if(('-' != flag[0]) || ('-' == flag[1])) { |
| 1714 | /* this should be a long name */ |
| 1715 | const char *word = ('-' == flag[0]) ? flag + 2 : flag; |
| 1716 | bool noflagged = FALSE; |
| 1717 | bool expand = FALSE; |
| 1718 | |
| 1719 | if(!strncmp(word, "no-", 3)) { |
| 1720 | /* disable this option but ignore the "no-" part when looking for it */ |
| 1721 | word += 3; |
| 1722 | toggle = FALSE; |
| 1723 | noflagged = TRUE; |
| 1724 | } |
| 1725 | else if(!strncmp(word, "expand-", 7)) { |
| 1726 | /* variable expansions is to be done on the argument */ |
| 1727 | word += 7; |
| 1728 | expand = TRUE; |
| 1729 | } |
| 1730 | |
| 1731 | a = findlongopt(word); |
| 1732 | if(a) { |
| 1733 | longopt = TRUE; |
| 1734 | } |
| 1735 | else { |
| 1736 | err = PARAM_OPTION_UNKNOWN; |
| 1737 | goto error; |
| 1738 | } |
| 1739 | if(noflagged && (ARGTYPE(a->desc) != ARG_BOOL)) { |
| 1740 | /* --no- prefixed an option that is not boolean! */ |
| 1741 | err = PARAM_NO_NOT_BOOLEAN; |
| 1742 | goto error; |
| 1743 | } |
| 1744 | else if(expand && nextarg) { |
| 1745 | struct curlx_dynbuf nbuf; |
| 1746 | bool replaced; |
| 1747 | |
| 1748 | if((ARGTYPE(a->desc) != ARG_STRG) && |
| 1749 | (ARGTYPE(a->desc) != ARG_FILE)) { |
| 1750 | /* --expand on an option that is not a string or a filename */ |
| 1751 | err = PARAM_EXPAND_ERROR; |
| 1752 | goto error; |
| 1753 | } |
| 1754 | err = varexpand(global, nextarg, &nbuf, &replaced); |
| 1755 | if(err) { |
| 1756 | curlx_dyn_free(&nbuf); |
| 1757 | goto error; |
| 1758 | } |
| 1759 | if(replaced) { |
| 1760 | nextarg = curlx_dyn_ptr(&nbuf); |
| 1761 | nextalloc = TRUE; |
| 1762 | } |
| 1763 | } |
| 1764 | } |
| 1765 | else { |
| 1766 | flag++; /* prefixed with one dash, pass it */ |
| 1767 | parse = flag; |
| 1768 | } |
| 1769 | |
| 1770 | do { |
| 1771 | /* we can loop here if we have multiple single-letters */ |
| 1772 | cmdline_t cmd; |
| 1773 | |
| 1774 | if(!longopt && !a) { |
| 1775 | a = findshortopt(*parse); |
| 1776 | if(!a) { |
| 1777 | err = PARAM_OPTION_UNKNOWN; |
| 1778 | break; |
| 1779 | } |
| 1780 | } |
| 1781 | cmd = (cmdline_t)a->cmd; |
| 1782 | if(ARGTYPE(a->desc) >= ARG_STRG) { |
| 1783 | /* this option requires an extra parameter */ |
| 1784 | if(!longopt && parse[1]) { |
| 1785 | nextarg = &parse[1]; /* this is the actual extra parameter */ |
| 1786 | singleopt = TRUE; /* do not loop anymore after this */ |
| 1787 | #ifdef HAVE_WRITABLE_ARGV |
| 1788 | clearthis = &cleararg1[parse + 2 - flag]; |
| 1789 | #endif |
| 1790 | } |
| 1791 | else if(!nextarg) { |
| 1792 | err = PARAM_REQUIRES_PARAMETER; |
| 1793 | break; |
| 1794 | } |
| 1795 | else { |
| 1796 | #ifdef HAVE_WRITABLE_ARGV |
| 1797 | clearthis = cleararg2; |
| 1798 | #endif |
| 1799 | *usedarg = TRUE; /* mark it as used */ |
| 1800 | } |
| 1801 | |
| 1802 | if((ARGTYPE(a->desc) == ARG_FILE) && |
| 1803 | (nextarg[0] == '-') && nextarg[1]) { |
| 1804 | /* if the filename looks like a command line option */ |
| 1805 | warnf(global, "The filename argument '%s' looks like a flag.", |
| 1806 | nextarg); |
| 1807 | } |
| 1808 | else if(!strncmp("\xe2\x80\x9c", nextarg, 3)) { |
| 1809 | warnf(global, "The argument '%s' starts with a Unicode quote where " |
| 1810 | "maybe an ASCII \" was intended?", |
| 1811 | nextarg); |
| 1812 | } |
| 1813 | } |
| 1814 | else if((ARGTYPE(a->desc) == ARG_NONE) && !toggle) { |
| 1815 | err = PARAM_NO_PREFIX; |
| 1816 | break; |
| 1817 | } |
| 1818 | else if((a->desc & ARG_TLS) && !feature_ssl) { |
| 1819 | err = PARAM_LIBCURL_DOESNT_SUPPORT; |
| 1820 | break; |
| 1821 | } |
| 1822 | |
| 1823 | if(!nextarg) |
| 1824 | /* this is a precaution mostly to please scan-build, as all arguments |
| 1825 | that use nextarg should be marked as such and they will check that |
| 1826 | nextarg is set before continuing, but code analyzers are not always |
| 1827 | that aware of that state */ |
| 1828 | nextarg = ""; |
| 1829 | |
| 1830 | switch(cmd) { |
| 1831 | case C_RANDOM_FILE: /* --random-file */ |
| 1832 | case C_EGD_FILE: /* --egd-file */ |
| 1833 | case C_NTLM_WB: /* --ntlm-wb */ |
| 1834 | warnf(global, "--%s is deprecated and has no function anymore", |
| 1835 | a->lname); |
| 1836 | break; |
| 1837 | case C_DNS_IPV4_ADDR: /* --dns-ipv4-addr */ |
| 1838 | if(!curlinfo->ares_num) /* c-ares is needed for this */ |
Show 12 lines (not cited by the judge)
| 243 | int main(int argc, char **argv) |
| 244 | { |
| 245 | int i; |
| 246 | |
| 247 | (void) argc; |
| 248 | (void) argv; |
| 249 | |
| 250 | for(i = 0; disabled[i]; i++) |
| 251 | printf("%s\n", disabled[i]); |
| 252 | |
| 253 | return 0; |
| 254 | } |
Show 143 lines (not cited by the judge)
| 3153 | CURLcode operate(struct GlobalConfig *global, int argc, argv_item_t argv[]) |
| 3154 | { |
| 3155 | CURLcode result = CURLE_OK; |
| 3156 | const char *first_arg; |
| 3157 | #ifdef UNDER_CE |
| 3158 | first_arg = argc > 1 ? strdup(argv[1]) : NULL; |
| 3159 | #else |
| 3160 | first_arg = argc > 1 ? convert_tchar_to_UTF8(argv[1]) : NULL; |
| 3161 | #endif |
| 3162 | |
| 3163 | #ifdef HAVE_SETLOCALE |
| 3164 | /* Override locale for number parsing (only) */ |
| 3165 | setlocale(LC_ALL, ""); |
| 3166 | setlocale(LC_NUMERIC, "C"); |
| 3167 | #endif |
| 3168 | |
| 3169 | /* Parse .curlrc if necessary */ |
| 3170 | if((argc == 1) || |
| 3171 | (first_arg && strncmp(first_arg, "-q", 2) && |
| 3172 | strcmp(first_arg, "--disable"))) { |
| 3173 | parseconfig(NULL, global); /* ignore possible failure */ |
| 3174 | |
| 3175 | /* If we had no arguments then make sure a url was specified in .curlrc */ |
| 3176 | if((argc < 2) && (!global->first->url_list)) { |
| 3177 | helpf(tool_stderr, NULL); |
| 3178 | result = CURLE_FAILED_INIT; |
| 3179 | } |
| 3180 | } |
| 3181 | |
| 3182 | unicodefree(first_arg); |
| 3183 | |
| 3184 | if(!result) { |
| 3185 | /* Parse the command line arguments */ |
| 3186 | ParameterError res = parse_args(global, argc, argv); |
| 3187 | if(res) { |
| 3188 | result = CURLE_OK; |
| 3189 | |
| 3190 | /* Check if we were asked for the help */ |
| 3191 | if(res == PARAM_HELP_REQUESTED) |
| 3192 | tool_help(global->help_category); |
| 3193 | /* Check if we were asked for the manual */ |
| 3194 | else if(res == PARAM_MANUAL_REQUESTED) { |
| 3195 | #ifdef USE_MANUAL |
| 3196 | hugehelp(); |
| 3197 | #else |
| 3198 | puts("built-in manual was disabled at build-time"); |
| 3199 | #endif |
| 3200 | } |
| 3201 | /* Check if we were asked for the version information */ |
| 3202 | else if(res == PARAM_VERSION_INFO_REQUESTED) |
| 3203 | tool_version_info(); |
| 3204 | /* Check if we were asked to list the SSL engines */ |
| 3205 | else if(res == PARAM_ENGINES_REQUESTED) |
| 3206 | tool_list_engines(); |
| 3207 | /* Check if we were asked to dump the embedded CA bundle */ |
| 3208 | else if(res == PARAM_CA_EMBED_REQUESTED) { |
| 3209 | #ifdef CURL_CA_EMBED |
| 3210 | printf("%s", curl_ca_embed); |
| 3211 | #endif |
| 3212 | } |
| 3213 | else if(res == PARAM_LIBCURL_UNSUPPORTED_PROTOCOL) |
| 3214 | result = CURLE_UNSUPPORTED_PROTOCOL; |
| 3215 | else if(res == PARAM_READ_ERROR) |
| 3216 | result = CURLE_READ_ERROR; |
| 3217 | else |
| 3218 | result = CURLE_FAILED_INIT; |
| 3219 | } |
| 3220 | else { |
| 3221 | if(global->libcurl) { |
| 3222 | /* Initialise the libcurl source output */ |
| 3223 | result = easysrc_init(); |
| 3224 | } |
| 3225 | |
| 3226 | /* Perform the main operations */ |
| 3227 | if(!result) { |
| 3228 | size_t count = 0; |
| 3229 | struct OperationConfig *operation = global->first; |
| 3230 | CURLSH *share = curl_share_init(); |
| 3231 | if(!share) { |
| 3232 | if(global->libcurl) { |
| 3233 | /* Cleanup the libcurl source output */ |
| 3234 | easysrc_cleanup(); |
| 3235 | } |
| 3236 | result = CURLE_OUT_OF_MEMORY; |
| 3237 | } |
| 3238 | |
| 3239 | if(!result) { |
| 3240 | curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE); |
| 3241 | curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); |
| 3242 | curl_share_setopt(share, CURLSHOPT_SHARE, |
| 3243 | CURL_LOCK_DATA_SSL_SESSION); |
| 3244 | /* Running parallel, use the multi connection cache */ |
| 3245 | if(!global->parallel) |
| 3246 | curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT); |
| 3247 | curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_PSL); |
| 3248 | curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_HSTS); |
| 3249 | |
| 3250 | if(global->ssl_sessions && feature_ssls_export) |
| 3251 | result = tool_ssls_load(global, global->first, share, |
| 3252 | global->ssl_sessions); |
| 3253 | |
| 3254 | if(!result) { |
| 3255 | /* Get the required arguments for each operation */ |
| 3256 | do { |
| 3257 | result = get_args(operation, count++); |
| 3258 | |
| 3259 | operation = operation->next; |
| 3260 | } while(!result && operation); |
| 3261 | |
| 3262 | /* Set the current operation pointer */ |
| 3263 | global->current = global->first; |
| 3264 | |
| 3265 | /* now run! */ |
| 3266 | result = run_all_transfers(global, share, result); |
| 3267 | |
| 3268 | if(global->ssl_sessions && feature_ssls_export) { |
| 3269 | CURLcode r2 = tool_ssls_save(global, global->first, share, |
| 3270 | global->ssl_sessions); |
| 3271 | if(r2 && !result) |
| 3272 | result = r2; |
| 3273 | } |
| 3274 | } |
| 3275 | |
| 3276 | curl_share_cleanup(share); |
| 3277 | if(global->libcurl) { |
| 3278 | /* Cleanup the libcurl source output */ |
| 3279 | easysrc_cleanup(); |
| 3280 | |
| 3281 | /* Dump the libcurl code if previously enabled */ |
| 3282 | dumpeasysrc(global); |
| 3283 | } |
| 3284 | } |
| 3285 | } |
| 3286 | else |
| 3287 | errorf(global, "out of memory"); |
| 3288 | } |
| 3289 | } |
| 3290 | |
| 3291 | varcleanup(global); |
| 3292 | curl_free(global->knownhosts); |
| 3293 | |
| 3294 | return result; |
| 3295 | } |
Show 105 lines (not cited by the judge)
| 2988 | ParameterError parse_args(struct GlobalConfig *global, int argc, |
| 2989 | argv_item_t argv[]) |
| 2990 | { |
| 2991 | int i; |
| 2992 | bool stillflags; |
| 2993 | const char *orig_opt = NULL; |
| 2994 | ParameterError result = PARAM_OK; |
| 2995 | struct OperationConfig *config = global->first; |
| 2996 | |
| 2997 | for(i = 1, stillflags = TRUE; i < argc && !result; i++) { |
| 2998 | orig_opt = convert_tchar_to_UTF8(argv[i]); |
| 2999 | if(!orig_opt) |
| 3000 | return PARAM_NO_MEM; |
| 3001 | |
| 3002 | if(stillflags && ('-' == orig_opt[0])) { |
| 3003 | bool passarg; |
| 3004 | |
| 3005 | if(!strcmp("--", orig_opt)) |
| 3006 | /* This indicates the end of the flags and thus enables the |
| 3007 | following (URL) argument to start with -. */ |
| 3008 | stillflags = FALSE; |
| 3009 | else { |
| 3010 | const char *nextarg = NULL; |
| 3011 | if(i < (argc - 1)) { |
| 3012 | nextarg = convert_tchar_to_UTF8(argv[i + 1]); |
| 3013 | if(!nextarg) { |
| 3014 | unicodefree(orig_opt); |
| 3015 | return PARAM_NO_MEM; |
| 3016 | } |
| 3017 | } |
| 3018 | |
| 3019 | result = getparameter(orig_opt, nextarg, argv[i], argv[i + 1], |
| 3020 | &passarg, global, config); |
| 3021 | |
| 3022 | unicodefree(nextarg); |
| 3023 | config = global->last; |
| 3024 | if(result == PARAM_NEXT_OPERATION) { |
| 3025 | /* Reset result as PARAM_NEXT_OPERATION is only used here and not |
| 3026 | returned from this function */ |
| 3027 | result = PARAM_OK; |
| 3028 | |
| 3029 | if(config->url_list && config->url_list->url) { |
| 3030 | /* Allocate the next config */ |
| 3031 | config->next = malloc(sizeof(struct OperationConfig)); |
| 3032 | if(config->next) { |
| 3033 | /* Initialise the newly created config */ |
| 3034 | config_init(config->next); |
| 3035 | |
| 3036 | /* Set the global config pointer */ |
| 3037 | config->next->global = global; |
| 3038 | |
| 3039 | /* Update the last config pointer */ |
| 3040 | global->last = config->next; |
| 3041 | |
| 3042 | /* Move onto the new config */ |
| 3043 | config->next->prev = config; |
| 3044 | config = config->next; |
| 3045 | } |
| 3046 | else |
| 3047 | result = PARAM_NO_MEM; |
| 3048 | } |
| 3049 | else { |
| 3050 | errorf(global, "missing URL before --next"); |
| 3051 | result = PARAM_BAD_USE; |
| 3052 | } |
| 3053 | } |
| 3054 | else if(!result && passarg) |
| 3055 | i++; /* we are supposed to skip this */ |
| 3056 | } |
| 3057 | } |
| 3058 | else { |
| 3059 | bool used; |
| 3060 | |
| 3061 | /* Just add the URL please */ |
| 3062 | result = getparameter("--url", orig_opt, NULL, NULL, |
| 3063 | &used, global, config); |
| 3064 | } |
| 3065 | |
| 3066 | if(!result) { |
| 3067 | unicodefree(orig_opt); |
| 3068 | orig_opt = NULL; |
| 3069 | } |
| 3070 | } |
| 3071 | |
| 3072 | if(!result && config->content_disposition) { |
| 3073 | if(config->resume_from_current) |
| 3074 | result = PARAM_CONTDISP_RESUME_FROM; |
| 3075 | } |
| 3076 | |
| 3077 | if(result && result != PARAM_HELP_REQUESTED && |
| 3078 | result != PARAM_MANUAL_REQUESTED && |
| 3079 | result != PARAM_VERSION_INFO_REQUESTED && |
| 3080 | result != PARAM_ENGINES_REQUESTED && |
| 3081 | result != PARAM_CA_EMBED_REQUESTED) { |
| 3082 | const char *reason = param2text(result); |
| 3083 | |
| 3084 | if(orig_opt && strcmp(":", orig_opt)) |
| 3085 | helpf(tool_stderr, "option %s: %s", orig_opt, reason); |
| 3086 | else |
| 3087 | helpf(tool_stderr, "%s", reason); |
| 3088 | } |
| 3089 | |
| 3090 | unicodefree(orig_opt); |
| 3091 | return result; |
| 3092 | } |
Show 103 lines (not cited by the judge)
| 2985 | ParameterError parse_args(struct GlobalConfig *global, int argc, |
| 2986 | argv_item_t argv[]) |
| 2987 | { |
| 2988 | int i; |
| 2989 | bool stillflags; |
| 2990 | const char *orig_opt = NULL; |
| 2991 | ParameterError result = PARAM_OK; |
| 2992 | struct OperationConfig *config = global->first; |
| 2993 | |
| 2994 | for(i = 1, stillflags = TRUE; i < argc && !result; i++) { |
| 2995 | orig_opt = convert_tchar_to_UTF8(argv[i]); |
| 2996 | if(!orig_opt) |
| 2997 | return PARAM_NO_MEM; |
| 2998 | |
| 2999 | if(stillflags && ('-' == orig_opt[0])) { |
| 3000 | bool passarg; |
| 3001 | |
| 3002 | if(!strcmp("--", orig_opt)) |
| 3003 | /* This indicates the end of the flags and thus enables the |
| 3004 | following (URL) argument to start with -. */ |
| 3005 | stillflags = FALSE; |
| 3006 | else { |
| 3007 | const char *nextarg = NULL; |
| 3008 | if(i < (argc - 1)) { |
| 3009 | nextarg = convert_tchar_to_UTF8(argv[i + 1]); |
| 3010 | if(!nextarg) { |
| 3011 | unicodefree(orig_opt); |
| 3012 | return PARAM_NO_MEM; |
| 3013 | } |
| 3014 | } |
| 3015 | |
| 3016 | result = getparameter(orig_opt, nextarg, argv[i], argv[i + 1], |
| 3017 | &passarg, global, config); |
| 3018 | |
| 3019 | unicodefree(nextarg); |
| 3020 | config = global->last; |
| 3021 | if(result == PARAM_NEXT_OPERATION) { |
| 3022 | /* Reset result as PARAM_NEXT_OPERATION is only used here and not |
| 3023 | returned from this function */ |
| 3024 | result = PARAM_OK; |
| 3025 | |
| 3026 | if(config->url_list && config->url_list->url) { |
| 3027 | /* Allocate the next config */ |
| 3028 | config->next = malloc(sizeof(struct OperationConfig)); |
| 3029 | if(config->next) { |
| 3030 | /* Initialise the newly created config */ |
| 3031 | config_init(config->next); |
| 3032 | |
| 3033 | /* Set the global config pointer */ |
| 3034 | config->next->global = global; |
| 3035 | |
| 3036 | /* Update the last config pointer */ |
| 3037 | global->last = config->next; |
| 3038 | |
| 3039 | /* Move onto the new config */ |
| 3040 | config->next->prev = config; |
| 3041 | config = config->next; |
| 3042 | } |
| 3043 | else |
| 3044 | result = PARAM_NO_MEM; |
| 3045 | } |
| 3046 | else { |
| 3047 | errorf(global, "missing URL before --next"); |
| 3048 | result = PARAM_BAD_USE; |
| 3049 | } |
| 3050 | } |
| 3051 | else if(!result && passarg) |
| 3052 | i++; /* we are supposed to skip this */ |
| 3053 | } |
| 3054 | } |
| 3055 | else { |
| 3056 | bool used; |
| 3057 | |
| 3058 | /* Just add the URL please */ |
| 3059 | result = getparameter("--url", orig_opt, NULL, NULL, |
| 3060 | &used, global, config); |
| 3061 | } |
| 3062 | |
| 3063 | if(!result) |
| 3064 | unicodefree(orig_opt); |
| 3065 | } |
| 3066 | |
| 3067 | if(!result && config->content_disposition) { |
| 3068 | if(config->resume_from_current) |
| 3069 | result = PARAM_CONTDISP_RESUME_FROM; |
| 3070 | } |
| 3071 | |
| 3072 | if(result && result != PARAM_HELP_REQUESTED && |
| 3073 | result != PARAM_MANUAL_REQUESTED && |
| 3074 | result != PARAM_VERSION_INFO_REQUESTED && |
| 3075 | result != PARAM_ENGINES_REQUESTED && |
| 3076 | result != PARAM_CA_EMBED_REQUESTED) { |
| 3077 | const char *reason = param2text(result); |
| 3078 | |
| 3079 | if(orig_opt && strcmp(":", orig_opt)) |
| 3080 | helpf(tool_stderr, "option %s: %s", orig_opt, reason); |
| 3081 | else |
| 3082 | helpf(tool_stderr, "%s", reason); |
| 3083 | } |
| 3084 | |
| 3085 | unicodefree(orig_opt); |
| 3086 | return result; |
| 3087 | } |
Show 161 lines (not cited by the judge)
| 48 | int parseconfig(const char *filename, struct GlobalConfig *global) |
| 49 | { |
| 50 | FILE *file = NULL; |
| 51 | bool usedarg = FALSE; |
| 52 | int rc = 0; |
| 53 | struct OperationConfig *operation = global->last; |
| 54 | char *pathalloc = NULL; |
| 55 | |
| 56 | if(!filename) { |
| 57 | /* NULL means load .curlrc from homedir! */ |
| 58 | char *curlrc = findfile(".curlrc", CURLRC_DOTSCORE); |
| 59 | if(curlrc) { |
| 60 | file = fopen(curlrc, FOPEN_READTEXT); |
| 61 | if(!file) { |
| 62 | free(curlrc); |
| 63 | return 1; |
| 64 | } |
| 65 | filename = pathalloc = curlrc; |
| 66 | } |
| 67 | #if defined(_WIN32) && !defined(UNDER_CE) |
| 68 | else { |
| 69 | char *fullp; |
| 70 | /* check for .curlrc then _curlrc in the dir of the executable */ |
| 71 | file = tool_execpath(".curlrc", &fullp); |
| 72 | if(!file) |
| 73 | file = tool_execpath("_curlrc", &fullp); |
| 74 | if(file) |
| 75 | /* this is the filename we read from */ |
| 76 | filename = fullp; |
| 77 | } |
| 78 | #endif |
| 79 | } |
| 80 | else { |
| 81 | if(strcmp(filename, "-")) |
| 82 | file = fopen(filename, FOPEN_READTEXT); |
| 83 | else |
| 84 | file = stdin; |
| 85 | } |
| 86 | |
| 87 | if(file) { |
| 88 | char *line; |
| 89 | char *option; |
| 90 | char *param; |
| 91 | int lineno = 0; |
| 92 | bool dashed_option; |
| 93 | struct curlx_dynbuf buf; |
| 94 | bool fileerror = FALSE; |
| 95 | curlx_dyn_init(&buf, MAX_CONFIG_LINE_LENGTH); |
| 96 | DEBUGASSERT(filename); |
| 97 | |
| 98 | while(!rc && my_get_line(file, &buf, &fileerror)) { |
| 99 | ParameterError res; |
| 100 | bool alloced_param = FALSE; |
| 101 | lineno++; |
| 102 | line = curlx_dyn_ptr(&buf); |
| 103 | if(!line) { |
| 104 | rc = 1; /* out of memory */ |
| 105 | break; |
| 106 | } |
| 107 | |
| 108 | /* the option keywords starts here */ |
| 109 | option = line; |
| 110 | |
| 111 | /* the option starts with a dash? */ |
| 112 | dashed_option = (option[0] == '-'); |
| 113 | |
| 114 | while(*line && !ISBLANK(*line) && !ISSEP(*line, dashed_option)) |
| 115 | line++; |
| 116 | /* ... and has ended here */ |
| 117 | |
| 118 | if(*line) |
| 119 | *line++ = '\0'; /* null-terminate, we have a local copy of the data */ |
| 120 | |
| 121 | #ifdef DEBUG_CONFIG |
| 122 | fprintf(tool_stderr, "GOT: %s\n", option); |
| 123 | #endif |
| 124 | |
| 125 | /* pass spaces and separator(s) */ |
| 126 | while(ISBLANK(*line) || ISSEP(*line, dashed_option)) |
| 127 | line++; |
| 128 | |
| 129 | /* the parameter starts here (unless quoted) */ |
| 130 | if(*line == '\"') { |
| 131 | /* quoted parameter, do the quote dance */ |
| 132 | line++; |
| 133 | param = malloc(strlen(line) + 1); /* parameter */ |
| 134 | if(!param) { |
| 135 | /* out of memory */ |
| 136 | rc = 1; |
| 137 | break; |
| 138 | } |
| 139 | alloced_param = TRUE; |
| 140 | (void)unslashquote(line, param); |
| 141 | } |
| 142 | else { |
| 143 | param = line; /* parameter starts here */ |
| 144 | while(*line && !ISSPACE(*line)) /* stop also on CRLF */ |
| 145 | line++; |
| 146 | |
| 147 | if(*line) { |
| 148 | *line = '\0'; /* null-terminate */ |
| 149 | |
| 150 | /* to detect mistakes better, see if there is data following */ |
| 151 | line++; |
| 152 | /* pass all spaces */ |
| 153 | while(ISBLANK(*line)) |
| 154 | line++; |
| 155 | |
| 156 | switch(*line) { |
| 157 | case '\0': |
| 158 | case '\r': |
| 159 | case '\n': |
| 160 | case '#': /* comment */ |
| 161 | break; |
| 162 | default: |
| 163 | warnf(operation->global, "%s:%d: warning: '%s' uses unquoted " |
| 164 | "whitespace", filename, lineno, option); |
| 165 | warnf(operation->global, "This may cause side-effects. " |
| 166 | "Consider using double quotes?"); |
| 167 | } |
| 168 | } |
| 169 | if(!*param) |
| 170 | /* do this so getparameter can check for required parameters. |
| 171 | Otherwise it always thinks there is a parameter. */ |
| 172 | param = NULL; |
| 173 | } |
| 174 | |
| 175 | #ifdef DEBUG_CONFIG |
| 176 | fprintf(tool_stderr, "PARAM: \"%s\"\n",(param ? param : "(null)")); |
| 177 | #endif |
| 178 | res = getparameter(option, param, NULL, NULL, |
| 179 | &usedarg, global, operation); |
| 180 | operation = global->last; |
| 181 | |
| 182 | if(!res && param && *param && !usedarg) |
| 183 | /* we passed in a parameter that was not used! */ |
| 184 | res = PARAM_GOT_EXTRA_PARAMETER; |
| 185 | |
| 186 | if(res == PARAM_NEXT_OPERATION) { |
| 187 | if(operation->url_list && operation->url_list->url) { |
| 188 | /* Allocate the next config */ |
| 189 | operation->next = malloc(sizeof(struct OperationConfig)); |
| 190 | if(operation->next) { |
| 191 | /* Initialise the newly created config */ |
| 192 | config_init(operation->next); |
| 193 | |
| 194 | /* Set the global config pointer */ |
| 195 | operation->next->global = global; |
| 196 | |
| 197 | /* Update the last operation pointer */ |
| 198 | global->last = operation->next; |
| 199 | |
| 200 | /* Move onto the new config */ |
| 201 | operation->next->prev = operation; |
| 202 | operation = operation->next; |
| 203 | } |
| 204 | else |
| 205 | res = PARAM_NO_MEM; |
| 206 | } |
| 207 | } |
| 208 |
Show 1 lines (not cited by the judge)
| 141 | #define strdup(ptr) Curl_cstrdup(ptr) |