From c478c7efdf4ebbc8d768ae4cdfdcecf49b68cf94 Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Tue, 30 Sep 2025 11:41:11 +0200 Subject: [PATCH] examples: fix two more cases of `stat()` TOCTOU Also: - ftpupload: bump an intermediate variable size. Follow-up to f13250edf11312ab8c0425cf39b182a31b53c6f7 #18605 Closes #18778 --- docs/examples/ftpupload.c | 32 ++++++++++++++++++++------------ docs/examples/httpput.c | 16 +++++++++++++--- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/docs/examples/ftpupload.c b/docs/examples/ftpupload.c index 6e7bece70d..ec64f4a2cd 100644 --- a/docs/examples/ftpupload.c +++ b/docs/examples/ftpupload.c @@ -37,6 +37,9 @@ #include #undef stat #define stat _stat +#undef fstat +#define fstat _fstat +#define fileno _fileno #else #include #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); diff --git a/docs/examples/httpput.c b/docs/examples/httpput.c index 3743e1b5b9..ddb1b07328 100644 --- a/docs/examples/httpput.c +++ b/docs/examples/httpput.c @@ -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); -- 2.47.3