]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
examples: fix two more cases of `stat()` TOCTOU
authorViktor Szakats <commit@vsz.me>
Tue, 30 Sep 2025 09:41:11 +0000 (11:41 +0200)
committerViktor Szakats <commit@vsz.me>
Tue, 30 Sep 2025 10:28:43 +0000 (12:28 +0200)
Also:
- ftpupload: bump an intermediate variable size.

Follow-up to f13250edf11312ab8c0425cf39b182a31b53c6f7 #18605

Closes #18778

docs/examples/ftpupload.c
docs/examples/httpput.c

index 6e7bece70dee28b28e68c00d283522b5eccd06e8..ec64f4a2cdd9bfff5115e5348bfca5e7bda84ea1 100644 (file)
@@ -37,6 +37,9 @@
 #include <io.h>
 #undef stat
 #define stat _stat
+#undef fstat
+#define fstat _fstat
+#define fileno _fileno
 #else
 #include <unistd.h>
 #endif
@@ -78,25 +81,31 @@ int main(void)
   CURLcode res;
   FILE *hd_src;
   struct stat file_info;
-  unsigned long fsize;
+  curl_off_t fsize;
 
   struct curl_slist *headerlist = NULL;
   static const char buf_1 [] = "RNFR " UPLOAD_FILE_AS;
   static const char buf_2 [] = "RNTO " RENAME_FILE_TO;
 
-  /* get the file size of the local file */
-  if(stat(LOCAL_FILE, &file_info)) {
+  /* get a FILE * of the file */
+  hd_src = fopen(LOCAL_FILE, "rb");
+  if(!hd_src) {
     printf("Couldn't open '%s': %s\n", LOCAL_FILE, strerror(errno));
-    return 1;
+    return 2;
   }
-  fsize = (unsigned long)file_info.st_size;
 
-  printf("Local file size: %lu bytes.\n", fsize);
+  /* to get the file size */
+#ifdef UNDER_CE
+  if(stat(LOCAL_FILE, &file_info) != 0) {
+#else
+  if(fstat(fileno(hd_src), &file_info) != 0) {
+#endif
+    fclose(hd_src);
+    return 1; /* cannot continue */
+  }
+  fsize = file_info.st_size;
 
-  /* get a FILE * of the same file */
-  hd_src = fopen(LOCAL_FILE, "rb");
-  if(!hd_src)
-    return 2;
+  printf("Local file size: %lu bytes.\n", (unsigned long)fsize);
 
   /* In Windows, this inits the Winsock stuff */
   curl_global_init(CURL_GLOBAL_ALL);
@@ -127,8 +136,7 @@ int main(void)
        option you MUST make sure that the type of the passed-in argument is a
        curl_off_t. If you use CURLOPT_INFILESIZE (without _LARGE) you must
        make sure that to pass in a type 'long' argument. */
-    curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,
-                     (curl_off_t)fsize);
+    curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, fsize);
 
     /* Now run off and do what you have been told! */
     res = curl_easy_perform(curl);
index 3743e1b5b9c860194fcba5deac9f932a01c730f2..ddb1b07328c6941c6b0f9de411b1534afeaae763 100644 (file)
@@ -33,6 +33,9 @@
 #ifdef _WIN32
 #undef stat
 #define stat _stat
+#undef fstat
+#define fstat _fstat
+#define fileno _fileno
 #endif
 
 /*
@@ -79,9 +82,6 @@ int main(int argc, char **argv)
   file = argv[1];
   url = argv[2];
 
-  /* get the file size of the local file */
-  stat(file, &file_info);
-
   /* get a FILE * of the same file, could also be made with
      fdopen() from the previous descriptor, but hey this is just
      an example! */
@@ -89,6 +89,16 @@ int main(int argc, char **argv)
   if(!hd_src)
     return 2;
 
+  /* get the file size of the local file */
+#ifdef UNDER_CE
+  if(stat(file, &file_info) != 0) {
+#else
+  if(fstat(fileno(hd_src), &file_info) != 0) {
+#endif
+    fclose(hd_src);
+    return 1; /* cannot continue */
+  }
+
   /* In Windows, this inits the Winsock stuff */
   curl_global_init(CURL_GLOBAL_ALL);