[PATCH v2] msvcrt: Introduce vsprintf & vswprintf helper functions.

Gijs Vermeulen gijsvrm at gmail.com
Sat Jan 13 20:45:00 CST 2018


Signed-off-by: Gijs Vermeulen <gijsvrm at gmail.com>
---
 dlls/msvcrt/wcs.c | 318 +++++++++++++++++++++++-------------------------------
 1 file changed, 132 insertions(+), 186 deletions(-)

diff --git a/dlls/msvcrt/wcs.c b/dlls/msvcrt/wcs.c
index 098e0d5ba8..fb1173c859 100644
--- a/dlls/msvcrt/wcs.c
+++ b/dlls/msvcrt/wcs.c
@@ -720,20 +720,117 @@ printf_arg arg_clbk_positional(void *ctx, int pos, int type, __ms_va_list *valis
     return args[pos];
 }
 
+static int vsprintf_helper(DWORD options, char *str, MSVCRT_size_t sizeOfBuffer, MSVCRT_size_t count,
+        const char *format, MSVCRT__locale_t locale, __ms_va_list valist)
+{
+    static const char nullbyte = '\0';
+    printf_arg args_ctx[MSVCRT__ARGMAX+1];
+    struct _str_ctx_a puts_ctx;
+    int len, ret;
+    BOOL postional, secure, initially_positional;
+
+    len = sizeOfBuffer;
+    postional = options & MSVCRT_PRINTF_POSITIONAL_PARAMS;
+    initially_positional = postional;
+    secure = options & MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER;
+
+    if(secure && !postional)
+        if(sizeOfBuffer>count+1 && count!=-1) len = count+1;
+
+    puts_ctx.len = len;
+    puts_ctx.buf = str;
+
+    if(postional) {
+        memset(args_ctx, 0, sizeof(args_ctx));
+
+        ret = create_positional_ctx_a(args_ctx, format, valist);
+        if(ret < 0) {
+            MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
+            *MSVCRT__errno() = MSVCRT_EINVAL;
+            return ret;
+        } else if(!ret)
+            postional = FALSE;
+    }
+
+    ret = pf_printf_a(puts_clbk_str_a,
+            &puts_ctx, format, locale, options,
+            postional ? arg_clbk_positional : arg_clbk_valist,
+            postional ? args_ctx : NULL,
+            postional ? NULL : &valist);
+    puts_clbk_str_a(&puts_ctx, 1, &nullbyte);
+
+    if((secure && !initially_positional) && (ret<0 || ret==len)) {
+        if(count!=MSVCRT__TRUNCATE && count>sizeOfBuffer) {
+            MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", MSVCRT_ERANGE);
+            memset(str, 0, sizeOfBuffer);
+        } else
+            str[len-1] = '\0';
+
+        return -1;
+    }
+
+    return ret;
+}
+
+static int vswprintf_helper(DWORD options, MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer, MSVCRT_size_t count,
+        const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list valist)
+{
+    static const MSVCRT_wchar_t nullbyte = '\0';
+    printf_arg args_ctx[MSVCRT__ARGMAX+1];
+    struct _str_ctx_w puts_ctx;
+    int len, ret;
+    BOOL postional, secure, initially_positional;
+
+    len = sizeOfBuffer;
+    postional = options & MSVCRT_PRINTF_POSITIONAL_PARAMS;
+    initially_positional = postional;
+    secure = options & MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER;
+
+    if(secure && !postional)
+        if(sizeOfBuffer>count+1 && count!=-1) len = count+1;
+
+    puts_ctx.len = len;
+    puts_ctx.buf = str;
+
+    if(postional) {
+        memset(args_ctx, 0, sizeof(args_ctx));
+
+        ret = create_positional_ctx_w(args_ctx, format, valist);
+        if(ret < 0) {
+            MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
+            *MSVCRT__errno() = MSVCRT_EINVAL;
+            return ret;
+        } else if(!ret)
+            postional = FALSE;
+    }
+
+    ret = pf_printf_w(puts_clbk_str_w,
+            &puts_ctx, format, locale, options,
+            postional ? arg_clbk_positional : arg_clbk_valist,
+            postional ? args_ctx : NULL,
+            postional ? NULL : &valist);
+    puts_clbk_str_w(&puts_ctx, 1, &nullbyte);
+
+    if((secure && !initially_positional) && (ret<0 || ret==len)) {
+        if(count!=MSVCRT__TRUNCATE && count>sizeOfBuffer) {
+            MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", MSVCRT_ERANGE);
+            memset(str, 0, sizeOfBuffer*sizeof(MSVCRT_wchar_t));
+        } else
+            str[len-1] = '\0';
+
+        return -1;
+    }
+
+    return ret;
+}
+
 /*********************************************************************
  *              _vsnprintf (MSVCRT.@)
  */
 int CDECL MSVCRT_vsnprintf( char *str, MSVCRT_size_t len,
                             const char *format, __ms_va_list valist )
 {
-    static const char nullbyte = '\0';
-    struct _str_ctx_a ctx = {len, str};
-    int ret;
-
-    ret = pf_printf_a(puts_clbk_str_a, &ctx, format, NULL, 0,
-            arg_clbk_valist, NULL, &valist);
-    puts_clbk_str_a(&ctx, 1, &nullbyte);
-    return ret;
+    return vsprintf_helper(0, str, len, 0, format, NULL, valist);
 }
 
 #if _MSVCR_VER>=140
