curl: warn the user if a given file name looks like an option

... simply because this is usually a sign of the user having omitted the
file name and the next option is instead "eaten" by the parser as a file
name.

Add test1268 to verify

Closes #2885

Daniel Stenberg 4 months ago
parent
commit
099f37e9c5
3 changed files with 70 additions and 23 deletions
  1. 31 23
      src/tool_getparam.c
  2. 1 0
      tests/data/Makefile.inc
  3. 38 0
      tests/data/test1268

+ 31 - 23
src/tool_getparam.c

@@ -65,7 +65,8 @@ struct LongShort {
65 65
   enum {
66 66
     ARG_NONE,   /* stand-alone but not a boolean */
67 67
     ARG_BOOL,   /* accepts a --no-[name] prefix */
68
-    ARG_STRING  /* requires an argument */
68
+    ARG_STRING, /* requires an argument */
69
+    ARG_FILENAME /* requires an argument, usually a file name */
69 70
   } desc;
70 71
 };
71 72
 
@@ -75,7 +76,7 @@ static const struct LongShort aliases[]= {
75 76
   {"*@", "url",                      ARG_STRING},
76 77
   {"*4", "dns-ipv4-addr",            ARG_STRING},
77 78
   {"*6", "dns-ipv6-addr",            ARG_STRING},
78
-  {"*a", "random-file",              ARG_STRING},
79
+  {"*a", "random-file",              ARG_FILENAME},
79 80
   {"*b", "egd-file",                 ARG_STRING},
80 81
   {"*B", "oauth2-bearer",            ARG_STRING},
81 82
   {"*c", "connect-timeout",          ARG_STRING},
@@ -87,9 +88,9 @@ static const struct LongShort aliases[]= {
87 88
          /* 'epsv' made like this to make --no-epsv and --epsv to work
88 89
              although --disable-epsv is the documented option */
89 90
   {"*F", "dns-servers",              ARG_STRING},
90
-  {"*g", "trace",                    ARG_STRING},
91
+  {"*g", "trace",                    ARG_FILENAME},
91 92
   {"*G", "npn",                      ARG_BOOL},
92
-  {"*h", "trace-ascii",              ARG_STRING},
93
+  {"*h", "trace-ascii",              ARG_FILENAME},
93 94
   {"*H", "alpn",                     ARG_BOOL},
94 95
   {"*i", "limit-rate",               ARG_STRING},
95 96
   {"*j", "compressed",               ARG_BOOL},
@@ -108,7 +109,7 @@ static const struct LongShort aliases[]= {
108 109
   {"*s", "max-redirs",               ARG_STRING},
109 110
   {"*t", "proxy-ntlm",               ARG_BOOL},
110 111
   {"*u", "crlf",                     ARG_BOOL},
111
-  {"*v", "stderr",                   ARG_STRING},
112
+  {"*v", "stderr",                   ARG_FILENAME},
112 113
   {"*w", "interface",                ARG_STRING},
113 114
   {"*x", "krb",                      ARG_STRING},
114 115
   {"*x", "krb4",                     ARG_STRING},
@@ -177,7 +178,7 @@ static const struct LongShort aliases[]= {
177 178
   {"$J", "metalink",                 ARG_BOOL},
178 179
   {"$K", "sasl-ir",                  ARG_BOOL},
179 180
   {"$L", "test-event",               ARG_BOOL},
180
-  {"$M", "unix-socket",              ARG_STRING},
181
+  {"$M", "unix-socket",              ARG_FILENAME},
181 182
   {"$N", "path-as-is",               ARG_BOOL},
182 183
   {"$O", "socks5-gssapi-service",    ARG_STRING},
183 184
          /* 'socks5-gssapi-service' merged with'proxy-service-name' and
@@ -188,7 +189,7 @@ static const struct LongShort aliases[]= {
188 189
   {"$R", "expect100-timeout",        ARG_STRING},
189 190
   {"$S", "tftp-no-options",          ARG_BOOL},
190 191
   {"$U", "connect-to",               ARG_STRING},
191
-  {"$W", "abstract-unix-socket",     ARG_STRING},
192
+  {"$W", "abstract-unix-socket",     ARG_FILENAME},
192 193
   {"$X", "tls-max",                  ARG_STRING},
193 194
   {"$Y", "suppress-connect-headers", ARG_BOOL},
194 195
   {"$Z", "compressed-ssh",           ARG_BOOL},
@@ -219,19 +220,19 @@ static const struct LongShort aliases[]= {
219 220
   {"da", "data-ascii",               ARG_STRING},
220 221
   {"db", "data-binary",              ARG_STRING},
221 222
   {"de", "data-urlencode",           ARG_STRING},
222
-  {"D",  "dump-header",              ARG_STRING},
223
+  {"D",  "dump-header",              ARG_FILENAME},
223 224
   {"e",  "referer",                  ARG_STRING},
224
-  {"E",  "cert",                     ARG_STRING},
225
-  {"Ea", "cacert",                   ARG_STRING},
225
+  {"E",  "cert",                     ARG_FILENAME},
226
+  {"Ea", "cacert",                   ARG_FILENAME},
226 227
   {"Eb", "cert-type",                ARG_STRING},
227
-  {"Ec", "key",                      ARG_STRING},
228
+  {"Ec", "key",                      ARG_FILENAME},
228 229
   {"Ed", "key-type",                 ARG_STRING},
229 230
   {"Ee", "pass",                     ARG_STRING},
230 231
   {"Ef", "engine",                   ARG_STRING},
231
-  {"Eg", "capath",                   ARG_STRING},
232
+  {"Eg", "capath",                   ARG_FILENAME},
232 233
   {"Eh", "pubkey",                   ARG_STRING},
233 234
   {"Ei", "hostpubmd5",               ARG_STRING},
234
-  {"Ej", "crlfile",                  ARG_STRING},
235
+  {"Ej", "crlfile",                  ARG_FILENAME},
235 236
   {"Ek", "tlsuser",                  ARG_STRING},
236 237
   {"El", "tlspassword",              ARG_STRING},
237 238
   {"Em", "tlsauthtype",              ARG_STRING},
@@ -246,17 +247,17 @@ static const struct LongShort aliases[]= {
246 247
   {"Eu", "proxy-tlsuser",            ARG_STRING},
247 248
   {"Ev", "proxy-tlspassword",        ARG_STRING},
248 249
   {"Ew", "proxy-tlsauthtype",        ARG_STRING},
249
-  {"Ex", "proxy-cert",               ARG_STRING},
250
+  {"Ex", "proxy-cert",               ARG_FILENAME},
250 251
   {"Ey", "proxy-cert-type",          ARG_STRING},
251
-  {"Ez", "proxy-key",                ARG_STRING},
252
+  {"Ez", "proxy-key",                ARG_FILENAME},
252 253
   {"E0", "proxy-key-type",           ARG_STRING},
253 254
   {"E1", "proxy-pass",               ARG_STRING},
254 255
   {"E2", "proxy-ciphers",            ARG_STRING},
255
-  {"E3", "proxy-crlfile",            ARG_STRING},
256
+  {"E3", "proxy-crlfile",            ARG_FILENAME},
256 257
   {"E4", "proxy-ssl-allow-beast",    ARG_BOOL},
257 258
   {"E5", "login-options",            ARG_STRING},
258
-  {"E6", "proxy-cacert",             ARG_STRING},
259
-  {"E7", "proxy-capath",             ARG_STRING},
259
+  {"E6", "proxy-cacert",             ARG_FILENAME},
260
+  {"E7", "proxy-capath",             ARG_FILENAME},
260 261
   {"E8", "proxy-insecure",           ARG_BOOL},
261 262
   {"E9", "proxy-tlsv1",              ARG_NONE},
262 263
   {"EA", "socks5-basic",             ARG_BOOL},
@@ -277,7 +278,7 @@ static const struct LongShort aliases[]= {
277 278
   {"j",  "junk-session-cookies",     ARG_BOOL},
278 279
   {"J",  "remote-header-name",       ARG_BOOL},
279 280
   {"k",  "insecure",                 ARG_BOOL},
280
-  {"K",  "config",                   ARG_STRING},
281
+  {"K",  "config",                   ARG_FILENAME},
281 282
   {"l",  "list-only",                ARG_BOOL},
282 283
   {"L",  "location",                 ARG_BOOL},
283 284
   {"Lt", "location-trusted",         ARG_BOOL},
@@ -285,10 +286,10 @@ static const struct LongShort aliases[]= {
285 286
   {"M",  "manual",                   ARG_BOOL},
286 287
   {"n",  "netrc",                    ARG_BOOL},
287 288
   {"no", "netrc-optional",           ARG_BOOL},
288
-  {"ne", "netrc-file",               ARG_STRING},
289
+  {"ne", "netrc-file",               ARG_FILENAME},
289 290
   {"N",  "buffer",                   ARG_BOOL},
290 291
          /* 'buffer' listed as --no-buffer in the help */
291
-  {"o",  "output",                   ARG_STRING},
292
+  {"o",  "output",                   ARG_FILENAME},
292 293
   {"O",  "remote-name",              ARG_NONE},
293 294
   {"Oa", "remote-name-all",          ARG_BOOL},
294 295
   {"p",  "proxytunnel",              ARG_BOOL},
@@ -300,7 +301,7 @@ static const struct LongShort aliases[]= {
300 301
   {"s",  "silent",                   ARG_BOOL},
301 302
   {"S",  "show-error",               ARG_BOOL},
302 303
   {"t",  "telnet-option",            ARG_STRING},
303
-  {"T",  "upload-file",              ARG_STRING},
304
+  {"T",  "upload-file",              ARG_FILENAME},
304 305
   {"u",  "user",                     ARG_STRING},
305 306
   {"U",  "proxy-user",               ARG_STRING},
306 307
   {"v",  "verbose",                  ARG_BOOL},
@@ -570,7 +571,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
570 571
       }
571 572
     }
572 573
 
573
-    if(aliases[hit].desc == ARG_STRING) {
574
+    if(aliases[hit].desc >= ARG_STRING) {
574 575
       /* this option requires an extra parameter */
575 576
       if(!longopt && parse[1]) {
576 577
         nextarg = (char *)&parse[1]; /* this is the actual extra parameter */
@@ -580,6 +581,13 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
580 581
         return PARAM_REQUIRES_PARAMETER;
581 582
       else
582 583
         *usedarg = TRUE; /* mark it as used */
584
+
585
+      if((aliases[hit].desc == ARG_FILENAME) &&
586
+         (nextarg[0] == '-') && nextarg[1]) {
587
+        /* if the file name looks like a command line option */
588
+        warnf(global, "The file name argument '%s' looks like a flag.\n",
589
+              nextarg);
590
+      }
583 591
     }
584 592
     else if((aliases[hit].desc == ARG_NONE) && !toggle)
585 593
       return PARAM_NO_PREFIX;

+ 1 - 0
tests/data/Makefile.inc

@@ -140,6 +140,7 @@ test1236 test1237 test1238 test1239 test1240 test1241 test1242 test1243 \
140 140
 test1244 test1245 test1246 test1247 test1248 test1249 test1250 test1251 \
141 141
 test1252 test1253 test1254 test1255 test1256 test1257 test1258 test1259 \
142 142
 test1260 test1261 test1262 test1263 test1264 test1265 test1266 test1267 \
143
+test1268 \
143 144
 \
144 145
 test1280 test1281 test1282 test1283 test1284 test1285 test1286 test1287 \
145 146
 test1288 test1289 test1290 test1291 test1292 \

+ 38 - 0
tests/data/test1268

@@ -0,0 +1,38 @@
1
+<testcase>
2
+<info>
3
+<keywords>
4
+warning
5
+</keywords>
6
+</info>
7
+
8
+#
9
+# Server-side
10
+<reply>
11
+</reply>
12
+
13
+#
14
+# Client-side
15
+<client>
16
+<server>
17
+none
18
+</server>
19
+ <name>
20
+file name argument looks like a flag
21
+ </name>
22
+ <command>
23
+--stderr log/moo1268 --unix-socket -k hej://moo
24
+</command>
25
+</client>
26
+
27
+<verify>
28
+<file name="log/moo1268">
29
+Warning: The file name argument '-k' looks like a flag.
30
+curl: (1) Protocol "hej" not supported or disabled in libcurl
31
+</file>
32
+
33
+# we expect an error since we provide a weird URL
34
+<errorcode>
35
+1
36
+</errorcode>
37
+</verify>
38
+</testcase>