1 /*******************************************************************************
2  *
3  * Module Name: utstrsuppt - Support functions for string-to-integer conversion
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2019, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "acpi.h"
45 #include "accommon.h"
46 
47 #define _COMPONENT          ACPI_UTILITIES
48         ACPI_MODULE_NAME    ("utstrsuppt")
49 
50 
51 /* Local prototypes */
52 
53 static ACPI_STATUS
54 AcpiUtInsertDigit (
55     UINT64                  *AccumulatedValue,
56     UINT32                  Base,
57     int                     AsciiDigit);
58 
59 static ACPI_STATUS
60 AcpiUtStrtoulMultiply64 (
61     UINT64                  Multiplicand,
62     UINT32                  Base,
63     UINT64                  *OutProduct);
64 
65 static ACPI_STATUS
66 AcpiUtStrtoulAdd64 (
67     UINT64                  Addend1,
68     UINT32                  Digit,
69     UINT64                  *OutSum);
70 
71 
72 /*******************************************************************************
73  *
74  * FUNCTION:    AcpiUtConvertOctalString
75  *
76  * PARAMETERS:  String                  - Null terminated input string
77  *              ReturnValuePtr          - Where the converted value is returned
78  *
79  * RETURN:      Status and 64-bit converted integer
80  *
81  * DESCRIPTION: Performs a base 8 conversion of the input string to an
82  *              integer value, either 32 or 64 bits.
83  *
84  * NOTE:        Maximum 64-bit unsigned octal value is 01777777777777777777777
85  *              Maximum 32-bit unsigned octal value is 037777777777
86  *
87  ******************************************************************************/
88 
89 ACPI_STATUS
90 AcpiUtConvertOctalString (
91     char                    *String,
92     UINT64                  *ReturnValuePtr)
93 {
94     UINT64                  AccumulatedValue = 0;
95     ACPI_STATUS             Status = AE_OK;
96 
97 
98     /* Convert each ASCII byte in the input string */
99 
100     while (*String)
101     {
102         /* Character must be ASCII 0-7, otherwise terminate with no error */
103 
104         if (!(ACPI_IS_OCTAL_DIGIT (*String)))
105         {
106             break;
107         }
108 
109         /* Convert and insert this octal digit into the accumulator */
110 
111         Status = AcpiUtInsertDigit (&AccumulatedValue, 8, *String);
112         if (ACPI_FAILURE (Status))
113         {
114             Status = AE_OCTAL_OVERFLOW;
115             break;
116         }
117 
118         String++;
119     }
120 
121     /* Always return the value that has been accumulated */
122 
123     *ReturnValuePtr = AccumulatedValue;
124     return (Status);
125 }
126 
127 
128 /*******************************************************************************
129  *
130  * FUNCTION:    AcpiUtConvertDecimalString
131  *
132  * PARAMETERS:  String                  - Null terminated input string
133  *              ReturnValuePtr          - Where the converted value is returned
134  *
135  * RETURN:      Status and 64-bit converted integer
136  *
137  * DESCRIPTION: Performs a base 10 conversion of the input string to an
138  *              integer value, either 32 or 64 bits.
139  *
140  * NOTE:        Maximum 64-bit unsigned decimal value is 18446744073709551615
141  *              Maximum 32-bit unsigned decimal value is 4294967295
142  *
143  ******************************************************************************/
144 
145 ACPI_STATUS
146 AcpiUtConvertDecimalString (
147     char                    *String,
148     UINT64                  *ReturnValuePtr)
149 {
150     UINT64                  AccumulatedValue = 0;
151     ACPI_STATUS             Status = AE_OK;
152 
153 
154     /* Convert each ASCII byte in the input string */
155 
156     while (*String)
157     {
158         /* Character must be ASCII 0-9, otherwise terminate with no error */
159 
160         if (!isdigit (*String))
161         {
162            break;
163         }
164 
165         /* Convert and insert this decimal digit into the accumulator */
166 
167         Status = AcpiUtInsertDigit (&AccumulatedValue, 10, *String);
168         if (ACPI_FAILURE (Status))
169         {
170             Status = AE_DECIMAL_OVERFLOW;
171             break;
172         }
173 
174         String++;
175     }
176 
177     /* Always return the value that has been accumulated */
178 
179     *ReturnValuePtr = AccumulatedValue;
180     return (Status);
181 }
182 
183 
184 /*******************************************************************************
185  *
186  * FUNCTION:    AcpiUtConvertHexString
187  *
188  * PARAMETERS:  String                  - Null terminated input string
189  *              ReturnValuePtr          - Where the converted value is returned
190  *
191  * RETURN:      Status and 64-bit converted integer
192  *
193  * DESCRIPTION: Performs a base 16 conversion of the input string to an
194  *              integer value, either 32 or 64 bits.
195  *
196  * NOTE:        Maximum 64-bit unsigned hex value is 0xFFFFFFFFFFFFFFFF
197  *              Maximum 32-bit unsigned hex value is 0xFFFFFFFF
198  *
199  ******************************************************************************/
200 
201 ACPI_STATUS
202 AcpiUtConvertHexString (
203     char                    *String,
204     UINT64                  *ReturnValuePtr)
205 {
206     UINT64                  AccumulatedValue = 0;
207     ACPI_STATUS             Status = AE_OK;
208 
209 
210     /* Convert each ASCII byte in the input string */
211 
212     while (*String)
213     {
214         /* Must be ASCII A-F, a-f, or 0-9, otherwise terminate with no error */
215 
216         if (!isxdigit (*String))
217         {
218             break;
219         }
220 
221         /* Convert and insert this hex digit into the accumulator */
222 
223         Status = AcpiUtInsertDigit (&AccumulatedValue, 16, *String);
224         if (ACPI_FAILURE (Status))
225         {
226             Status = AE_HEX_OVERFLOW;
227             break;
228         }
229 
230         String++;
231     }
232 
233     /* Always return the value that has been accumulated */
234 
235     *ReturnValuePtr = AccumulatedValue;
236     return (Status);
237 }
238 
239 
240 /*******************************************************************************
241  *
242  * FUNCTION:    AcpiUtRemoveLeadingZeros
243  *
244  * PARAMETERS:  String                  - Pointer to input ASCII string
245  *
246  * RETURN:      Next character after any leading zeros. This character may be
247  *              used by the caller to detect end-of-string.
248  *
249  * DESCRIPTION: Remove any leading zeros in the input string. Return the
250  *              next character after the final ASCII zero to enable the caller
251  *              to check for the end of the string (NULL terminator).
252  *
253  ******************************************************************************/
254 
255 char
256 AcpiUtRemoveLeadingZeros (
257     char                    **String)
258 {
259 
260     while (**String == ACPI_ASCII_ZERO)
261     {
262         *String += 1;
263     }
264 
265     return (**String);
266 }
267 
268 
269 /*******************************************************************************
270  *
271  * FUNCTION:    AcpiUtRemoveWhitespace
272  *
273  * PARAMETERS:  String                  - Pointer to input ASCII string
274  *
275  * RETURN:      Next character after any whitespace. This character may be
276  *              used by the caller to detect end-of-string.
277  *
278  * DESCRIPTION: Remove any leading whitespace in the input string. Return the
279  *              next character after the final ASCII zero to enable the caller
280  *              to check for the end of the string (NULL terminator).
281  *
282  ******************************************************************************/
283 
284 char
285 AcpiUtRemoveWhitespace (
286     char                    **String)
287 {
288 
289     while (isspace ((UINT8) **String))
290     {
291         *String += 1;
292     }
293 
294     return (**String);
295 }
296 
297 
298 /*******************************************************************************
299  *
300  * FUNCTION:    AcpiUtDetectHexPrefix
301  *
302  * PARAMETERS:  String                  - Pointer to input ASCII string
303  *
304  * RETURN:      TRUE if a "0x" prefix was found at the start of the string
305  *
306  * DESCRIPTION: Detect and remove a hex "0x" prefix
307  *
308  ******************************************************************************/
309 
310 BOOLEAN
311 AcpiUtDetectHexPrefix (
312     char                    **String)
313 {
314     char                    *InitialPosition = *String;
315 
316     AcpiUtRemoveHexPrefix (String);
317     if (*String != InitialPosition)
318     {
319         return (TRUE); /* String is past leading 0x */
320     }
321 
322     return (FALSE);     /* Not a hex string */
323 }
324 
325 
326 /*******************************************************************************
327  *
328  * FUNCTION:    AcpiUtRemoveHexPrefix
329  *
330  * PARAMETERS:  String                  - Pointer to input ASCII string
331  *
332  * RETURN:      none
333  *
334  * DESCRIPTION: Remove a hex "0x" prefix
335  *
336  ******************************************************************************/
337 
338 void
339 AcpiUtRemoveHexPrefix (
340     char                    **String)
341 {
342     if ((**String == ACPI_ASCII_ZERO) &&
343         (tolower ((int) *(*String + 1)) == 'x'))
344     {
345         *String += 2;        /* Go past the leading 0x */
346     }
347 }
348 
349 
350 /*******************************************************************************
351  *
352  * FUNCTION:    AcpiUtDetectOctalPrefix
353  *
354  * PARAMETERS:  String                  - Pointer to input ASCII string
355  *
356  * RETURN:      True if an octal "0" prefix was found at the start of the
357  *              string
358  *
359  * DESCRIPTION: Detect and remove an octal prefix (zero)
360  *
361  ******************************************************************************/
362 
363 BOOLEAN
364 AcpiUtDetectOctalPrefix (
365     char                    **String)
366 {
367 
368     if (**String == ACPI_ASCII_ZERO)
369     {
370         *String += 1;       /* Go past the leading 0 */
371         return (TRUE);
372     }
373 
374     return (FALSE);     /* Not an octal string */
375 }
376 
377 
378 /*******************************************************************************
379  *
380  * FUNCTION:    AcpiUtInsertDigit
381  *
382  * PARAMETERS:  AccumulatedValue        - Current value of the integer value
383  *                                        accumulator. The new value is
384  *                                        returned here.
385  *              Base                    - Radix, either 8/10/16
386  *              AsciiDigit              - ASCII single digit to be inserted
387  *
388  * RETURN:      Status and result of the convert/insert operation. The only
389  *              possible returned exception code is numeric overflow of
390  *              either the multiply or add conversion operations.
391  *
392  * DESCRIPTION: Generic conversion and insertion function for all bases:
393  *
394  *              1) Multiply the current accumulated/converted value by the
395  *              base in order to make room for the new character.
396  *
397  *              2) Convert the new character to binary and add it to the
398  *              current accumulated value.
399  *
400  *              Note: The only possible exception indicates an integer
401  *              overflow (AE_NUMERIC_OVERFLOW)
402  *
403  ******************************************************************************/
404 
405 static ACPI_STATUS
406 AcpiUtInsertDigit (
407     UINT64                  *AccumulatedValue,
408     UINT32                  Base,
409     int                     AsciiDigit)
410 {
411     ACPI_STATUS             Status;
412     UINT64                  Product;
413 
414 
415      /* Make room in the accumulated value for the incoming digit */
416 
417     Status = AcpiUtStrtoulMultiply64 (*AccumulatedValue, Base, &Product);
418     if (ACPI_FAILURE (Status))
419     {
420         return (Status);
421     }
422 
423     /* Add in the new digit, and store the sum to the accumulated value */
424 
425     Status = AcpiUtStrtoulAdd64 (Product, AcpiUtAsciiCharToHex (AsciiDigit),
426         AccumulatedValue);
427 
428     return (Status);
429 }
430 
431 
432 /*******************************************************************************
433  *
434  * FUNCTION:    AcpiUtStrtoulMultiply64
435  *
436  * PARAMETERS:  Multiplicand            - Current accumulated converted integer
437  *              Base                    - Base/Radix
438  *              OutProduct              - Where the product is returned
439  *
440  * RETURN:      Status and 64-bit product
441  *
442  * DESCRIPTION: Multiply two 64-bit values, with checking for 64-bit overflow as
443  *              well as 32-bit overflow if necessary (if the current global
444  *              integer width is 32).
445  *
446  ******************************************************************************/
447 
448 static ACPI_STATUS
449 AcpiUtStrtoulMultiply64 (
450     UINT64                  Multiplicand,
451     UINT32                  Base,
452     UINT64                  *OutProduct)
453 {
454     UINT64                  Product;
455     UINT64                  Quotient;
456 
457 
458     /* Exit if either operand is zero */
459 
460     *OutProduct = 0;
461     if (!Multiplicand || !Base)
462     {
463         return (AE_OK);
464     }
465 
466     /*
467      * Check for 64-bit overflow before the actual multiplication.
468      *
469      * Notes: 64-bit division is often not supported on 32-bit platforms
470      * (it requires a library function), Therefore ACPICA has a local
471      * 64-bit divide function. Also, Multiplier is currently only used
472      * as the radix (8/10/16), to the 64/32 divide will always work.
473      */
474     AcpiUtShortDivide (ACPI_UINT64_MAX, Base, &Quotient, NULL);
475     if (Multiplicand > Quotient)
476     {
477         return (AE_NUMERIC_OVERFLOW);
478     }
479 
480     Product = Multiplicand * Base;
481 
482     /* Check for 32-bit overflow if necessary */
483 
484     if ((AcpiGbl_IntegerBitWidth == 32) && (Product > ACPI_UINT32_MAX))
485     {
486         return (AE_NUMERIC_OVERFLOW);
487     }
488 
489     *OutProduct = Product;
490     return (AE_OK);
491 }
492 
493 
494 /*******************************************************************************
495  *
496  * FUNCTION:    AcpiUtStrtoulAdd64
497  *
498  * PARAMETERS:  Addend1                 - Current accumulated converted integer
499  *              Digit                   - New hex value/char
500  *              OutSum                  - Where sum is returned (Accumulator)
501  *
502  * RETURN:      Status and 64-bit sum
503  *
504  * DESCRIPTION: Add two 64-bit values, with checking for 64-bit overflow as
505  *              well as 32-bit overflow if necessary (if the current global
506  *              integer width is 32).
507  *
508  ******************************************************************************/
509 
510 static ACPI_STATUS
511 AcpiUtStrtoulAdd64 (
512     UINT64                  Addend1,
513     UINT32                  Digit,
514     UINT64                  *OutSum)
515 {
516     UINT64                  Sum;
517 
518 
519     /* Check for 64-bit overflow before the actual addition */
520 
521     if ((Addend1 > 0) && (Digit > (ACPI_UINT64_MAX - Addend1)))
522     {
523         return (AE_NUMERIC_OVERFLOW);
524     }
525 
526     Sum = Addend1 + Digit;
527 
528     /* Check for 32-bit overflow if necessary */
529 
530     if ((AcpiGbl_IntegerBitWidth == 32) && (Sum > ACPI_UINT32_MAX))
531     {
532         return (AE_NUMERIC_OVERFLOW);
533     }
534 
535     *OutSum = Sum;
536     return (AE_OK);
537 }
538