@@ -793,14 +890,7 @@ int CDECL MSVCRT__stdio_common_vsprintf( unsigned __int64 options, char *str, MS
 int CDECL MSVCRT_vsnprintf_l( char *str, MSVCRT_size_t len, const char *format,
                             MSVCRT__locale_t locale, __ms_va_list valist )
 {
-    static const char nullbyte = '\0';
-    struct _str_ctx_a ctx = {len, str};
-    int ret;
-
-    ret = pf_printf_a(puts_clbk_str_a, &ctx, format, locale, 0,
-            arg_clbk_valist, NULL, &valist);
-    puts_clbk_str_a(&ctx, 1, &nullbyte);
-    return ret;
+    return vsprintf_helper(0, str, len, 0, format, locale, valist);
 }
 
 /*********************************************************************
@@ -826,69 +916,6 @@ int WINAPIV MSVCRT_sprintf_l(char *str, const char *format,
     return retval;
 }
 
-static int CDECL MSVCRT_vsnprintf_s_l_opt( char *str, MSVCRT_size_t sizeOfBuffer,
-        MSVCRT_size_t count, const char *format, DWORD options,
-        MSVCRT__locale_t locale, __ms_va_list valist )
-{
-    static const char nullbyte = '\0';
-    struct _str_ctx_a ctx;
-    int len, ret;
-
-    if(sizeOfBuffer<count+1 || count==-1)
-        len = sizeOfBuffer;
-    else
-        len = count+1;
-
-    ctx.len = len;
-    ctx.buf = str;
-    ret = pf_printf_a(puts_clbk_str_a, &ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
-            arg_clbk_valist, NULL, &valist);
-    puts_clbk_str_a(&ctx, 1, &nullbyte);
-
-    if(ret<0 || ret==len) {
-        if(count!=MSVCRT__TRUNCATE && count>sizeOfBuffer) {
-            MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", MSVCRT_ERANGE);
-            memset(str, 0, sizeOfBuffer);
-        } else
-            str[len-1] = '\0';
-
-        return -1;
-    }
-
-    return ret;
-}
-
-static int MSVCRT_vsnwprintf_s_l_opt( MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer,
-        MSVCRT_size_t count, const MSVCRT_wchar_t *format, DWORD options,
-        MSVCRT__locale_t locale, __ms_va_list valist)
-{
-    static const MSVCRT_wchar_t nullbyte = '\0';
-    struct _str_ctx_w ctx;
-    int len, ret;
-
-    len = sizeOfBuffer;
-    if(count!=-1 && len>count+1)
-        len = count+1;
-
-    ctx.len = len;
-    ctx.buf = str;
-    ret = pf_printf_w(puts_clbk_str_w, &ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
-            arg_clbk_valist, NULL, &valist);
-    puts_clbk_str_w(&ctx, 1, &nullbyte);
-
-    if(ret<0 || ret==len) {
-        if(count!=MSVCRT__TRUNCATE && count>sizeOfBuffer) {
-            MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", MSVCRT_ERANGE);
-            memset(str, 0, sizeOfBuffer*sizeof(MSVCRT_wchar_t));
-        } else
-            str[len-1] = '\0';
-
-        return -1;
-    }
-
-    return ret;
-}
-
 /*********************************************************************
  *		_vsnprintf_s_l (MSVCRT.@)
  */
@@ -896,7 +923,8 @@ int CDECL MSVCRT_vsnprintf_s_l( char *str, MSVCRT_size_t sizeOfBuffer,
         MSVCRT_size_t count, const char *format,
         MSVCRT__locale_t locale, __ms_va_list valist )
 {
-    return MSVCRT_vsnprintf_s_l_opt(str, sizeOfBuffer, count, format, 0, locale, valist);
+    return vsprintf_helper(MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER, str, sizeOfBuffer, count, format,
+            locale, valist);
 }
 
 /*********************************************************************
@@ -942,7 +970,8 @@ int CDECL MSVCRT__stdio_common_vsnprintf_s( unsigned __int64 options,
 {
     if (options & ~UCRTBASE_PRINTF_MASK)
         FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
-    return MSVCRT_vsnprintf_s_l_opt(str, sizeOfBuffer, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
+    return vsprintf_helper((options & UCRTBASE_PRINTF_MASK) | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER, str,
+            sizeOfBuffer, count, format, locale, valist);
 }
 
 /*********************************************************************
@@ -954,7 +983,8 @@ int CDECL MSVCRT__stdio_common_vsnwprintf_s( unsigned __int64 options,
 {
     if (options & ~UCRTBASE_PRINTF_MASK)
         FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
-    return MSVCRT_vsnwprintf_s_l_opt(str, sizeOfBuffer, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
+    return vswprintf_helper((options & UCRTBASE_PRINTF_MASK) | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER, str,
+            sizeOfBuffer, count, format, locale, valist);
 }
 
 /*********************************************************************
@@ -974,9 +1004,7 @@ int CDECL MSVCRT__stdio_common_vsprintf_s( unsigned __int64 options,
         char *str, MSVCRT_size_t count, const char *format,
         MSVCRT__locale_t locale, __ms_va_list valist )
 {
-    if (options & ~UCRTBASE_PRINTF_MASK)
-        FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
-    return MSVCRT_vsnprintf_s_l_opt(str, INT_MAX, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
+    return MSVCRT__stdio_common_vsnprintf_s(options, str, INT_MAX, count, format, locale, valist);
 }
 
 #endif /* _MSVCR_VER>=140 */
@@ -1011,28 +1039,8 @@ int CDECL MSVCRT__vscprintf( const char *format, __ms_va_list valist )
 int CDECL MSVCRT__vscprintf_p_l(const char *format,
         MSVCRT__locale_t locale, __ms_va_list args)
 {
-    printf_arg args_ctx[MSVCRT__ARGMAX+1];
-    struct _str_ctx_a puts_ctx = {INT_MAX, NULL};
-    int ret;
-
-    memset(args_ctx, 0, sizeof(args_ctx));
-
-    ret = create_positional_ctx_a(args_ctx, format, args);
-    if(ret < 0)  {
-        MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
-        *MSVCRT__errno() = MSVCRT_EINVAL;
-        return ret;
-    } else if(ret == 0) {
-        ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
-                MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
-                arg_clbk_valist, NULL, &args);
-    } else {
-        ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
-                MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
-                arg_clbk_positional, args_ctx, NULL);
-    }
-
-    return ret;
+    return vsprintf_helper(MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
+            NULL, INT_MAX, 0, format, locale, args);
 }
 
 /*********************************************************************
@@ -1103,14 +1111,7 @@ int WINAPIV MSVCRT__scprintf(const char *format, ...)
 int CDECL MSVCRT_vsnwprintf(MSVCRT_wchar_t *str, MSVCRT_size_t len,
         const MSVCRT_wchar_t *format, __ms_va_list valist)
 {
-    static const MSVCRT_wchar_t nullbyte = '\0';
-    struct _str_ctx_w ctx = {len, str};
-    int ret;
-
-    ret = pf_printf_w(puts_clbk_str_w, &ctx, format, NULL, 0,
-            arg_clbk_valist, NULL, &valist);
-    puts_clbk_str_w(&ctx, 1, &nullbyte);
-    return ret;
+    return vswprintf_helper(0, str, len, 0, format, NULL, valist);
 }
 
 /*********************************************************************
@@ -1120,41 +1121,7 @@ int CDECL MSVCRT_vsnwprintf_l(MSVCRT_wchar_t *str, MSVCRT_size_t len,
         const MSVCRT_wchar_t *format, MSVCRT__locale_t locale,
         __ms_va_list valist)
 {
-    static const MSVCRT_wchar_t nullbyte = '\0';
-    struct _str_ctx_w ctx = {len, str};
-    int ret;
-
-    ret = pf_printf_w(puts_clbk_str_w, &ctx, format, locale, 0,
-            arg_clbk_valist, NULL, &valist);
-    puts_clbk_str_w(&ctx, 1, &nullbyte);
-    return ret;
-}
-
-static int MSVCRT_vswprintf_p_l_opt(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
-        const MSVCRT_wchar_t *format, DWORD options, MSVCRT__locale_t locale, __ms_va_list args)
-{
-    static const MSVCRT_wchar_t nullbyte = '\0';
-    printf_arg args_ctx[MSVCRT__ARGMAX+1];
-    struct _str_ctx_w puts_ctx = {length, buffer};
-    int ret;
-
-    memset(args_ctx, 0, sizeof(args_ctx));
-
-    ret = create_positional_ctx_w(args_ctx, format, args);
-    if(ret < 0)  {
-        MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
-        *MSVCRT__errno() = MSVCRT_EINVAL;
-        return ret;
-    } else if(ret == 0)
-        ret = pf_printf_w(puts_clbk_str_w, &puts_ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
-                arg_clbk_valist, NULL, &args);
-    else
-        ret = pf_printf_w(puts_clbk_str_w, &puts_ctx, format, locale,
-                MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
-                arg_clbk_positional, args_ctx, NULL);
-
-    puts_clbk_str_w(&puts_ctx, 1, &nullbyte);
-    return ret;
+    return vswprintf_helper(0, str, len, 0, format, locale, valist);
 }
 
 /*********************************************************************
@@ -1163,7 +1130,8 @@ static int MSVCRT_vswprintf_p_l_opt(MSVCRT_wchar_t *buffer, MSVCRT_size_t length
 int CDECL MSVCRT_vswprintf_p_l(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
         const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list args)
 {
-    return MSVCRT_vswprintf_p_l_opt(buffer, length, format, 0, locale, args);
+    return vswprintf_helper(MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
+            buffer, length, 0, format, locale, args);
 }
 
 #if _MSVCR_VER>=80
@@ -1173,7 +1141,7 @@ int CDECL MSVCRT_vswprintf_p_l(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
 int CDECL MSVCRT__vswprintf_p(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
         const MSVCRT_wchar_t *format, __ms_va_list args)
 {
-    return MSVCRT_vswprintf_p_l_opt(buffer, length, format, 0, NULL, args);
+    return MSVCRT_vswprintf_p_l(buffer, length, format, NULL, args);
 }
 #endif
 
@@ -1187,7 +1155,8 @@ int CDECL MSVCRT__stdio_common_vswprintf_p( unsigned __int64 options,
 {
     if (options & ~UCRTBASE_PRINTF_MASK)
         FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
-    return MSVCRT_vswprintf_p_l_opt(str, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
+    return vswprintf_helper((options & UCRTBASE_PRINTF_MASK) | (MSVCRT_PRINTF_POSITIONAL_PARAMS |
+            MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER), str, count, 0, format, locale, valist);
 }
 #endif
 
@@ -1198,7 +1167,8 @@ int CDECL MSVCRT_vsnwprintf_s_l( MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer
         MSVCRT_size_t count, const MSVCRT_wchar_t *format,
         MSVCRT__locale_t locale, __ms_va_list valist)
 {
-    return MSVCRT_vsnwprintf_s_l_opt(str, sizeOfBuffer, count, format, 0, locale, valist);
+    return vswprintf_helper(MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER, str, sizeOfBuffer, count, format,
+            locale, valist);
 }
 
 /*********************************************************************
@@ -1444,7 +1414,8 @@ int CDECL MSVCRT__vscwprintf_l( const MSVCRT_wchar_t *format, MSVCRT__locale_t l
  */
 int CDECL MSVCRT__vscwprintf_p_l( const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list args )
 {
-    return MSVCRT_vswprintf_p_l_opt( NULL, INT_MAX, format, 0, locale, args );
+    return vswprintf_helper(MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER, NULL, INT_MAX,
+            0, format, locale, args);
 }
 
 #if _MSVCR_VER>=80
