]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
lib: don't use strerror()
authorDaniel Stenberg <daniel@haxx.se>
Wed, 8 Sep 2021 09:27:49 +0000 (11:27 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 9 Sep 2021 05:53:42 +0000 (07:53 +0200)
We have and provide Curl_strerror() internally for a reason: strerror()
is not necessarily thread-safe so we should always try to avoid it.

Extended checksrc to warn for this, but feature the check disabled by
default and only enable it in lib/

Closes #7685

lib/.checksrc [new file with mode: 0644]
lib/checksrc.pl
lib/non-ascii.c
lib/strerror.c
lib/url.c
lib/vtls/gskit.c
lib/vtls/rustls.c
lib/vtls/sectransp.c

diff --git a/lib/.checksrc b/lib/.checksrc
new file mode 100644 (file)
index 0000000..16133a4
--- /dev/null
@@ -0,0 +1 @@
+enable STRERROR
index a35535c1915137a655c800cb15dfdfc1367b3a39..ac7e3847e7056538db0eca7ba24d570d9489933d 100755 (executable)
@@ -47,6 +47,7 @@ my @ignore_line;
 
 my %warnings_extended = (
     'COPYRIGHTYEAR'    => 'copyright year incorrect',
+    'STRERROR',        => 'strerror() detected',
     );
 
 my %warnings = (
@@ -87,7 +88,7 @@ my %warnings = (
     'EXCLAMATIONSPACE' => 'Whitespace after exclamation mark in expression',
     'EMPTYLINEBRACE'   => 'Empty line before the open brace',
     'EQUALSNULL'       => 'if/while comparison with == NULL',
-    'NOTEQUALSZERO'    => 'if/while comparison with != 0'
+    'NOTEQUALSZERO',   => 'if/while comparison with != 0',
     );
 
 sub readskiplist {
@@ -238,9 +239,17 @@ if(!$file) {
     print "  -i<n>     Indent spaces. Default: 2\n";
     print "  -m<n>     Maximum line length. Default: 79\n";
     print "\nDetects and warns for these problems:\n";
-    for(sort keys %warnings) {
-        printf (" %-18s: %s\n", $_, $warnings{$_});
+    my @allw = keys %warnings;
+    push @allw, keys %warnings_extended;
+    for my $w (sort @allw) {
+        if($warnings{$w}) {
+            printf (" %-18s: %s\n", $w, $warnings{$w});
+        }
+        else {
+            printf (" %-18s: %s[*]\n", $w, $warnings_extended{$w});
+        }
     }
+    print " [*] = disabled by default\n";
     exit;
 }
 
@@ -638,7 +647,18 @@ sub scanfile {
                       $line, length($1), $file, $ol,
                       "use of $2 is banned");
         }
-
+        if($warnings{"STRERROR"}) {
+            # scan for use of banned strerror. This is not a BANNEDFUNC to
+            # allow for individual enable/disable of this warning.
+            if($l =~ /^(.*\W)(strerror)\s*\(/x) {
+                if($1 !~ /^ *\#/) {
+                    # skip preprocessor lines
+                    checkwarn("STRERROR",
+                              $line, length($1), $file, $ol,
+                              "use of $2 is banned");
+                }
+            }
+        }
         # scan for use of snprintf for curl-internals reasons
         if($l =~ /^(.*\W)(v?snprintf)\s*\(/x) {
             checkwarn("SNPRINTF",
index 932cf89eef6078181f40e586b2f133a1ee048c2e..28398adf1b288e899dd413e8b556cd6f78295fd8 100644 (file)
@@ -112,11 +112,12 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
       *cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
                        CURL_ICONV_CODESET_OF_HOST);
       if(*cd == (iconv_t)-1) {
+        char buffer[STRERROR_LEN];
         failf(data,
               "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
               CURL_ICONV_CODESET_OF_NETWORK,
               CURL_ICONV_CODESET_OF_HOST,
-              errno, strerror(errno));
+              errno, Curl_strerror(errno, buffer, sizeof(buffer)));
         return CURLE_CONV_FAILED;
       }
     }
@@ -128,9 +129,10 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
     if(!data)
       iconv_close(tmpcd);
     if((rc == ICONV_ERROR) || (in_bytes)) {
+      char buffer[STRERROR_LEN];
       failf(data,
             "The Curl_convert_to_network iconv call failed with errno %i: %s",
-            errno, strerror(errno));
+            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
       return CURLE_CONV_FAILED;
     }
 #else
@@ -178,11 +180,12 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
       *cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
                        CURL_ICONV_CODESET_OF_NETWORK);
       if(*cd == (iconv_t)-1) {
+        char buffer[STRERROR_LEN];
         failf(data,
               "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
               CURL_ICONV_CODESET_OF_HOST,
               CURL_ICONV_CODESET_OF_NETWORK,
-              errno, strerror(errno));
+              errno, Curl_strerror(errno, buffer, sizeof(buffer)));
         return CURLE_CONV_FAILED;
       }
     }
@@ -194,9 +197,10 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
     if(!data)
       iconv_close(tmpcd);
     if((rc == ICONV_ERROR) || (in_bytes)) {
+      char buffer[STRERROR_LEN];
       failf(data,
             "Curl_convert_from_network iconv call failed with errno %i: %s",
-            errno, strerror(errno));
+            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
       return CURLE_CONV_FAILED;
     }
 #else
@@ -245,11 +249,12 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
       *cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
                        CURL_ICONV_CODESET_FOR_UTF8);
       if(*cd == (iconv_t)-1) {
+        char buffer[STRERROR_LEN];
         failf(data,
               "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
               CURL_ICONV_CODESET_OF_HOST,
               CURL_ICONV_CODESET_FOR_UTF8,
-              errno, strerror(errno));
+              errno, Curl_strerror(errno, buffer, sizeof(buffer)));
         return CURLE_CONV_FAILED;
       }
     }
