diff --git a/lib/Makefile.inc b/lib/Makefile.inc index 366ddb8a18..84b4e5425b 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -32,6 +32,7 @@ LIB_CURLX_CFILES = \ curlx/inet_pton.c \ curlx/multibyte.c \ curlx/nonblock.c \ + curlx/snprintf.c \ curlx/strcopy.c \ curlx/strdup.c \ curlx/strerr.c \ diff --git a/lib/curl_setup.h b/lib/curl_setup.h index 4629f79fb9..6e65697408 100644 --- a/lib/curl_setup.h +++ b/lib/curl_setup.h @@ -90,7 +90,7 @@ /* Disable Visual Studio warnings: 4127 "conditional expression is constant" */ #pragma warning(disable:4127) #ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS /* for _snprintf(), getenv(), sscanf() */ +#define _CRT_SECURE_NO_WARNINGS /* for getenv(), sscanf() */ #endif #endif /* _MSC_VER */ diff --git a/lib/curlx/snprintf.c b/lib/curlx/snprintf.c new file mode 100644 index 0000000000..c7332520e7 --- /dev/null +++ b/lib/curlx/snprintf.c @@ -0,0 +1,49 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ +#include "curlx/snprintf.h" + +#ifdef _WIN32 +#include + +/* Simplified wrapper for the Windows platform to use the correct symbol and + ensuring null-termination. Omit returning a length to keep it simple. */ +void curlx_win32_snprintf(char *buf, size_t maxlen, const char *fmt, ...) +{ + va_list ap; + if(!maxlen) + return; + va_start(ap, fmt); +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif + /* !checksrc! disable BANNEDFUNC 1 */ + (void)vsnprintf(buf, maxlen, fmt, ap); +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + buf[maxlen - 1] = 0; + va_end(ap); +} +#endif /* _WIN32 */ diff --git a/lib/curlx/snprintf.h b/lib/curlx/snprintf.h index 266ea137fa..d6260e4e39 100644 --- a/lib/curlx/snprintf.h +++ b/lib/curlx/snprintf.h @@ -1,3 +1,5 @@ +#ifndef HEADER_CURLX_SNPRINTF_H +#define HEADER_CURLX_SNPRINTF_H /*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | @@ -21,12 +23,18 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ +#include "curl_setup.h" /* Raw snprintf() for curlx */ +#ifdef _WIN32 +void curlx_win32_snprintf(char *buf, size_t maxlen, const char *fmt, ...) + CURL_PRINTF(3, 4); +#endif + #ifdef WITHOUT_LIBCURL /* when built for the test servers */ -#if defined(_MSC_VER) && (_MSC_VER < 1900) /* adjust for old MSVC */ -#define SNPRINTF _snprintf +#ifdef _WIN32 +#define SNPRINTF curlx_win32_snprintf #else #define SNPRINTF snprintf #endif @@ -34,3 +42,4 @@ #include #define SNPRINTF curl_msnprintf #endif /* WITHOUT_LIBCURL */ +#endif /* HEADER_CURLX_SNPRINTF_H */ diff --git a/lib/mprintf.c b/lib/mprintf.c index b00f16e34b..18eb421ba1 100644 --- a/lib/mprintf.c +++ b/lib/mprintf.c @@ -26,6 +26,7 @@ #include "curlx/dynbuf.h" #include "curl_printf.h" #include "curlx/strparse.h" +#include "curlx/snprintf.h" /* for curlx_win32_snprintf() */ #define BUFFSIZE 326 /* buffer for long-to-str and float-to-str calcs, should fit negative DBL_MAX (317 letters) */ @@ -671,29 +672,23 @@ static bool out_double(void *userp, /* NOTE NOTE NOTE!! Not all sprintf implementations return number of output characters */ -#ifdef HAVE_SNPRINTF #if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-nonliteral" #endif +#ifdef _WIN32 + curlx_win32_snprintf(work, BUFFSIZE, formatbuf, dnum); +#elif defined(HAVE_SNPRINTF) /* !checksrc! disable BANNEDFUNC 1 */ /* !checksrc! disable LONGLINE */ /* NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling) */ snprintf(work, BUFFSIZE, formatbuf, dnum); -#if defined(__GNUC__) || defined(__clang__) -#pragma GCC diagnostic pop -#endif -#ifdef _WIN32 - /* Old versions of the Windows CRT do not terminate the snprintf output - buffer if it reaches the max size so we do that here. */ - work[BUFFSIZE - 1] = 0; -#endif -#elif defined(_MSC_VER) && (_MSC_VER < 1900) - _snprintf(work, BUFFSIZE, formatbuf, dnum); - work[BUFFSIZE - 1] = 0; #else /* float and double outputs do not work without snprintf support */ work[0] = 0; +#endif +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop #endif DEBUGASSERT(strlen(work) < BUFFSIZE); while(*work) { diff --git a/tests/server/Makefile.inc b/tests/server/Makefile.inc index 96da26d643..1b7bb1af94 100644 --- a/tests/server/Makefile.inc +++ b/tests/server/Makefile.inc @@ -40,6 +40,7 @@ CURLX_C = \ ../../lib/curlx/inet_pton.c \ ../../lib/curlx/multibyte.c \ ../../lib/curlx/nonblock.c \ + ../../lib/curlx/snprintf.c \ ../../lib/curlx/strcopy.c \ ../../lib/curlx/strerr.c \ ../../lib/curlx/strparse.c \ diff --git a/tests/server/first.h b/tests/server/first.h index 1de5f43a64..39feb64d62 100644 --- a/tests/server/first.h +++ b/tests/server/first.h @@ -64,9 +64,9 @@ extern const struct entry_s s_entries[]; #include -/* adjust for old MSVC */ -#if defined(_MSC_VER) && (_MSC_VER < 1900) -# define snprintf _snprintf +#ifdef _WIN32 +#include +#define snprintf curlx_win32_snprintf #endif #ifdef _WIN32 diff --git a/tests/server/tftpd.c b/tests/server/tftpd.c index aff8e3a1d6..44e7976f1c 100644 --- a/tests/server/tftpd.c +++ b/tests/server/tftpd.c @@ -606,8 +606,9 @@ static int validate_access(struct testcase *test, if(!strncmp("verifiedserver", filename, 14)) { char weare[128]; - size_t count = snprintf(weare, sizeof(weare), "WE ROOLZ: %ld\r\n", - (long)our_getpid()); + size_t count; + snprintf(weare, sizeof(weare), "WE ROOLZ: %ld\r\n", (long)our_getpid()); + count = strlen(weare); logmsg("Are-we-friendly question received"); test->buffer = curlx_strdup(weare);