]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tool: improve config error messaging
authorDaniel Stenberg <daniel@haxx.se>
Sat, 21 Feb 2026 22:16:39 +0000 (23:16 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Sun, 22 Feb 2026 13:56:07 +0000 (14:56 +0100)
- make sure that errors for specific options in config files identify
  the file, line number and shows the error about the correct option

- improve some error message wording

- add warning for leading single quote of arguments in config files
  (verified in test 1712)

- adjust test error outputs accordingly

test1712 introduces mode=warn

Use the mode="warn" attribute if the output curl warning output, as it
then makes the check without newlines and the prefix to better handle
that the lines may wrap at different points depending on the lengths of
the lines and terminal width.

Fixes #20598
Closes #20666

docs/tests/FILEFORMAT.md
src/tool_getparam.h
src/tool_helpers.c
src/tool_parsecfg.c
tests/data/Makefile.am
tests/data/test1712 [new file with mode: 0644]
tests/data/test459
tests/runtests.pl

index 26dae3e23fd4e20a797e732c1eba6c197e6dc8f3..b946c7973ce4d7d321b1c2c505a16a493ea0c702 100644 (file)
@@ -712,12 +712,16 @@ server is used), if `nonewline` is set, we cut off the trailing newline of
 this given data before comparing with the one actually sent by the client The
 `<strip>` and `<strippart>` rules are applied before comparisons are made.
 
-### `<stderr [mode="text"] [nonewline="yes"] [crlf="yes|headers"]>`
+### `<stderr [mode="text/warn"] [nonewline="yes"] [crlf="yes|headers"]>`
 This verifies that this data was passed to stderr.
 
 Use the mode="text" attribute if the output is in text mode on platforms that
 have a text/binary difference.
 
+Use the mode="warn" attribute for curl warning output, as it then makes the
+check without newlines and the prefix to better handle that the lines may wrap
+at different points depending on the lengths of the lines and terminal width.
+
 `crlf=yes` forces the newlines to become CRLF even if not written so in the
 test.
 