@@ -261,9 +266,10 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
     if(!data)
       iconv_close(tmpcd);
     if((rc == ICONV_ERROR) || (in_bytes)) {
+      char buffer[STRERROR_LEN];
       failf(data,
             "The Curl_convert_from_utf8 iconv call failed with errno %i: %s",
-            errno, strerror(errno));
+            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
       return CURLE_CONV_FAILED;
     }
     if(output_ptr < input_ptr) {
index a1ec539b90a5dfd1227abac6c96d2b7c11bae42e..431ff1c2fb0806830e937478ef955a42ca6b495a 100644 (file)
@@ -731,6 +731,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
   max = buflen - 1;
   *buf = '\0';
 
+  /* !checksrc! disable STRERROR 2 */
 #if defined(WIN32) || defined(_WIN32_WCE)
 #if defined(WIN32)
   /* 'sys_nerr' is the maximum errno number, it is not widely portable */
index 8a2845dddd87e00d9aaa4237324fd836ed977acb..b672710c52230d6bd476d572716c6efc40e1dbcb 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -1892,9 +1892,11 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data,
 #else
       scopeidx = if_nametoindex(zoneid);
 #endif
-      if(!scopeidx)
+      if(!scopeidx) {
+        char buffer[STRERROR_LEN];
         infof(data, "Invalid zoneid: %s; %s", zoneid,
-              strerror(errno));
+              Curl_strerror(errno, buffer, sizeof(buffer)));
+      }
       else
         conn->scope_id = scopeidx;
     }
