• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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