1/*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2014-2021. All rights reserved.
3 * Licensed under Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 *          http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
8 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 * Description: vsnprintf_s  function
12 * Create: 2014-02-25
13 */
14
15#include "secureprintoutput.h"
16
17#if SECUREC_ENABLE_VSNPRINTF
18/*
19 * <FUNCTION DESCRIPTION>
20 *    The vsnprintf_s function is equivalent to the vsnprintf function
21 *     except for the parameter destMax/count and the explicit runtime-constraints violation
22 *    The vsnprintf_s function takes a pointer to an argument list, then formats
23 *    and writes up to count characters of the given data to the memory pointed
24 *    to by strDest and appends a terminating null.
25 *
26 * <INPUT PARAMETERS>
27 *    strDest                  Storage location for the output.
28 *    destMax                The size of the strDest for output.
29 *    count                    Maximum number of character to write(not including
30 *                                the terminating NULL)
31 *    format                   Format-control string.
32 *    argList                     pointer to list of arguments.
33 *
34 * <OUTPUT PARAMETERS>
35 *    strDest                is updated
36 *
37 * <RETURN VALUE>
38 *    return  the number of characters written, not including the terminating null
39 *    return -1 if an  error occurs.
40 *    return -1 if count < destMax and the output string  has been truncated
41 *
42 * If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
43 */
44int vsnprintf_s(char *strDest, size_t destMax, size_t count, const char *format, va_list argList)
45{
46    int retVal;
47
48    if (SECUREC_VSNPRINTF_PARAM_ERROR(format, strDest, destMax, count, SECUREC_STRING_MAX_LEN)) {
49        SECUREC_VSPRINTF_CLEAR_DEST(strDest, destMax, SECUREC_STRING_MAX_LEN);
50        SECUREC_ERROR_INVALID_PARAMTER("vsnprintf_s");
51        return -1;
52    }
53
54    if (destMax > count) {
55        retVal = SecVsnprintfImpl(strDest, count + 1, format, argList);
56        if (retVal == SECUREC_PRINTF_TRUNCATE) {  /* To keep dest buffer not destroyed 2014.2.18 */
57            /* The string has been truncated, return  -1 */
58            return -1;          /* To skip error handler,  return strlen(strDest) or -1 */
59        }
60    } else {
61        retVal = SecVsnprintfImpl(strDest, destMax, format, argList);
62#ifdef SECUREC_COMPATIBLE_WIN_FORMAT
63        if (retVal == SECUREC_PRINTF_TRUNCATE && count == (size_t)(-1)) {
64            return -1;
65        }
66#endif
67    }
68
69    if (retVal < 0) {
70        strDest[0] = '\0';      /* Empty the dest strDest */
71        if (retVal == SECUREC_PRINTF_TRUNCATE) {
72            /* Buffer too small */
73            SECUREC_ERROR_INVALID_RANGE("vsnprintf_s");
74        }
75        SECUREC_ERROR_INVALID_PARAMTER("vsnprintf_s");
76        return -1;
77    }
78
79    return retVal;
80}
81#if SECUREC_EXPORT_KERNEL_SYMBOL
82EXPORT_SYMBOL(vsnprintf_s);
83#endif
84#endif
85
86#if SECUREC_SNPRINTF_TRUNCATED
87/*
88 * <FUNCTION DESCRIPTION>
89 *    The vsnprintf_truncated_s function is equivalent to the vsnprintf function
90 *     except for the parameter destMax/count and the explicit runtime-constraints violation
91 *    The vsnprintf_truncated_s function takes a pointer to an argument list, then formats
92 *    and writes up to count characters of the given data to the memory pointed
93 *    to by strDest and appends a terminating null.
94 *
95 * <INPUT PARAMETERS>
96 *    strDest                  Storage location for the output.
97 *    destMax                The size of the strDest for output.
98 *                                the terminating NULL)
99 *    format                   Format-control string.
100 *    argList                     pointer to list of arguments.
101 *
102 * <OUTPUT PARAMETERS>
103 *    strDest                is updated
104 *
105 * <RETURN VALUE>
106 *    return  the number of characters written, not including the terminating null
107 *    return -1 if an  error occurs.
108 *    return destMax-1 if output string  has been truncated
109 *
110 * If there is a runtime-constraint violation, strDest[0] will be set to the '\0' when strDest and destMax valid
111 */
112int vsnprintf_truncated_s(char *strDest, size_t destMax, const char *format, va_list argList)
113{
114    int retVal;
115
116    if (SECUREC_VSPRINTF_PARAM_ERROR(format, strDest, destMax, SECUREC_STRING_MAX_LEN)) {
117        SECUREC_VSPRINTF_CLEAR_DEST(strDest, destMax, SECUREC_STRING_MAX_LEN);
118        SECUREC_ERROR_INVALID_PARAMTER("vsnprintf_truncated_s");
119        return -1;
120    }
121
122    retVal = SecVsnprintfImpl(strDest, destMax, format, argList);
123    if (retVal < 0) {
124        if (retVal == SECUREC_PRINTF_TRUNCATE) {
125            return (int)(destMax - 1);  /* To skip error handler,  return strlen(strDest) */
126        }
127        strDest[0] = '\0';      /* Empty the dest strDest */
128        SECUREC_ERROR_INVALID_PARAMTER("vsnprintf_truncated_s");
129        return -1;
130    }
131
132    return retVal;
133}
134#if SECUREC_EXPORT_KERNEL_SYMBOL
135EXPORT_SYMBOL(vsnprintf_truncated_s);
136#endif
137#endif
138
139