@@ -1453,7 +1424,7 @@ int CDECL MSVCRT__vscwprintf_p_l( const MSVCRT_wchar_t *format, MSVCRT__locale_t
  */
 int CDECL MSVCRT__vscwprintf_p(const MSVCRT_wchar_t *format, __ms_va_list args)
 {
-    return MSVCRT_vswprintf_p_l_opt(NULL, INT_MAX, format, 0, NULL, args);
+    return MSVCRT__vscwprintf_p_l(format, NULL, args);
 }
 #endif
 
@@ -1476,40 +1447,14 @@ int CDECL MSVCRT_vswprintf_s_l(MSVCRT_wchar_t* str, MSVCRT_size_t numberOfElemen
             format, locale, args );
 }
 
-static int MSVCRT_vsprintf_p_l_opt(char *buffer, MSVCRT_size_t length, const char *format,
-        DWORD options, MSVCRT__locale_t locale, __ms_va_list args)
-{
-    static const char nullbyte = '\0';
-    printf_arg args_ctx[MSVCRT__ARGMAX+1];
-    struct _str_ctx_a puts_ctx = {length, buffer};
-    int ret;
-
-    memset(args_ctx, 0, sizeof(args_ctx));
-
-    ret = create_positional_ctx_a(args_ctx, format, args);
-    if(ret < 0) {
-        MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
-        *MSVCRT__errno() = MSVCRT_EINVAL;
-        return ret;
-    } else if(ret == 0)
-        ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
-                MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options, arg_clbk_valist, NULL, &args);
-    else
-        ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
-                MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
-                arg_clbk_positional, args_ctx, NULL);
-
-    puts_clbk_str_a(&puts_ctx, 1, &nullbyte);
-    return ret;
-}
-
 /*********************************************************************
  *              _vsprintf_p_l (MSVCRT.@)
  */
 int CDECL MSVCRT_vsprintf_p_l(char *buffer, MSVCRT_size_t length, const char *format,
         MSVCRT__locale_t locale, __ms_va_list args)
 {
-    return MSVCRT_vsprintf_p_l_opt(buffer, length, format, 0, locale, args);
+    return vsprintf_helper(MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER, buffer, length,
+        0, format, locale, args);
 }
 
 /*********************************************************************
@@ -1530,7 +1475,8 @@ int CDECL MSVCRT__stdio_common_vsprintf_p(unsigned __int64 options, char *buffer
 {
     if (options & ~UCRTBASE_PRINTF_MASK)
         FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
-    return MSVCRT_vsprintf_p_l_opt(buffer, length, format, options & UCRTBASE_PRINTF_MASK, locale, args);
+    return vsprintf_helper((options & UCRTBASE_PRINTF_MASK) | (MSVCRT_PRINTF_POSITIONAL_PARAMS |
+            MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER), buffer, length, 0, format, locale, args);
 }
 #endif
 
@@ -1591,7 +1537,7 @@ int WINAPIV MSVCRT_swprintf_p_l(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
     int r;
 
     __ms_va_start(valist, locale);
-    r = MSVCRT_vswprintf_p_l_opt(buffer, length, format, 0, locale, valist);
+    r = MSVCRT_vswprintf_p_l(buffer, length, format, locale, valist);
     __ms_va_end(valist);
 
     return r;
-- 
2.15.1




More information about the wine-devel mailing list