index af8fc92b27d1cc4a9ad3d248e3620886aaec196e..e451f6aebebbf22e4f95a6ac981ed51ab66b3b51 100644 (file)
@@ -180,6 +180,7 @@ static bool is_separator(char c)
 static CURLcode gskit_status(struct Curl_easy *data, int rc,
                              const char *procname, CURLcode defcode)
 {
+  char buffer[STRERROR_LEN];
   /* Process GSKit status and map it to a CURLcode. */
   switch(rc) {
   case GSK_OK:
@@ -208,7 +209,8 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc,
     case ENOMEM:
       return CURLE_OUT_OF_MEMORY;
     default:
-      failf(data, "%s I/O error: %s", procname, strerror(errno));
+      failf(data, "%s I/O error: %s", procname,
+            Curl_strerror(errno, buffer, sizeof(buffer)));
       break;
     }
     break;
@@ -223,13 +225,15 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc,
 static CURLcode set_enum(struct Curl_easy *data, gsk_handle h,
                 GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok)
 {
+  char buffer[STRERROR_LEN];
   int rc = gsk_attribute_set_enum(h, id, value);
 
   switch(rc) {
   case GSK_OK:
     return CURLE_OK;
   case GSK_ERROR_IO:
-    failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno));
+    failf(data, "gsk_attribute_set_enum() I/O error: %s",
+          Curl_strerror(errno, buffer, sizeof(buffer)));
     break;
   case GSK_ATTRIBUTE_INVALID_ID:
     if(unsupported_ok)
@@ -245,13 +249,15 @@ static CURLcode set_enum(struct Curl_easy *data, gsk_handle h,
 static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h,
                         GSK_BUF_ID id, const char *buffer, bool unsupported_ok)
 {
+  char buffer[STRERROR_LEN];
   int rc = gsk_attribute_set_buffer(h, id, buffer, 0);
 
   switch(rc) {
   case GSK_OK:
     return CURLE_OK;
   case GSK_ERROR_IO:
-    failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno));
+    failf(data, "gsk_attribute_set_buffer() I/O error: %s",
+          Curl_strerror(errno, buffer, sizeof(buffer)));
     break;
   case GSK_ATTRIBUTE_INVALID_ID:
     if(unsupported_ok)
@@ -267,6 +273,7 @@ static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h,
 static CURLcode set_numeric(struct Curl_easy *data,
                             gsk_handle h, GSK_NUM_ID id, int value)
 {
+  char buffer[STRERROR_LEN];
   int rc = gsk_attribute_set_numeric_value(h, id, value);
 
   switch(rc) {
@@ -274,7 +281,7 @@ static CURLcode set_numeric(struct Curl_easy *data,
     return CURLE_OK;
   case GSK_ERROR_IO:
     failf(data, "gsk_attribute_set_numeric_value() I/O error: %s",
-          strerror(errno));
+          Curl_strerror(errno, buffer, sizeof(buffer)));
     break;
   default:
     failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc));
@@ -287,13 +294,15 @@ static CURLcode set_numeric(struct Curl_easy *data,
 static CURLcode set_callback(struct Curl_easy *data,
                              gsk_handle h, GSK_CALLBACK_ID id, void *info)
 {
+  char buffer[STRERROR_LEN];
   int rc = gsk_attribute_set_callback(h, id, info);
 
   switch(rc) {
   case GSK_OK:
     return CURLE_OK;
   case GSK_ERROR_IO:
-    failf(data, "gsk_attribute_set_callback() I/O error: %s", strerror(errno));
+    failf(data, "gsk_attribute_set_callback() I/O error: %s",
+          Curl_strerror(errno, buffer, sizeof(buffer)));
     break;
   default:
     failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc));
@@ -966,7 +975,9 @@ static CURLcode gskit_connect_step2(struct Curl_easy *data,
         continue;       /* Retry. */
       }
       if(errno != ETIME) {
-        failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno));
+        char buffer[STRERROR_LEN];
+        failf(data, "QsoWaitForIOCompletion() I/O error: %s",
+              Curl_strerror(errno, buffer, sizeof(buffer)));
         cancel_async_handshake(conn, sockindex);
         close_async_handshake(connssl);
         return CURLE_SSL_CONNECT_ERROR;
@@ -1229,7 +1240,8 @@ static int gskit_shutdown(struct Curl_easy *data,
     nread = read(conn->sock[sockindex], buf, sizeof(buf));
 
     if(nread < 0) {
-      failf(data, "read: %s", strerror(errno));
+      char buffer[STRERROR_LEN];
+      failf(data, "read: %s", Curl_strerror(errno, buffer, sizeof(buffer)));
       rc = -1;
     }
 
index 94a1ca8861f456ca849a02a4658630eab8f9661e..be2e739e00cfe52de6c98af025ad83fac272407c 100644 (file)
@@ -132,7 +132,9 @@ cr_recv(struct Curl_easy *data, int sockindex,
     infof(data, "sread: EAGAIN or EWOULDBLOCK");
   }
   else if(io_error) {
-    failf(data, "reading from socket: %s", strerror(io_error));
+    char buffer[STRERROR_LEN];
+    failf(data, "reading from socket: %s",
+          Curl_strerror(io_error, buffer, sizeof(buffer)));
     *err = CURLE_READ_ERROR;
     return -1;
   }
@@ -244,7 +246,9 @@ cr_send(struct Curl_easy *data, int sockindex,
       return -1;
     }
     else if(io_error) {
-      failf(data, "writing to socket: %s", strerror(io_error));
+      char buffer[STRERROR_LEN];
+      failf(data, "writing to socket: %s",
+            Curl_strerror(io_error, buffer, sizeof(buffer)));
       *err = CURLE_WRITE_ERROR;
       return -1;
     }
index 23b9fad94f00d71bc6604e022dda50c5c17f1bc0..1e6ed5f06d6b4b9dc018276f4a0a858ccd5be930 100644 (file)
@@ -34,6 +34,7 @@
 #include "multiif.h"
 #include "strcase.h"
 #include "x509asn1.h"
+#include "strerror.h"
 
 #ifdef USE_SECTRANSP
 
@@ -3222,7 +3223,9 @@ static int sectransp_shutdown(struct Curl_easy *data,
     nread = read(conn->sock[sockindex], buf, sizeof(buf));
 
     if(nread < 0) {
-      failf(data, "read: %s", strerror(errno));
+      char buffer[STRERROR_LEN];
+      failf(data, "read: %s",
+            Curl_strerror(errno, buffer, sizeof(buffer)));
       rc = -1;
     }