Merge remote-tracking branch 'origin/pr/1551' into development
diff --git a/ChangeLog b/ChangeLog
index 2789704..122cd2c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -23,6 +23,9 @@
* Add support for alternative CSR headers, as used by Microsoft and defined
in RFC 7468. Found by Michael Ernst. Fixes #767.
* Correct many misspellings. Fixed by MisterDA #2371.
+ * Provide an abstraction of vsnprintf to allow alternative implementations
+ for platforms that don't provide it. Based on contributions by Joris Aerts
+ and Nathaniel Wesley Filardo.
= mbed TLS 2.16.0 branch released 2018-12-21
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 0f72c17..00dbeb1 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -50,6 +50,11 @@
!defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO)
#define MBEDTLS_PLATFORM_SNPRINTF_ALT
#endif
+
+#if !defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && \
+ !defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO)
+#define MBEDTLS_PLATFORM_VSNPRINTF_ALT
+#endif
#endif /* _WIN32 */
#if defined(TARGET_LIKE_MBED) && \
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index c5d7bfe..f89bf96 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -226,6 +226,7 @@
//#define MBEDTLS_PLATFORM_FPRINTF_ALT
//#define MBEDTLS_PLATFORM_PRINTF_ALT
//#define MBEDTLS_PLATFORM_SNPRINTF_ALT
+//#define MBEDTLS_PLATFORM_VSNPRINTF_ALT
//#define MBEDTLS_PLATFORM_NV_SEED_ALT
//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT
@@ -3035,6 +3036,7 @@
//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */
/* Note: your snprintf must correctly zero-terminate the buffer! */
//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_VSNPRINTF_MACRO vsnprintf /**< Default vsnprintf macro to use, can be undefined */
//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
diff --git a/include/mbedtls/platform.h b/include/mbedtls/platform.h
index 89fe8a7..801a948 100644
--- a/include/mbedtls/platform.h
+++ b/include/mbedtls/platform.h
@@ -58,17 +58,33 @@
* \{
*/
+/* The older Microsoft Windows common runtime provides non-conforming
+ * implementations of some standard library functions, including snprintf
+ * and vsnprintf. This affects MSVC and MinGW builds.
+ */
+#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900)
+#define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF
+#define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF
+#endif
+
#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF)
-#if defined(_WIN32)
+#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF)
#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< The default \c snprintf function to use. */
#else
#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< The default \c snprintf function to use. */
#endif
#endif
+#if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF)
+#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF)
+#define MBEDTLS_PLATFORM_STD_VSNPRINTF mbedtls_platform_win32_vsnprintf /**< The default \c vsnprintf function to use. */
+#else
+#define MBEDTLS_PLATFORM_STD_VSNPRINTF vsnprintf /**< The default \c vsnprintf function to use. */
+#endif
+#endif
#if !defined(MBEDTLS_PLATFORM_STD_PRINTF)
#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< The default \c printf function to use. */
#endif
@@ -204,7 +220,7 @@
* - however it is acceptable to return -1 instead of the required length when
* the destination buffer is too short.
*/
-#if defined(_WIN32)
+#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF)
/* For Windows (inc. MSYS2), we provide our own fixed implementation */
int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... );
#endif
@@ -231,6 +247,41 @@
#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */
/*
+ * The function pointers for vsnprintf
+ *
+ * The vsnprintf implementation should conform to C99:
+ * - it *must* always correctly zero-terminate the buffer
+ * (except when n == 0, then it must leave the buffer untouched)
+ * - however it is acceptable to return -1 instead of the required length when
+ * the destination buffer is too short.
+ */
+#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF)
+/* For Older Windows (inc. MSYS2), we provide our own fixed implementation */
+int mbedtls_platform_win32_vsnprintf( char *s, size_t n, const char *fmt, va_list arg );
+#endif
+
+#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT)
+#include <stdarg.h>
+extern int (*mbedtls_vsnprintf)( char * s, size_t n, const char * format, va_list arg );
+
+/**
+ * \brief Set your own snprintf function pointer
+ *
+ * \param vsnprintf_func The \c vsnprintf function implementation
+ *
+ * \return \c 0
+ */
+int mbedtls_platform_set_vsnprintf( int (*vsnprintf_func)( char * s, size_t n,
+ const char * format, va_list arg ) );
+#else /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */
+#if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO)
+#define mbedtls_vsnprintf MBEDTLS_PLATFORM_VSNPRINTF_MACRO
+#else
+#define mbedtls_vsnprintf vsnprintf
+#endif /* MBEDTLS_PLATFORM_VSNPRINTF_MACRO */
+#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */
+
+/*
* The function pointers for exit
*/
#if defined(MBEDTLS_PLATFORM_EXIT_ALT)
diff --git a/library/debug.c b/library/debug.c
index 824cd02..6e1efbf 100644
--- a/library/debug.c
+++ b/library/debug.c
@@ -35,6 +35,7 @@
#define mbedtls_free free
#define mbedtls_time_t time_t
#define mbedtls_snprintf snprintf
+#define mbedtls_vsnprintf vsnprintf
#endif
#include "mbedtls/debug.h"
@@ -90,20 +91,7 @@
return;
va_start( argp, format );
-#if defined(_WIN32)
-#if defined(_TRUNCATE) && !defined(__MINGW32__)
- ret = _vsnprintf_s( str, DEBUG_BUF_SIZE, _TRUNCATE, format, argp );
-#else
- ret = _vsnprintf( str, DEBUG_BUF_SIZE, format, argp );
- if( ret < 0 || (size_t) ret == DEBUG_BUF_SIZE )
- {
- str[DEBUG_BUF_SIZE-1] = '\0';
- ret = -1;
- }
-#endif
-#else
- ret = vsnprintf( str, DEBUG_BUF_SIZE, format, argp );
-#endif
+ ret = mbedtls_vsnprintf( str, DEBUG_BUF_SIZE, format, argp );
va_end( argp );
if( ret >= 0 && ret < DEBUG_BUF_SIZE - 1 )
diff --git a/library/platform.c b/library/platform.c
index 73a6db9..5756159 100644
--- a/library/platform.c
+++ b/library/platform.c
@@ -82,28 +82,15 @@
!( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&
defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */
-#if defined(_WIN32)
+#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF)
#include <stdarg.h>
int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... )
{
int ret;
va_list argp;
- /* Avoid calling the invalid parameter handler by checking ourselves */
- if( s == NULL || n == 0 || fmt == NULL )
- return( -1 );
-
va_start( argp, fmt );
-#if defined(_TRUNCATE) && !defined(__MINGW32__)
- ret = _vsnprintf_s( s, n, _TRUNCATE, fmt, argp );
-#else
- ret = _vsnprintf( s, n, fmt, argp );
- if( ret < 0 || (size_t) ret == n )
- {
- s[n-1] = '\0';
- ret = -1;
- }
-#endif
+ ret = mbedtls_vsnprintf( s, n, fmt, argp );
va_end( argp );
return( ret );
@@ -140,6 +127,62 @@
}
#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */
+#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF)
+#include <stdarg.h>
+int mbedtls_platform_win32_vsnprintf( char *s, size_t n, const char *fmt, va_list arg )
+{
+ int ret;
+
+ /* Avoid calling the invalid parameter handler by checking ourselves */
+ if( s == NULL || n == 0 || fmt == NULL )
+ return( -1 );
+
+#if defined(_TRUNCATE)
+ ret = vsnprintf_s( s, n, _TRUNCATE, fmt, arg );
+#else
+ ret = vsnprintf( s, n, fmt, arg );
+ if( ret < 0 || (size_t) ret == n )
+ {
+ s[n-1] = '\0';
+ ret = -1;
+ }
+#endif
+
+ return( ret );
+}
+#endif
+
+#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT)
+#if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static int platform_vsnprintf_uninit( char * s, size_t n,
+ const char * format, va_list arg )
+{
+ ((void) s);
+ ((void) n);
+ ((void) format);
+ ((void) arg);
+ return( -1 );
+}
+
+#define MBEDTLS_PLATFORM_STD_VSNPRINTF platform_vsnprintf_uninit
+#endif /* !MBEDTLS_PLATFORM_STD_VSNPRINTF */
+
+int (*mbedtls_vsnprintf)( char * s, size_t n,
+ const char * format,
+ va_list arg ) = MBEDTLS_PLATFORM_STD_VSNPRINTF;
+
+int mbedtls_platform_set_vsnprintf( int (*vsnprintf_func)( char * s, size_t n,
+ const char * format,
+ va_list arg ) )
+{
+ mbedtls_vsnprintf = vsnprintf_func;
+ return( 0 );
+}
+#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */
+
#if defined(MBEDTLS_PLATFORM_PRINTF_ALT)
#if !defined(MBEDTLS_PLATFORM_STD_PRINTF)
/*
diff --git a/library/version_features.c b/library/version_features.c
index 4c36d3c..9750d20 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -72,6 +72,9 @@
#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT)
"MBEDTLS_PLATFORM_SNPRINTF_ALT",
#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */
+#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT)
+ "MBEDTLS_PLATFORM_VSNPRINTF_ALT",
+#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */
#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT)
"MBEDTLS_PLATFORM_NV_SEED_ALT",
#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */