1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 /* Avoid duplicate header files,not include securecutil.h */
17 #include "securecutil.h"
18 #if SECUREC_IN_KERNEL == 0
19 #include "secureprintoutput.h"
20 #endif
21
22
23 #if SECUREC_IN_KERNEL == 0
24 /* put a char to output */
25 #define SECUREC_PUTC(_c,_stream) ((--(_stream)->count >= 0) ? ((*(_stream)->cur++ = (char)(_c)) & 0xff) : EOF)
26 /* to clear e835 */
27 #define SECUREC_PUTC_ZERO(_stream) ((--(_stream)->count >= 0) ? ((*(_stream)->cur++ = (char)('\0'))) : EOF)
28
SecPutWcharStrEndingZero(SecPrintfStream * str,int zeroNum)29 int SecPutWcharStrEndingZero(SecPrintfStream *str, int zeroNum)
30 {
31 int succeed = 0;
32 int i;
33
34 for (i = 0; i < zeroNum && (SECUREC_PUTC_ZERO(str) != EOF); ++i) {
35 }
36 if (i == zeroNum) {
37 succeed = 1;
38 }
39 return succeed;
40 }
41
SecVsnprintfImpl(char * string,size_t count,const char * format,va_list arglist)42 int SecVsnprintfImpl(char *string, size_t count, const char *format, va_list arglist)
43 {
44 SecPrintfStream str;
45 int retVal;
46
47 str.count = (int)count; /* this count include \0 character */
48 str.cur = string;
49
50 retVal = SecOutputS(&str, format, arglist);
51 if ((retVal >= 0) && (SECUREC_PUTC_ZERO(&str) != EOF)) {
52 return (retVal);
53 } else if (str.count < 0) {
54 /* the buffer was too small; we return truncation */
55 string[count - 1] = 0;
56 return SECUREC_PRINTF_TRUNCATE;
57 }
58
59 return -1;
60 }
61
SecWriteMultiChar(char ch,int num,SecPrintfStream * f,int * pnumwritten)62 void SecWriteMultiChar(char ch, int num, SecPrintfStream *f, int *pnumwritten)
63 {
64 int count = num;
65 while (count-- > 0) {
66 if (SECUREC_PUTC(ch, f) == EOF) {
67 *pnumwritten = -1;
68 break;
69 } else {
70 ++(*pnumwritten);
71 }
72 }
73 }
74
SecWriteString(const char * string,int len,SecPrintfStream * f,int * pnumwritten)75 void SecWriteString(const char *string, int len, SecPrintfStream *f, int *pnumwritten)
76 {
77 const char *str = string;
78 int count = len;
79 while (count-- > 0) {
80 if (SECUREC_PUTC(*str, f) == EOF) {
81 *pnumwritten = -1;
82 break;
83 } else {
84 ++(*pnumwritten);
85 ++str;
86 }
87 }
88 }
89 #endif
90
91 /* Following function "U64Div32" realized the operation of division between an unsigned 64-bits
92 * number and an unsigned 32-bits number.
93 * these codes are contributed by Dopra team in syslib.
94 */
95 #if defined(SECUREC_VXWORKS_VERSION_5_4)
96
97 #define SECUREC_MAX_SHIFT_NUM 32
98 #define SECUREC_MASK_BIT_ALL 0xFFFFFFFF
99 #define SECUREC_MASK_BIT_32 0x80000000
100 #define SECUREC_MASK_BIT_01 0x00000001
101 #define SECUREC_MASK_HI_NBITS(x) (SECUREC_MASK_BIT_ALL << (SECUREC_MAX_SHIFT_NUM - (x)))
102
103 typedef enum {
104 SEC_BIT64_GREAT,
105 SEC_BIT64_EQUAL,
106 SEC_BIT64_LESS
107 } SecCompareResult;
108
SecBigIntSub(SecUnsignedInt32 * aHi,SecUnsignedInt32 * aLo,const SecUnsignedInt32 bHi,const SecUnsignedInt32 bLo)109 static void SecBigIntSub(SecUnsignedInt32 *aHi, SecUnsignedInt32 *aLo, const SecUnsignedInt32 bHi,
110 const SecUnsignedInt32 bLo)
111 {
112 if (*aLo < bLo) {
113 *aHi -= (bHi + 1);
114 } else {
115 *aHi -= (bHi);
116 }
117 *aLo -= bLo;
118 }
119
SecBigIntCompare(const SecUnsignedInt32 aHi,const SecUnsignedInt32 aLo,const SecUnsignedInt32 bHi,const SecUnsignedInt32 bLo)120 static SecCompareResult SecBigIntCompare(const SecUnsignedInt32 aHi, const SecUnsignedInt32 aLo,
121 const SecUnsignedInt32 bHi, const SecUnsignedInt32 bLo)
122 {
123 if (aHi > bHi) {
124 return SEC_BIT64_GREAT;
125 } else if ((aHi == bHi) && (aLo > bLo)) {
126 return SEC_BIT64_GREAT;
127 } else if ((aHi == bHi) && (aLo == bLo)) {
128 return SEC_BIT64_EQUAL;
129 } else {
130 return SEC_BIT64_LESS;
131 }
132 }
133
SecU64Div64Ret(SecUnsignedInt32 tmpQuoHi,SecUnsignedInt32 tmpQuoLo,SecUnsignedInt32 tmpDividendHi,SecUnsignedInt32 tmpDividendLo,SecUnsignedInt32 * pQuotientHigh,SecUnsignedInt32 * pQuotientLow,SecUnsignedInt32 * pRemainderHigh,SecUnsignedInt32 * pRemainderLow)134 static void SecU64Div64Ret(SecUnsignedInt32 tmpQuoHi, SecUnsignedInt32 tmpQuoLo,
135 SecUnsignedInt32 tmpDividendHi, SecUnsignedInt32 tmpDividendLo,
136 SecUnsignedInt32 *pQuotientHigh, SecUnsignedInt32 *pQuotientLow,
137 SecUnsignedInt32 *pRemainderHigh, SecUnsignedInt32 *pRemainderLow)
138 {
139 *pQuotientHigh = tmpQuoHi;
140 *pQuotientLow = tmpQuoLo;
141
142 if ((pRemainderHigh != NULL)
143 && (pRemainderLow != NULL)) {
144 *pRemainderHigh = tmpDividendHi;
145 *pRemainderLow = tmpDividendLo;
146 }
147 return;
148 }
149
SecU64Div64(SecUnsignedInt32 dividendHigh,SecUnsignedInt32 dividendLow,SecUnsignedInt32 divisorHigh,SecUnsignedInt32 divisorLow,SecUnsignedInt32 * pQuotientHigh,SecUnsignedInt32 * pQuotientLow,SecUnsignedInt32 * pRemainderHigh,SecUnsignedInt32 * pRemainderLow)150 static int SecU64Div64(SecUnsignedInt32 dividendHigh, SecUnsignedInt32 dividendLow,
151 SecUnsignedInt32 divisorHigh, SecUnsignedInt32 divisorLow,
152 SecUnsignedInt32 *pQuotientHigh, SecUnsignedInt32 *pQuotientLow,
153 SecUnsignedInt32 *pRemainderHigh, SecUnsignedInt32 *pRemainderLow)
154 {
155 signed char scShiftNumHi = 0;
156 signed char scShiftNumLo = 0;
157 SecUnsignedInt32 tmpQuoHi;
158 SecUnsignedInt32 tmpQuoLo;
159 SecUnsignedInt32 tmpDividendHi;
160 SecUnsignedInt32 tmpDividendLo;
161 SecUnsignedInt32 tmpDivisorHi;
162 SecUnsignedInt32 tmpDivisorLo;
163 SecCompareResult etmpResult;
164
165 if ((pQuotientHigh == NULL) || (pQuotientLow == NULL)) {
166 return -1;
167 }
168
169 if (divisorHigh == 0) {
170 if (divisorLow == 0) {
171 return -1;
172 } else if (divisorLow == 1) {
173 *pQuotientHigh = dividendHigh;
174 *pQuotientLow = dividendLow;
175
176 if (pRemainderHigh != NULL && pRemainderLow != NULL) {
177 *pRemainderHigh = 0;
178 *pRemainderLow = 0;
179 }
180
181 return 0;
182 }
183 }
184
185 tmpQuoHi = tmpQuoLo = 0;
186 tmpDividendHi = dividendHigh;
187 tmpDividendLo = dividendLow;
188
189 /* if divisor is larger than dividend, quotient equals to zero,
190 * remainder equals to dividends */
191 etmpResult = SecBigIntCompare(dividendHigh, dividendLow, divisorHigh, divisorLow);
192
193 if (etmpResult == SEC_BIT64_LESS) {
194 SecU64Div64Ret(tmpQuoHi, tmpQuoLo,
195 tmpDividendHi, tmpDividendLo, pQuotientHigh, pQuotientLow, pRemainderHigh, pRemainderLow);
196 return 0;
197 }
198
199 else if (etmpResult == SEC_BIT64_EQUAL) {
200 *pQuotientHigh = 0;
201 *pQuotientLow = 1;
202
203 if ((pRemainderHigh != NULL) && (pRemainderLow != NULL)) {
204 *pRemainderHigh = 0;
205 *pRemainderLow = 0;
206 }
207
208 return 0;
209 }
210
211 /* get shift number to implement divide arithmetic */
212 if (divisorHigh > 0) {
213 for (scShiftNumHi = 0; scShiftNumHi < SECUREC_MAX_SHIFT_NUM; scShiftNumHi++) {
214 if ((divisorHigh << (SecUnsignedInt32)(unsigned char)scShiftNumHi) & SECUREC_MASK_BIT_32) {
215 break;
216 }
217 }
218 } else {
219 for (scShiftNumLo = 0; scShiftNumLo < SECUREC_MAX_SHIFT_NUM; scShiftNumLo++) {
220 if ((divisorLow << scShiftNumLo) & SECUREC_MASK_BIT_32) {
221 break;
222 }
223 }
224 }
225
226 if (divisorHigh > 0) {
227 /* divisor's high 32 bits doesn't equal to zero */
228
229 for (; scShiftNumHi >= 0; scShiftNumHi--) {
230
231 if (scShiftNumHi == 0) {
232 tmpDivisorHi = divisorHigh;
233 } else {
234 tmpDivisorHi = (divisorHigh << (SecUnsignedInt32)(unsigned char)scShiftNumHi)
235 | (divisorLow >> (SECUREC_MAX_SHIFT_NUM - scShiftNumHi));
236 }
237
238 tmpDivisorLo = divisorLow << (SecUnsignedInt32)(unsigned char)scShiftNumHi;
239
240 etmpResult = SecBigIntCompare(tmpDividendHi, tmpDividendLo, tmpDivisorHi, tmpDivisorLo);
241
242 if (etmpResult != SEC_BIT64_LESS) {
243 SecBigIntSub(&tmpDividendHi, &tmpDividendLo, tmpDivisorHi, tmpDivisorLo);
244
245 tmpQuoLo |= (SecUnsignedInt32)(1 << (SecUnsignedInt32)(unsigned char)scShiftNumHi);
246
247 if ((tmpDividendHi == 0) && (tmpDividendLo == 0)) {
248 SecU64Div64Ret(tmpQuoHi, tmpQuoLo,
249 tmpDividendHi, tmpDividendLo,
250 pQuotientHigh, pQuotientLow, pRemainderHigh, pRemainderLow);
251 return 0;
252 }
253 }
254 if (scShiftNumHi == 0) {
255 break;
256 }
257 }
258
259 } else {
260 /* divisor's high 32 bits equals to zero */
261
262 scShiftNumHi = scShiftNumLo;
263
264 for (; scShiftNumHi >= 0; scShiftNumHi--) {
265 tmpDivisorHi = divisorLow << (SecUnsignedInt32)(unsigned char)scShiftNumHi;
266 etmpResult = SecBigIntCompare(tmpDividendHi, tmpDividendLo, tmpDivisorHi, 0);
267
268 if (etmpResult != SEC_BIT64_LESS) {
269 SecUnsignedInt32 tmp = 0;
270 SecBigIntSub(&tmpDividendHi, &tmpDividendLo, tmpDivisorHi, tmp);
271
272 tmpQuoHi |= (SecUnsignedInt32)(1 << (SecUnsignedInt32)(unsigned char)scShiftNumHi);
273
274 if ((tmpDividendHi == 0) && (tmpDividendLo == 0)) {
275 SecU64Div64Ret(tmpQuoHi, tmpQuoLo, tmpDividendHi, tmpDividendLo,
276 pQuotientHigh, pQuotientLow, pRemainderHigh, pRemainderLow);
277 return 0;
278 }
279 }
280 if (scShiftNumHi == 0) {
281 break;
282 }
283 }
284
285 for (scShiftNumHi = SECUREC_MAX_SHIFT_NUM - 1; scShiftNumHi >= 0; scShiftNumHi--) {
286 if (scShiftNumHi == 0) {
287 tmpDivisorHi = 0;
288 } else {
289 tmpDivisorHi = divisorLow >> (SECUREC_MAX_SHIFT_NUM - scShiftNumHi);
290 }
291
292 tmpDivisorLo = divisorLow << (SecUnsignedInt32)(unsigned char)scShiftNumHi;
293
294 etmpResult = SecBigIntCompare(tmpDividendHi, tmpDividendLo, tmpDivisorHi, tmpDivisorLo);
295
296 if (etmpResult != SEC_BIT64_LESS) {
297 SecBigIntSub(&tmpDividendHi, &tmpDividendLo, tmpDivisorHi, tmpDivisorLo);
298
299 tmpQuoLo |= (SecUnsignedInt32)(1 << (SecUnsignedInt32)(unsigned char)scShiftNumHi);
300
301 if ((tmpDividendHi == 0) && (tmpDividendLo == 0)) {
302 SecU64Div64Ret(tmpQuoHi, tmpQuoLo, tmpDividendHi, tmpDividendLo,
303 pQuotientHigh, pQuotientLow, pRemainderHigh, pRemainderLow);
304 return 0;
305 }
306 }
307 if (scShiftNumHi == 0) {
308 break;
309 }
310 }
311
312 }
313
314 SecU64Div64Ret(tmpQuoHi, tmpQuoLo,
315 tmpDividendHi, tmpDividendLo, pQuotientHigh, pQuotientLow, pRemainderHigh, pRemainderLow);
316 return 0;
317 }
318
SecU64Div32(SecUnsignedInt32 dividendHigh,SecUnsignedInt32 dividendLow,SecUnsignedInt32 divisor,SecUnsignedInt32 * pQuotientHigh,SecUnsignedInt32 * pQuotientLow,SecUnsignedInt32 * puiRemainder)319 int SecU64Div32(SecUnsignedInt32 dividendHigh, SecUnsignedInt32 dividendLow, SecUnsignedInt32 divisor,
320 SecUnsignedInt32 *pQuotientHigh, SecUnsignedInt32 *pQuotientLow, SecUnsignedInt32 *puiRemainder)
321 {
322 SecUnsignedInt32 tmpRemainderHi = 0;
323 SecUnsignedInt32 tmpRemainderLo = 0;
324 SecUnsignedInt32 tmpDividendHigh = dividendHigh;
325 SecUnsignedInt32 tmpDividendLow = dividendLow;
326 SecUnsignedInt32 tmpDivisor = divisor;
327 int ret = 0;
328
329 if ((pQuotientHigh == NULL) || (pQuotientLow == NULL) || tmpDivisor == 0 || puiRemainder == NULL) {
330 return -1;
331 }
332
333 tmpDividendHigh &= SECUREC_MASK_BIT_ALL;
334 tmpDividendLow &= SECUREC_MASK_BIT_ALL;
335 tmpDivisor &= SECUREC_MASK_BIT_ALL;
336 *pQuotientHigh = 0;
337 *pQuotientLow = 0;
338 *puiRemainder = 0;
339
340 ret = SecU64Div64(tmpDividendHigh,
341 tmpDividendLow, 0, tmpDivisor, pQuotientHigh, pQuotientLow, &tmpRemainderHi, &tmpRemainderLo);
342 if (ret != 0) {
343 return ret;
344 }
345
346 if (tmpRemainderHi != 0) {
347 return -1;
348 }
349 *puiRemainder = tmpRemainderLo;
350
351 return 0;
352 }
353 #endif
354
355