index 4d345413931debbcd76798ac0eac7b15793ddf04..e3cbe5454a6d429232396e87796b0a1f724be220 100644 (file)
@@ -336,6 +336,7 @@ struct LongShort {
 typedef enum {
   PARAM_OK = 0,
   PARAM_OPTION_UNKNOWN,
+  PARAM_CONFIG_OPTION_UNKNOWN,
   PARAM_REQUIRES_PARAMETER,
   PARAM_BAD_USE,
   PARAM_HELP_REQUESTED,
index 2a84accf2c508f000bf3eab280a7e87cb562cf5d..a23c3a80e75b29cc4f9ff2bd08a107d211bb1048 100644 (file)
@@ -39,6 +39,8 @@ const char *param2text(ParameterError error)
     return "had unsupported trailing garbage";
   case PARAM_OPTION_UNKNOWN:
     return "is unknown";
+  case PARAM_CONFIG_OPTION_UNKNOWN:
+    return "found an unknown config option";
   case PARAM_REQUIRES_PARAMETER:
     return "requires parameter";
   case PARAM_BAD_USE:
index 9cecaaa2f4db630dec13803618ddd2d742e4426c..d5421136c47bd76206ba0dd92c108527eceee108 100644 (file)
@@ -172,6 +172,11 @@ ParameterError parseconfig(const char *filename, int max_recursive,
         param = curlx_dyn_len(&pbuf) ? curlx_dyn_ptr(&pbuf) : CURL_UNCONST("");
       }
       else {
+        if(*line == '\'') {
+          warnf("%s:%d Option '%s' uses argument with leading single quote. "
+                "It is probably a mistake. Consider double quotes.",
+                filename, lineno, option);
+        }
         param = line; /* parameter starts here */
         while(*line && !ISSPACE(*line)) /* stop also on CRLF */
           line++;
@@ -192,7 +197,7 @@ ParameterError parseconfig(const char *filename, int max_recursive,
           case '#': /* comment */
             break;
           default:
-            warnf("%s:%d: warning: '%s' uses unquoted whitespace. "
+            warnf("%s:%d Option '%s' uses argument with unquoted whitespace. "
                   "This may cause side-effects. Consider double quotes.",
                   filename, lineno, option);
           }
@@ -240,11 +245,11 @@ ParameterError parseconfig(const char *filename, int max_recursive,
            res != PARAM_VERSION_INFO_REQUESTED &&
            res != PARAM_ENGINES_REQUESTED &&
            res != PARAM_CA_EMBED_REQUESTED) {
-          /* only show error in the first level config call */
-          if(max_recursive == CONFIG_MAX_LEVELS) {
-            const char *reason = param2text(res);
-            errorf("%s:%d: '%s' %s", filename, lineno, option, reason);
-          }
+          const char *reason = param2text(res);
+          errorf("%s:%d config file option '%s' %s",
+                 filename, lineno, option, reason);
+          if(res == PARAM_OPTION_UNKNOWN)
+            res = PARAM_CONFIG_OPTION_UNKNOWN;
           err = res;
         }
       }
index ca44e3d2b002f16de6011e5b8ce2464eae6c8edb..ecbcc28fe9496ea386b95d7f3d8fde7e0aab3c6d 100644 (file)
@@ -229,7 +229,7 @@ test1670 test1671 \
 test1680 test1681 test1682 test1683 \
 \
 test1700 test1701 test1702 test1703 test1704 test1705 test1706 test1707 \
-test1708 test1709 test1710 test1711 \
+test1708 test1709 test1710 test1711 test1712 \
 \
 test1800 test1801 test1802 test1847 test1848 \
 \
diff --git a/tests/data/test1712 b/tests/data/test1712
new file mode 100644 (file)
index 0000000..5cdc642
--- /dev/null
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+<info>
+<keywords>
+HTTP
+--config
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data crlf="headers">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+config file with argument using single quotes
+</name>
+<file name="%LOGDIR/config">
+data = 'arg-with-quote'
+</file>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --config %LOGDIR/config --silent
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes" nonewline="yes">
+POST /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+Content-Length: 16
+Content-Type: application/x-www-form-urlencoded
+
+'arg-with-quote'
+</protocol>
+<stderr mode="warn">
+Warning: %LOGDIR/config:1 Option 'data' uses argument with leading single quote.%SP
+It is probably a mistake. Consider double quotes.
+</stderr>
+</verify>
+</testcase>
index 5d623077284c3bea8d934f5408c5d0f00f7a9f35..7a2e1db7b30cdd9c597a98d5020e35e019ac816e 100644 (file)
@@ -54,8 +54,8 @@ Content-Type: application/x-www-form-urlencoded
 arg
 </protocol>
 <stderr mode="text">
-Warning: %LOGDIR/config:1: warning: 'data' uses unquoted whitespace. This may%SP
-Warning: cause side-effects. Consider double quotes.
+Warning: %LOGDIR/config:1 Option 'data' uses argument with unquoted whitespace.%SP
+Warning: This may cause side-effects. Consider double quotes.
 </stderr>
 </verify>
 </testcase>
index e0bc468f103b216c1d89106cbc25b816e450c743..e8612d27567f39d317b2a044e95d44d9bfe5041d 100755 (executable)
@@ -1346,6 +1346,22 @@ sub singletest_check {
             normalize_text(\@validstderr);
             normalize_text(\@actual);
         }
+        if($filemode && ($filemode eq "warn")) {
+            for(@validstderr) {
+                s/Warning: //;
+                s/\r//;
+                s/\n/ /;
+            }
+            for(@actual) {
+                s/Warning: //;
+                s/\r//;
+                s/\n/ /;
+            }
+            my $v = join(@validstderr, "");
+            my $a = join(@actual, "");
+            @validstderr = $v;
+            @actual = $a;
+        }
 
         if($hash{'nonewline'}) {
             # Yes, we must cut off the final newline from the final line