* [PATCH 0/4] Add and refine sting APIs in MdePkg/BaseLib @ 2017-01-04 11:22 Hao Wu 2017-01-04 11:22 ` [PATCH 1/4] MdePkg/BaseLib: Add safe string functions [Ascii]StrnSizeS Hao Wu ` (3 more replies) 0 siblings, 4 replies; 9+ messages in thread From: Hao Wu @ 2017-01-04 11:22 UTC (permalink / raw) To: edk2-devel; +Cc: Hao Wu, Jiewen Yao, Liming Gao, Michael Kinney The series does the following things: 1). Add safe string functions [Ascii]StrnSizeS 2). Add safe string functions [Ascii]StrDecimalToUintnS, [Ascii]StrDecimalToUint64S, [Ascii]StrHexToUintnS and [Ascii]StrHexToUint64S 3). Refine the return value of string funcitons [Ascii]StrDecimalToUintn [Ascii]StrDecimalToUint64, [Ascii]StrHexToUintn and [Ascii]StrHexToUint64 4). Add safe string functions UnicodeStrnToAsciiStrS and AsciiStrnToUnicodeStrS Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Liming Gao <liming.gao@intel.com> Cc: Michael Kinney <michael.d.kinney@intel.com> Hao Wu (4): MdePkg/BaseLib: Add safe string functions [Ascii]StrnSizeS MdePkg/BaseLib: Add safe string functions that convert str to value MdePkg/BaseLib: Enhance the return value for string to uint functions MdePkg/BaseLib: Add safe string functions [U|A]StrnTo[A|U]StrS MdePkg/Include/Library/BaseLib.h | 641 ++++++++++++- MdePkg/Library/BaseLib/BaseLibInternals.h | 166 +++- MdePkg/Library/BaseLib/SafeString.c | 1387 ++++++++++++++++++++++++++++- MdePkg/Library/BaseLib/String.c | 334 +------ 4 files changed, 2154 insertions(+), 374 deletions(-) -- 1.9.5.msysgit.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/4] MdePkg/BaseLib: Add safe string functions [Ascii]StrnSizeS 2017-01-04 11:22 [PATCH 0/4] Add and refine sting APIs in MdePkg/BaseLib Hao Wu @ 2017-01-04 11:22 ` Hao Wu 2017-01-05 2:02 ` Yao, Jiewen 2017-01-04 11:22 ` [PATCH 2/4] MdePkg/BaseLib: Add safe string functions that convert str to value Hao Wu ` (2 subsequent siblings) 3 siblings, 1 reply; 9+ messages in thread From: Hao Wu @ 2017-01-04 11:22 UTC (permalink / raw) To: edk2-devel; +Cc: Hao Wu, Jiewen Yao, Liming Gao, Michael Kinney Add StrnSizeS() and AsciiStrnSizeS() APIs. These 2 safe version APIs are used to replace StrSize() and AsciiStrSize(). Those two APIs use similar checks as [Ascii]StrnLenS(). Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Liming Gao <liming.gao@intel.com> Cc: Michael Kinney <michael.d.kinney@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Hao Wu <hao.a.wu@intel.com> --- MdePkg/Include/Library/BaseLib.h | 56 ++++++++++++++++++++++- MdePkg/Library/BaseLib/SafeString.c | 91 ++++++++++++++++++++++++++++++++++++- 2 files changed, 145 insertions(+), 2 deletions(-) diff --git a/MdePkg/Include/Library/BaseLib.h b/MdePkg/Include/Library/BaseLib.h index b69c703..72d1f0b 100644 --- a/MdePkg/Include/Library/BaseLib.h +++ b/MdePkg/Include/Library/BaseLib.h @@ -2,7 +2,7 @@ Provides string functions, linked list functions, math functions, synchronization functions, file path functions, and CPU architecture-specific functions. -Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR> +Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR> Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR> This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -208,6 +208,34 @@ StrnLenS ( ); /** + Returns the size of a Null-terminated Unicode string in bytes, including the + Null terminator. + + This function returns the size of the Null-terminated Unicode string + specified by String in bytes, including the Null terminator. + + If String is not aligned on a 16-bit boundary, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + @param MaxSize The maximum number of Destination Unicode + char, including the Null terminator. + + @retval 0 If String is NULL. + @retval (sizeof (CHAR16) * (MaxSize + 1)) + If there is no Null terminator in the first MaxSize characters of + String. + @return The size of the Null-terminated Unicode string in bytes, including + the Null terminator. + +**/ +UINTN +EFIAPI +StrnSizeS ( + IN CONST CHAR16 *String, + IN UINTN MaxSize + ); + +/** Copies the string pointed to by Source (including the terminating null char) to the array pointed to by Destination. @@ -383,6 +411,32 @@ AsciiStrnLenS ( ); /** + Returns the size of a Null-terminated Ascii string in bytes, including the + Null terminator. + + This function returns the size of the Null-terminated Ascii string specified + by String in bytes, including the Null terminator. + + @param String A pointer to a Null-terminated Ascii string. + @param MaxSize The maximum number of Destination Ascii + char, including the Null terminator. + + @retval 0 If String is NULL. + @retval (sizeof (CHAR8) * (MaxSize + 1)) + If there is no Null terminator in the first MaxSize characters of + String. + @return The size of the Null-terminated Ascii string in bytes, including the + Null terminator. + +**/ +UINTN +EFIAPI +AsciiStrnSizeS ( + IN CONST CHAR8 *String, + IN UINTN MaxSize + ); + +/** Copies the string pointed to by Source (including the terminating null char) to the array pointed to by Destination. diff --git a/MdePkg/Library/BaseLib/SafeString.c b/MdePkg/Library/BaseLib/SafeString.c index e4c0759..f80db9f 100644 --- a/MdePkg/Library/BaseLib/SafeString.c +++ b/MdePkg/Library/BaseLib/SafeString.c @@ -1,7 +1,7 @@ /** @file Safe String functions. - Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR> + Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR> This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -154,6 +154,51 @@ StrnLenS ( } /** + Returns the size of a Null-terminated Unicode string in bytes, including the + Null terminator. + + This function returns the size of the Null-terminated Unicode string + specified by String in bytes, including the Null terminator. + + If String is not aligned on a 16-bit boundary, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + @param MaxSize The maximum number of Destination Unicode + char, including the Null terminator. + + @retval 0 If String is NULL. + @retval (sizeof (CHAR16) * (MaxSize + 1)) + If there is no Null terminator in the first MaxSize characters of + String. + @return The size of the Null-terminated Unicode string in bytes, including + the Null terminator. + +**/ +UINTN +EFIAPI +StrnSizeS ( + IN CONST CHAR16 *String, + IN UINTN MaxSize + ) +{ + // + // If String is a null pointer, then the StrnSizeS function returns zero. + // + if (String == NULL) { + return 0; + } + + // + // Otherwise, the StrnSizeS function returns the size of the Null-terminated + // Unicode string in bytes, including the Null terminator. If there is no + // Null terminator in the first MaxSize characters of String, then StrnSizeS + // returns (sizeof (CHAR16) * (MaxSize + 1)) to keep a consistent map with + // the StrnLenS function. + // + return (StrnLenS (String, MaxSize) + 1) * sizeof (*String); +} + +/** Copies the string pointed to by Source (including the terminating null char) to the array pointed to by Destination. @@ -586,6 +631,50 @@ AsciiStrnLenS ( } /** + Returns the size of a Null-terminated Ascii string in bytes, including the + Null terminator. + + This function returns the size of the Null-terminated Ascii string specified + by String in bytes, including the Null terminator. + + @param String A pointer to a Null-terminated Ascii string. + @param MaxSize The maximum number of Destination Ascii + char, including the Null terminator. + + @retval 0 If String is NULL. + @retval (sizeof (CHAR8) * (MaxSize + 1)) + If there is no Null terminator in the first MaxSize characters of + String. + @return The size of the Null-terminated Ascii string in bytes, including the + Null terminator. + +**/ +UINTN +EFIAPI +AsciiStrnSizeS ( + IN CONST CHAR8 *String, + IN UINTN MaxSize + ) +{ + // + // If String is a null pointer, then the AsciiStrnSizeS function returns + // zero. + // + if (String == NULL) { + return 0; + } + + // + // Otherwise, the AsciiStrnSizeS function returns the size of the + // Null-terminated Ascii string in bytes, including the Null terminator. If + // there is no Null terminator in the first MaxSize characters of String, + // then AsciiStrnSizeS returns (sizeof (CHAR8) * (MaxSize + 1)) to keep a + // consistent map with the AsciiStrnLenS function. + // + return (AsciiStrnLenS (String, MaxSize) + 1) * sizeof (*String); +} + +/** Copies the string pointed to by Source (including the terminating null char) to the array pointed to by Destination. -- 1.9.5.msysgit.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 1/4] MdePkg/BaseLib: Add safe string functions [Ascii]StrnSizeS 2017-01-04 11:22 ` [PATCH 1/4] MdePkg/BaseLib: Add safe string functions [Ascii]StrnSizeS Hao Wu @ 2017-01-05 2:02 ` Yao, Jiewen 0 siblings, 0 replies; 9+ messages in thread From: Yao, Jiewen @ 2017-01-05 2:02 UTC (permalink / raw) To: Wu, Hao A, edk2-devel@lists.01.org; +Cc: Gao, Liming, Kinney, Michael D Reviewed-by: jiewen.yao@intel.com > -----Original Message----- > From: Wu, Hao A > Sent: Wednesday, January 4, 2017 7:23 PM > To: edk2-devel@lists.01.org > Cc: Wu, Hao A <hao.a.wu@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; > Gao, Liming <liming.gao@intel.com>; Kinney, Michael D > <michael.d.kinney@intel.com> > Subject: [PATCH 1/4] MdePkg/BaseLib: Add safe string functions [Ascii]StrnSizeS > > Add StrnSizeS() and AsciiStrnSizeS() APIs. > > These 2 safe version APIs are used to replace StrSize() and > AsciiStrSize(). Those two APIs use similar checks as [Ascii]StrnLenS(). > > Cc: Jiewen Yao <jiewen.yao@intel.com> > Cc: Liming Gao <liming.gao@intel.com> > Cc: Michael Kinney <michael.d.kinney@intel.com> > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Hao Wu <hao.a.wu@intel.com> > --- > MdePkg/Include/Library/BaseLib.h | 56 ++++++++++++++++++++++- > MdePkg/Library/BaseLib/SafeString.c | 91 > ++++++++++++++++++++++++++++++++++++- > 2 files changed, 145 insertions(+), 2 deletions(-) > > diff --git a/MdePkg/Include/Library/BaseLib.h > b/MdePkg/Include/Library/BaseLib.h > index b69c703..72d1f0b 100644 > --- a/MdePkg/Include/Library/BaseLib.h > +++ b/MdePkg/Include/Library/BaseLib.h > @@ -2,7 +2,7 @@ > Provides string functions, linked list functions, math functions, > synchronization > functions, file path functions, and CPU architecture-specific functions. > > -Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR> > +Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR> > Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR> > This program and the accompanying materials > are licensed and made available under the terms and conditions of the BSD > License > @@ -208,6 +208,34 @@ StrnLenS ( > ); > > /** > + Returns the size of a Null-terminated Unicode string in bytes, including the > + Null terminator. > + > + This function returns the size of the Null-terminated Unicode string > + specified by String in bytes, including the Null terminator. > + > + If String is not aligned on a 16-bit boundary, then ASSERT(). > + > + @param String A pointer to a Null-terminated Unicode string. > + @param MaxSize The maximum number of Destination Unicode > + char, including the Null terminator. > + > + @retval 0 If String is NULL. > + @retval (sizeof (CHAR16) * (MaxSize + 1)) > + If there is no Null terminator in the first MaxSize characters of > + String. > + @return The size of the Null-terminated Unicode string in bytes, including > + the Null terminator. > + > +**/ > +UINTN > +EFIAPI > +StrnSizeS ( > + IN CONST CHAR16 *String, > + IN UINTN MaxSize > + ); > + > +/** > Copies the string pointed to by Source (including the terminating null char) > to the array pointed to by Destination. > > @@ -383,6 +411,32 @@ AsciiStrnLenS ( > ); > > /** > + Returns the size of a Null-terminated Ascii string in bytes, including the > + Null terminator. > + > + This function returns the size of the Null-terminated Ascii string specified > + by String in bytes, including the Null terminator. > + > + @param String A pointer to a Null-terminated Ascii string. > + @param MaxSize The maximum number of Destination Ascii > + char, including the Null terminator. > + > + @retval 0 If String is NULL. > + @retval (sizeof (CHAR8) * (MaxSize + 1)) > + If there is no Null terminator in the first MaxSize characters of > + String. > + @return The size of the Null-terminated Ascii string in bytes, including the > + Null terminator. > + > +**/ > +UINTN > +EFIAPI > +AsciiStrnSizeS ( > + IN CONST CHAR8 *String, > + IN UINTN MaxSize > + ); > + > +/** > Copies the string pointed to by Source (including the terminating null char) > to the array pointed to by Destination. > > diff --git a/MdePkg/Library/BaseLib/SafeString.c > b/MdePkg/Library/BaseLib/SafeString.c > index e4c0759..f80db9f 100644 > --- a/MdePkg/Library/BaseLib/SafeString.c > +++ b/MdePkg/Library/BaseLib/SafeString.c > @@ -1,7 +1,7 @@ > /** @file > Safe String functions. > > - Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR> > + Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR> > This program and the accompanying materials > are licensed and made available under the terms and conditions of the BSD > License > which accompanies this distribution. The full text of the license may be > found at > @@ -154,6 +154,51 @@ StrnLenS ( > } > > /** > + Returns the size of a Null-terminated Unicode string in bytes, including the > + Null terminator. > + > + This function returns the size of the Null-terminated Unicode string > + specified by String in bytes, including the Null terminator. > + > + If String is not aligned on a 16-bit boundary, then ASSERT(). > + > + @param String A pointer to a Null-terminated Unicode string. > + @param MaxSize The maximum number of Destination Unicode > + char, including the Null terminator. > + > + @retval 0 If String is NULL. > + @retval (sizeof (CHAR16) * (MaxSize + 1)) > + If there is no Null terminator in the first MaxSize characters of > + String. > + @return The size of the Null-terminated Unicode string in bytes, including > + the Null terminator. > + > +**/ > +UINTN > +EFIAPI > +StrnSizeS ( > + IN CONST CHAR16 *String, > + IN UINTN MaxSize > + ) > +{ > + // > + // If String is a null pointer, then the StrnSizeS function returns zero. > + // > + if (String == NULL) { > + return 0; > + } > + > + // > + // Otherwise, the StrnSizeS function returns the size of the Null-terminated > + // Unicode string in bytes, including the Null terminator. If there is no > + // Null terminator in the first MaxSize characters of String, then StrnSizeS > + // returns (sizeof (CHAR16) * (MaxSize + 1)) to keep a consistent map with > + // the StrnLenS function. > + // > + return (StrnLenS (String, MaxSize) + 1) * sizeof (*String); > +} > + > +/** > Copies the string pointed to by Source (including the terminating null char) > to the array pointed to by Destination. > > @@ -586,6 +631,50 @@ AsciiStrnLenS ( > } > > /** > + Returns the size of a Null-terminated Ascii string in bytes, including the > + Null terminator. > + > + This function returns the size of the Null-terminated Ascii string specified > + by String in bytes, including the Null terminator. > + > + @param String A pointer to a Null-terminated Ascii string. > + @param MaxSize The maximum number of Destination Ascii > + char, including the Null terminator. > + > + @retval 0 If String is NULL. > + @retval (sizeof (CHAR8) * (MaxSize + 1)) > + If there is no Null terminator in the first MaxSize characters of > + String. > + @return The size of the Null-terminated Ascii string in bytes, including the > + Null terminator. > + > +**/ > +UINTN > +EFIAPI > +AsciiStrnSizeS ( > + IN CONST CHAR8 *String, > + IN UINTN MaxSize > + ) > +{ > + // > + // If String is a null pointer, then the AsciiStrnSizeS function returns > + // zero. > + // > + if (String == NULL) { > + return 0; > + } > + > + // > + // Otherwise, the AsciiStrnSizeS function returns the size of the > + // Null-terminated Ascii string in bytes, including the Null terminator. If > + // there is no Null terminator in the first MaxSize characters of String, > + // then AsciiStrnSizeS returns (sizeof (CHAR8) * (MaxSize + 1)) to keep a > + // consistent map with the AsciiStrnLenS function. > + // > + return (AsciiStrnLenS (String, MaxSize) + 1) * sizeof (*String); > +} > + > +/** > Copies the string pointed to by Source (including the terminating null char) > to the array pointed to by Destination. > > -- > 1.9.5.msysgit.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/4] MdePkg/BaseLib: Add safe string functions that convert str to value 2017-01-04 11:22 [PATCH 0/4] Add and refine sting APIs in MdePkg/BaseLib Hao Wu 2017-01-04 11:22 ` [PATCH 1/4] MdePkg/BaseLib: Add safe string functions [Ascii]StrnSizeS Hao Wu @ 2017-01-04 11:22 ` Hao Wu 2017-01-09 2:02 ` Yao, Jiewen 2017-01-04 11:22 ` [PATCH 3/4] MdePkg/BaseLib: Enhance the return value for string to uint functions Hao Wu 2017-01-04 11:22 ` [PATCH 4/4] MdePkg/BaseLib: Add safe string functions [U|A]StrnTo[A|U]StrS Hao Wu 3 siblings, 1 reply; 9+ messages in thread From: Hao Wu @ 2017-01-04 11:22 UTC (permalink / raw) To: edk2-devel; +Cc: Hao Wu, Jiewen Yao, Liming Gao, Michael Kinney Add the following 8 APIs: [Ascii]StrDecimalToUintnS [Ascii]StrDecimalToUint64S [Ascii]StrHexToUintnS [Ascii]StrHexToUint64S These safe version APIs are used to enhance their counterpart (APIs without trailing 'S' in function names). These safe version APIs perform checks to the input string and will return relative status to reflect the check result: When the input string exceeds the range of UINTN/64, these APIs will return RETURN_UNSUPPORTED and store MAX_UINTN/64 in the output data. When no conversion can be performed for the input string, these APIs will return RETURN_SUCCESS and store 0 in the output data. The optional parameter 'EndPointer', if provided, will point to the character that stopped the scan. Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Liming Gao <liming.gao@intel.com> Cc: Michael Kinney <michael.d.kinney@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Hao Wu <hao.a.wu@intel.com> --- MdePkg/Include/Library/BaseLib.h | 462 ++++++++++++++ MdePkg/Library/BaseLib/BaseLibInternals.h | 166 ++++- MdePkg/Library/BaseLib/SafeString.c | 975 +++++++++++++++++++++++++++++- 3 files changed, 1598 insertions(+), 5 deletions(-) diff --git a/MdePkg/Include/Library/BaseLib.h b/MdePkg/Include/Library/BaseLib.h index 72d1f0b..52011ee 100644 --- a/MdePkg/Include/Library/BaseLib.h +++ b/MdePkg/Include/Library/BaseLib.h @@ -390,6 +390,240 @@ StrnCatS ( ); /** + Convert a Null-terminated Unicode decimal string to a value of type UINTN. + + This function outputs a value of type UINTN by interpreting the contents of + the Unicode string specified by String as a decimal number. The format of the + input Unicode string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before + [decimal digits]. The running zero in the beginning of [decimal digits] will + be ignored. Then, the function stops at the first character that is a not a + valid decimal character or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid decimal digits in the above format, then 0 is stored + at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINTN, then + MAX_UINTN is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + decimal digits right after the optional pad spaces, the value of String is + stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINTN. + +**/ +RETURN_STATUS +EFIAPI +StrDecimalToUintnS ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT UINTN *Data + ); + +/** + Convert a Null-terminated Unicode decimal string to a value of type UINT64. + + This function outputs a value of type UINT64 by interpreting the contents of + the Unicode string specified by String as a decimal number. The format of the + input Unicode string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before + [decimal digits]. The running zero in the beginning of [decimal digits] will + be ignored. Then, the function stops at the first character that is a not a + valid decimal character or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid decimal digits in the above format, then 0 is stored + at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINT64, then + MAX_UINT64 is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + decimal digits right after the optional pad spaces, the value of String is + stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINT64. + +**/ +RETURN_STATUS +EFIAPI +StrDecimalToUint64S ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT UINT64 *Data + ); + +/** + Convert a Null-terminated Unicode hexadecimal string to a value of type + UINTN. + + This function outputs a value of type UINTN by interpreting the contents of + the Unicode string specified by String as a hexadecimal number. The format of + the input Unicode string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. + If "x" appears in the input string, it must be prefixed with at least one 0. + The function will ignore the pad space, which includes spaces or tab + characters, before [zeros], [x] or [hexadecimal digit]. The running zero + before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts + after [x] or the first valid hexadecimal digit. Then, the function stops at + the first character that is a not a valid hexadecimal character or NULL, + whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid hexadecimal digits in the above format, then 0 is + stored at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINTN, then + MAX_UINTN is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + hexadecimal digits right after the optional pad spaces, the value of String + is stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINTN. + +**/ +RETURN_STATUS +EFIAPI +StrHexToUintnS ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT UINTN *Data + ); + +/** + Convert a Null-terminated Unicode hexadecimal string to a value of type + UINT64. + + This function outputs a value of type UINT64 by interpreting the contents of + the Unicode string specified by String as a hexadecimal number. The format of + the input Unicode string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. + If "x" appears in the input string, it must be prefixed with at least one 0. + The function will ignore the pad space, which includes spaces or tab + characters, before [zeros], [x] or [hexadecimal digit]. The running zero + before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts + after [x] or the first valid hexadecimal digit. Then, the function stops at + the first character that is a not a valid hexadecimal character or NULL, + whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid hexadecimal digits in the above format, then 0 is + stored at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINT64, then + MAX_UINT64 is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + hexadecimal digits right after the optional pad spaces, the value of String + is stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINT64. + +**/ +RETURN_STATUS +EFIAPI +StrHexToUint64S ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT UINT64 *Data + ); + +/** Returns the length of a Null-terminated Ascii string. This function is similar as strlen_s defined in C11. @@ -582,6 +816,234 @@ AsciiStrnCatS ( IN UINTN Length ); +/** + Convert a Null-terminated Ascii decimal string to a value of type UINTN. + + This function outputs a value of type UINTN by interpreting the contents of + the Ascii string specified by String as a decimal number. The format of the + input Ascii string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before + [decimal digits]. The running zero in the beginning of [decimal digits] will + be ignored. Then, the function stops at the first character that is a not a + valid decimal character or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid decimal digits in the above format, then 0 is stored + at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINTN, then + MAX_UINTN is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + decimal digits right after the optional pad spaces, the value of String is + stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Ascii string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumAsciiStringLength is not zero, + and String contains more than + PcdMaximumAsciiStringLength Ascii + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINTN. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrDecimalToUintnS ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT UINTN *Data + ); + +/** + Convert a Null-terminated Ascii decimal string to a value of type UINT64. + + This function outputs a value of type UINT64 by interpreting the contents of + the Ascii string specified by String as a decimal number. The format of the + input Ascii string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before + [decimal digits]. The running zero in the beginning of [decimal digits] will + be ignored. Then, the function stops at the first character that is a not a + valid decimal character or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid decimal digits in the above format, then 0 is stored + at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINT64, then + MAX_UINT64 is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + decimal digits right after the optional pad spaces, the value of String is + stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Ascii string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumAsciiStringLength is not zero, + and String contains more than + PcdMaximumAsciiStringLength Ascii + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINT64. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrDecimalToUint64S ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT UINT64 *Data + ); + +/** + Convert a Null-terminated Ascii hexadecimal string to a value of type UINTN. + + This function outputs a value of type UINTN by interpreting the contents of + the Ascii string specified by String as a hexadecimal number. The format of + the input Ascii string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If + "x" appears in the input string, it must be prefixed with at least one 0. The + function will ignore the pad space, which includes spaces or tab characters, + before [zeros], [x] or [hexadecimal digits]. The running zero before [x] or + [hexadecimal digits] will be ignored. Then, the decoding starts after [x] or + the first valid hexadecimal digit. Then, the function stops at the first + character that is a not a valid hexadecimal character or Null-terminator, + whichever on comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid hexadecimal digits in the above format, then 0 is + stored at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINTN, then + MAX_UINTN is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + hexadecimal digits right after the optional pad spaces, the value of String + is stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Ascii string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumAsciiStringLength is not zero, + and String contains more than + PcdMaximumAsciiStringLength Ascii + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINTN. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrHexToUintnS ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT UINTN *Data + ); + +/** + Convert a Null-terminated Ascii hexadecimal string to a value of type UINT64. + + This function outputs a value of type UINT64 by interpreting the contents of + the Ascii string specified by String as a hexadecimal number. The format of + the input Ascii string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If + "x" appears in the input string, it must be prefixed with at least one 0. The + function will ignore the pad space, which includes spaces or tab characters, + before [zeros], [x] or [hexadecimal digits]. The running zero before [x] or + [hexadecimal digits] will be ignored. Then, the decoding starts after [x] or + the first valid hexadecimal digit. Then, the function stops at the first + character that is a not a valid hexadecimal character or Null-terminator, + whichever on comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid hexadecimal digits in the above format, then 0 is + stored at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINT64, then + MAX_UINT64 is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + hexadecimal digits right after the optional pad spaces, the value of String + is stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Ascii string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumAsciiStringLength is not zero, + and String contains more than + PcdMaximumAsciiStringLength Ascii + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINT64. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrHexToUint64S ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT UINT64 *Data + ); + #ifndef DISABLE_NEW_DEPRECATED_INTERFACES diff --git a/MdePkg/Library/BaseLib/BaseLibInternals.h b/MdePkg/Library/BaseLib/BaseLibInternals.h index a8f712b..ea387ce 100644 --- a/MdePkg/Library/BaseLib/BaseLibInternals.h +++ b/MdePkg/Library/BaseLib/BaseLibInternals.h @@ -1,7 +1,7 @@ /** @file Declaration of internal functions in BaseLib. - Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR> + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR> This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -477,6 +477,170 @@ InternalLongJump ( ); +/** + Check if a Unicode character is a decimal character. + + This internal function checks if a Unicode character is a + decimal character. The valid decimal character is from + L'0' to L'9'. + + @param Char The character to check against. + + @retval TRUE If the Char is a decmial character. + @retval FALSE If the Char is not a decmial character. + +**/ +BOOLEAN +EFIAPI +InternalIsDecimalDigitCharacter ( + IN CHAR16 Char + ); + + +/** + Convert a Unicode character to upper case only if + it maps to a valid small-case ASCII character. + + This internal function only deal with Unicode character + which maps to a valid small-case ASCII character, i.e. + L'a' to L'z'. For other Unicode character, the input character + is returned directly. + + @param Char The character to convert. + + @retval LowerCharacter If the Char is with range L'a' to L'z'. + @retval Unchanged Otherwise. + +**/ +CHAR16 +EFIAPI +InternalCharToUpper ( + IN CHAR16 Char + ); + + +/** + Convert a Unicode character to numerical value. + + This internal function only deal with Unicode character + which maps to a valid hexadecimal ASII character, i.e. + L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other + Unicode character, the value returned does not make sense. + + @param Char The character to convert. + + @return The numerical value converted. + +**/ +UINTN +EFIAPI +InternalHexCharToUintn ( + IN CHAR16 Char + ); + + +/** + Check if a Unicode character is a hexadecimal character. + + This internal function checks if a Unicode character is a + decimal character. The valid hexadecimal character is + L'0' to L'9', L'a' to L'f', or L'A' to L'F'. + + + @param Char The character to check against. + + @retval TRUE If the Char is a hexadecmial character. + @retval FALSE If the Char is not a hexadecmial character. + +**/ +BOOLEAN +EFIAPI +InternalIsHexaDecimalDigitCharacter ( + IN CHAR16 Char + ); + + +/** + Check if a ASCII character is a decimal character. + + This internal function checks if a Unicode character is a + decimal character. The valid decimal character is from + '0' to '9'. + + @param Char The character to check against. + + @retval TRUE If the Char is a decmial character. + @retval FALSE If the Char is not a decmial character. + +**/ +BOOLEAN +EFIAPI +InternalAsciiIsDecimalDigitCharacter ( + IN CHAR8 Char + ); + + +/** + Converts a lowercase Ascii character to upper one. + + If Chr is lowercase Ascii character, then converts it to upper one. + + If Value >= 0xA0, then ASSERT(). + If (Value & 0x0F) >= 0x0A, then ASSERT(). + + @param Chr one Ascii character + + @return The uppercase value of Ascii character + +**/ +CHAR8 +EFIAPI +InternalBaseLibAsciiToUpper ( + IN CHAR8 Chr + ); + + +/** + Check if a ASCII character is a hexadecimal character. + + This internal function checks if a ASCII character is a + decimal character. The valid hexadecimal character is + L'0' to L'9', L'a' to L'f', or L'A' to L'F'. + + + @param Char The character to check against. + + @retval TRUE If the Char is a hexadecmial character. + @retval FALSE If the Char is not a hexadecmial character. + +**/ +BOOLEAN +EFIAPI +InternalAsciiIsHexaDecimalDigitCharacter ( + IN CHAR8 Char + ); + + +/** + Convert a ASCII character to numerical value. + + This internal function only deal with Unicode character + which maps to a valid hexadecimal ASII character, i.e. + '0' to '9', 'a' to 'f' or 'A' to 'F'. For other + ASCII character, the value returned does not make sense. + + @param Char The character to convert. + + @return The numerical value converted. + +**/ +UINTN +EFIAPI +InternalAsciiHexCharToUintn ( + IN CHAR8 Char + ); + + // // Ia32 and x64 specific functions // diff --git a/MdePkg/Library/BaseLib/SafeString.c b/MdePkg/Library/BaseLib/SafeString.c index f80db9f..5edc6ef 100644 --- a/MdePkg/Library/BaseLib/SafeString.c +++ b/MdePkg/Library/BaseLib/SafeString.c @@ -12,10 +12,7 @@ **/ -#include <Base.h> -#include <Library/DebugLib.h> -#include <Library/PcdLib.h> -#include <Library/BaseLib.h> +#include "BaseLibInternals.h" #define RSIZE_MAX (PcdGet32 (PcdMaximumUnicodeStringLength)) @@ -585,6 +582,498 @@ StrnCatS ( } /** + Convert a Null-terminated Unicode decimal string to a value of type UINTN. + + This function outputs a value of type UINTN by interpreting the contents of + the Unicode string specified by String as a decimal number. The format of the + input Unicode string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before + [decimal digits]. The running zero in the beginning of [decimal digits] will + be ignored. Then, the function stops at the first character that is a not a + valid decimal character or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid decimal digits in the above format, then 0 is stored + at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINTN, then + MAX_UINTN is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + decimal digits right after the optional pad spaces, the value of String is + stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINTN. + +**/ +RETURN_STATUS +EFIAPI +StrDecimalToUintnS ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT UINTN *Data + ) +{ + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == L' ') || (*String == L'\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == L'0') { + String++; + } + + *Data = 0; + + while (InternalIsDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINTN, then MAX_UINTN is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > ((MAX_UINTN - (*String - L'0')) / 10)) { + *Data = MAX_UINTN; + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = *Data * 10 + (*String - L'0'); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode decimal string to a value of type UINT64. + + This function outputs a value of type UINT64 by interpreting the contents of + the Unicode string specified by String as a decimal number. The format of the + input Unicode string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before + [decimal digits]. The running zero in the beginning of [decimal digits] will + be ignored. Then, the function stops at the first character that is a not a + valid decimal character or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid decimal digits in the above format, then 0 is stored + at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINT64, then + MAX_UINT64 is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + decimal digits right after the optional pad spaces, the value of String is + stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINT64. + +**/ +RETURN_STATUS +EFIAPI +StrDecimalToUint64S ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT UINT64 *Data + ) +{ + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == L' ') || (*String == L'\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == L'0') { + String++; + } + + *Data = 0; + + while (InternalIsDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINT64, then MAX_UINT64 is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > DivU64x32 (MAX_UINT64 - (*String - L'0'), 10)) { + *Data = MAX_UINT64; + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = MultU64x32 (*Data, 10) + (*String - L'0'); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode hexadecimal string to a value of type + UINTN. + + This function outputs a value of type UINTN by interpreting the contents of + the Unicode string specified by String as a hexadecimal number. The format of + the input Unicode string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. + If "x" appears in the input string, it must be prefixed with at least one 0. + The function will ignore the pad space, which includes spaces or tab + characters, before [zeros], [x] or [hexadecimal digit]. The running zero + before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts + after [x] or the first valid hexadecimal digit. Then, the function stops at + the first character that is a not a valid hexadecimal character or NULL, + whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid hexadecimal digits in the above format, then 0 is + stored at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINTN, then + MAX_UINTN is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + hexadecimal digits right after the optional pad spaces, the value of String + is stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINTN. + +**/ +RETURN_STATUS +EFIAPI +StrHexToUintnS ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT UINTN *Data + ) +{ + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == L' ') || (*String == L'\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == L'0') { + String++; + } + + if (InternalCharToUpper (*String) == L'X') { + if (*(String - 1) != L'0') { + *Data = 0; + return RETURN_SUCCESS; + } + // + // Skip the 'X' + // + String++; + } + + *Data = 0; + + while (InternalIsHexaDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINTN, then MAX_UINTN is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > ((MAX_UINTN - InternalHexCharToUintn (*String)) >> 4)) { + *Data = MAX_UINTN; + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = (*Data << 4) + InternalHexCharToUintn (*String); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode hexadecimal string to a value of type + UINT64. + + This function outputs a value of type UINT64 by interpreting the contents of + the Unicode string specified by String as a hexadecimal number. The format of + the input Unicode string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. + If "x" appears in the input string, it must be prefixed with at least one 0. + The function will ignore the pad space, which includes spaces or tab + characters, before [zeros], [x] or [hexadecimal digit]. The running zero + before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts + after [x] or the first valid hexadecimal digit. Then, the function stops at + the first character that is a not a valid hexadecimal character or NULL, + whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid hexadecimal digits in the above format, then 0 is + stored at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINT64, then + MAX_UINT64 is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + hexadecimal digits right after the optional pad spaces, the value of String + is stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINT64. + +**/ +RETURN_STATUS +EFIAPI +StrHexToUint64S ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT UINT64 *Data + ) +{ + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == L' ') || (*String == L'\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == L'0') { + String++; + } + + if (InternalCharToUpper (*String) == L'X') { + if (*(String - 1) != L'0') { + *Data = 0; + return RETURN_SUCCESS; + } + // + // Skip the 'X' + // + String++; + } + + *Data = 0; + + while (InternalIsHexaDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINT64, then MAX_UINT64 is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > RShiftU64 (MAX_UINT64 - InternalHexCharToUintn (*String), 4)) { + *Data = MAX_UINT64; + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = LShiftU64 (*Data, 4) + InternalHexCharToUintn (*String); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_SUCCESS; +} + +/** Returns the length of a Null-terminated Ascii string. This function is similar as strlen_s defined in C11. @@ -1041,6 +1530,484 @@ AsciiStrnCatS ( } /** + Convert a Null-terminated Ascii decimal string to a value of type UINTN. + + This function outputs a value of type UINTN by interpreting the contents of + the Ascii string specified by String as a decimal number. The format of the + input Ascii string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before + [decimal digits]. The running zero in the beginning of [decimal digits] will + be ignored. Then, the function stops at the first character that is a not a + valid decimal character or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid decimal digits in the above format, then 0 is stored + at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINTN, then + MAX_UINTN is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + decimal digits right after the optional pad spaces, the value of String is + stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Ascii string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumAsciiStringLength is not zero, + and String contains more than + PcdMaximumAsciiStringLength Ascii + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINTN. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrDecimalToUintnS ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT UINTN *Data + ) +{ + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == ' ') || (*String == '\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == '0') { + String++; + } + + *Data = 0; + + while (InternalAsciiIsDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINTN, then MAX_UINTN is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > ((MAX_UINTN - (*String - '0')) / 10)) { + *Data = MAX_UINTN; + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = *Data * 10 + (*String - '0'); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Ascii decimal string to a value of type UINT64. + + This function outputs a value of type UINT64 by interpreting the contents of + the Ascii string specified by String as a decimal number. The format of the + input Ascii string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before + [decimal digits]. The running zero in the beginning of [decimal digits] will + be ignored. Then, the function stops at the first character that is a not a + valid decimal character or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid decimal digits in the above format, then 0 is stored + at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINT64, then + MAX_UINT64 is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + decimal digits right after the optional pad spaces, the value of String is + stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Ascii string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumAsciiStringLength is not zero, + and String contains more than + PcdMaximumAsciiStringLength Ascii + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINT64. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrDecimalToUint64S ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT UINT64 *Data + ) +{ + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == ' ') || (*String == '\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == '0') { + String++; + } + + *Data = 0; + + while (InternalAsciiIsDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINT64, then MAX_UINT64 is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > DivU64x32 (MAX_UINT64 - (*String - '0'), 10)) { + *Data = MAX_UINT64; + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = MultU64x32 (*Data, 10) + (*String - '0'); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Ascii hexadecimal string to a value of type UINTN. + + This function outputs a value of type UINTN by interpreting the contents of + the Ascii string specified by String as a hexadecimal number. The format of + the input Ascii string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If + "x" appears in the input string, it must be prefixed with at least one 0. The + function will ignore the pad space, which includes spaces or tab characters, + before [zeros], [x] or [hexadecimal digits]. The running zero before [x] or + [hexadecimal digits] will be ignored. Then, the decoding starts after [x] or + the first valid hexadecimal digit. Then, the function stops at the first + character that is a not a valid hexadecimal character or Null-terminator, + whichever on comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid hexadecimal digits in the above format, then 0 is + stored at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINTN, then + MAX_UINTN is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + hexadecimal digits right after the optional pad spaces, the value of String + is stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Ascii string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumAsciiStringLength is not zero, + and String contains more than + PcdMaximumAsciiStringLength Ascii + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINTN. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrHexToUintnS ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT UINTN *Data + ) +{ + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == ' ') || (*String == '\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == '0') { + String++; + } + + if (InternalBaseLibAsciiToUpper (*String) == 'X') { + if (*(String - 1) != '0') { + *Data = 0; + return RETURN_SUCCESS; + } + // + // Skip the 'X' + // + String++; + } + + *Data = 0; + + while (InternalAsciiIsHexaDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINTN, then MAX_UINTN is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > ((MAX_UINTN - InternalAsciiHexCharToUintn (*String)) >> 4)) { + *Data = MAX_UINTN; + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = (*Data << 4) + InternalAsciiHexCharToUintn (*String); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Ascii hexadecimal string to a value of type UINT64. + + This function outputs a value of type UINT64 by interpreting the contents of + the Ascii string specified by String as a hexadecimal number. The format of + the input Ascii string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If + "x" appears in the input string, it must be prefixed with at least one 0. The + function will ignore the pad space, which includes spaces or tab characters, + before [zeros], [x] or [hexadecimal digits]. The running zero before [x] or + [hexadecimal digits] will be ignored. Then, the decoding starts after [x] or + the first valid hexadecimal digit. Then, the function stops at the first + character that is a not a valid hexadecimal character or Null-terminator, + whichever on comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid hexadecimal digits in the above format, then 0 is + stored at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINT64, then + MAX_UINT64 is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + hexadecimal digits right after the optional pad spaces, the value of String + is stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Ascii string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumAsciiStringLength is not zero, + and String contains more than + PcdMaximumAsciiStringLength Ascii + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINT64. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrHexToUint64S ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT UINT64 *Data + ) +{ + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == ' ') || (*String == '\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == '0') { + String++; + } + + if (InternalBaseLibAsciiToUpper (*String) == 'X') { + if (*(String - 1) != '0') { + *Data = 0; + return RETURN_SUCCESS; + } + // + // Skip the 'X' + // + String++; + } + + *Data = 0; + + while (InternalAsciiIsHexaDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINT64, then MAX_UINT64 is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > RShiftU64 (MAX_UINT64 - InternalAsciiHexCharToUintn (*String), 4)) { + *Data = MAX_UINT64; + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = LShiftU64 (*Data, 4) + InternalAsciiHexCharToUintn (*String); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_SUCCESS; +} + +/** Convert a Null-terminated Unicode string to a Null-terminated ASCII string. -- 1.9.5.msysgit.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 2/4] MdePkg/BaseLib: Add safe string functions that convert str to value 2017-01-04 11:22 ` [PATCH 2/4] MdePkg/BaseLib: Add safe string functions that convert str to value Hao Wu @ 2017-01-09 2:02 ` Yao, Jiewen 0 siblings, 0 replies; 9+ messages in thread From: Yao, Jiewen @ 2017-01-09 2:02 UTC (permalink / raw) To: Wu, Hao A, edk2-devel@lists.01.org; +Cc: Gao, Liming, Kinney, Michael D Reviewed-by: jiewen.yao@intel.com > -----Original Message----- > From: Wu, Hao A > Sent: Wednesday, January 4, 2017 7:23 PM > To: edk2-devel@lists.01.org > Cc: Wu, Hao A <hao.a.wu@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; > Gao, Liming <liming.gao@intel.com>; Kinney, Michael D > <michael.d.kinney@intel.com> > Subject: [PATCH 2/4] MdePkg/BaseLib: Add safe string functions that convert str > to value > > Add the following 8 APIs: > [Ascii]StrDecimalToUintnS > [Ascii]StrDecimalToUint64S > [Ascii]StrHexToUintnS > [Ascii]StrHexToUint64S > > These safe version APIs are used to enhance their counterpart (APIs > without trailing 'S' in function names). > > These safe version APIs perform checks to the input string and will return > relative status to reflect the check result: > When the input string exceeds the range of UINTN/64, these APIs will > return RETURN_UNSUPPORTED and store MAX_UINTN/64 in the output data. > When no conversion can be performed for the input string, these APIs will > return RETURN_SUCCESS and store 0 in the output data. > > The optional parameter 'EndPointer', if provided, will point to the > character that stopped the scan. > > Cc: Jiewen Yao <jiewen.yao@intel.com> > Cc: Liming Gao <liming.gao@intel.com> > Cc: Michael Kinney <michael.d.kinney@intel.com> > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Hao Wu <hao.a.wu@intel.com> > --- > MdePkg/Include/Library/BaseLib.h | 462 ++++++++++++++ > MdePkg/Library/BaseLib/BaseLibInternals.h | 166 ++++- > MdePkg/Library/BaseLib/SafeString.c | 975 > +++++++++++++++++++++++++++++- > 3 files changed, 1598 insertions(+), 5 deletions(-) > > diff --git a/MdePkg/Include/Library/BaseLib.h > b/MdePkg/Include/Library/BaseLib.h > index 72d1f0b..52011ee 100644 > --- a/MdePkg/Include/Library/BaseLib.h > +++ b/MdePkg/Include/Library/BaseLib.h > @@ -390,6 +390,240 @@ StrnCatS ( > ); > > /** > + Convert a Null-terminated Unicode decimal string to a value of type UINTN. > + > + This function outputs a value of type UINTN by interpreting the contents of > + the Unicode string specified by String as a decimal number. The format of the > + input Unicode string String is: > + > + [spaces] [decimal digits]. > + > + The valid decimal digit character is in the range [0-9]. The function will > + ignore the pad space, which includes spaces or tab characters, before > + [decimal digits]. The running zero in the beginning of [decimal digits] will > + be ignored. Then, the function stops at the first character that is a not a > + valid decimal character or a Null-terminator, whichever one comes first. > + > + If String is NULL, then ASSERT(). > + If Data is NULL, then ASSERT(). > + If String is not aligned in a 16-bit boundary, then ASSERT(). > + If PcdMaximumUnicodeStringLength is not zero, and String contains more > than > + PcdMaximumUnicodeStringLength Unicode characters, not including the > + Null-terminator, then ASSERT(). > + > + If String has no valid decimal digits in the above format, then 0 is stored > + at the location pointed to by Data. > + If the number represented by String exceeds the range defined by UINTN, > then > + MAX_UINTN is stored at the location pointed to by Data. > + > + If EndPointer is not NULL, a pointer to the character that stopped the scan > + is stored at the location pointed to by EndPointer. If String has no valid > + decimal digits right after the optional pad spaces, the value of String is > + stored at the location pointed to by EndPointer. > + > + @param String Pointer to a Null-terminated Unicode > string. > + @param EndPointer Pointer to character that stops scan. > + @param Data Pointer to the converted value. > + > + @retval RETURN_SUCCESS Value is translated from String. > + @retval RETURN_INVALID_PARAMETER If String is NULL. > + If Data is NULL. > + If PcdMaximumUnicodeStringLength is > not > + zero, and String contains more than > + PcdMaximumUnicodeStringLength > Unicode > + characters, not including the > + Null-terminator. > + @retval RETURN_UNSUPPORTED If the number represented by String > exceeds > + the range defined by UINTN. > + > +**/ > +RETURN_STATUS > +EFIAPI > +StrDecimalToUintnS ( > + IN CONST CHAR16 *String, > + OUT CHAR16 **EndPointer, OPTIONAL > + OUT UINTN *Data > + ); > + > +/** > + Convert a Null-terminated Unicode decimal string to a value of type UINT64. > + > + This function outputs a value of type UINT64 by interpreting the contents of > + the Unicode string specified by String as a decimal number. The format of the > + input Unicode string String is: > + > + [spaces] [decimal digits]. > + > + The valid decimal digit character is in the range [0-9]. The function will > + ignore the pad space, which includes spaces or tab characters, before > + [decimal digits]. The running zero in the beginning of [decimal digits] will > + be ignored. Then, the function stops at the first character that is a not a > + valid decimal character or a Null-terminator, whichever one comes first. > + > + If String is NULL, then ASSERT(). > + If Data is NULL, then ASSERT(). > + If String is not aligned in a 16-bit boundary, then ASSERT(). > + If PcdMaximumUnicodeStringLength is not zero, and String contains more > than > + PcdMaximumUnicodeStringLength Unicode characters, not including the > + Null-terminator, then ASSERT(). > + > + If String has no valid decimal digits in the above format, then 0 is stored > + at the location pointed to by Data. > + If the number represented by String exceeds the range defined by UINT64, > then > + MAX_UINT64 is stored at the location pointed to by Data. > + > + If EndPointer is not NULL, a pointer to the character that stopped the scan > + is stored at the location pointed to by EndPointer. If String has no valid > + decimal digits right after the optional pad spaces, the value of String is > + stored at the location pointed to by EndPointer. > + > + @param String Pointer to a Null-terminated Unicode > string. > + @param EndPointer Pointer to character that stops scan. > + @param Data Pointer to the converted value. > + > + @retval RETURN_SUCCESS Value is translated from String. > + @retval RETURN_INVALID_PARAMETER If String is NULL. > + If Data is NULL. > + If PcdMaximumUnicodeStringLength is > not > + zero, and String contains more than > + PcdMaximumUnicodeStringLength > Unicode > + characters, not including the > + Null-terminator. > + @retval RETURN_UNSUPPORTED If the number represented by String > exceeds > + the range defined by UINT64. > + > +**/ > +RETURN_STATUS > +EFIAPI > +StrDecimalToUint64S ( > + IN CONST CHAR16 *String, > + OUT CHAR16 **EndPointer, OPTIONAL > + OUT UINT64 *Data > + ); > + > +/** > + Convert a Null-terminated Unicode hexadecimal string to a value of type > + UINTN. > + > + This function outputs a value of type UINTN by interpreting the contents of > + the Unicode string specified by String as a hexadecimal number. The format of > + the input Unicode string String is: > + > + [spaces][zeros][x][hexadecimal digits]. > + > + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. > + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. > + If "x" appears in the input string, it must be prefixed with at least one 0. > + The function will ignore the pad space, which includes spaces or tab > + characters, before [zeros], [x] or [hexadecimal digit]. The running zero > + before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts > + after [x] or the first valid hexadecimal digit. Then, the function stops at > + the first character that is a not a valid hexadecimal character or NULL, > + whichever one comes first. > + > + If String is NULL, then ASSERT(). > + If Data is NULL, then ASSERT(). > + If String is not aligned in a 16-bit boundary, then ASSERT(). > + If PcdMaximumUnicodeStringLength is not zero, and String contains more > than > + PcdMaximumUnicodeStringLength Unicode characters, not including the > + Null-terminator, then ASSERT(). > + > + If String has no valid hexadecimal digits in the above format, then 0 is > + stored at the location pointed to by Data. > + If the number represented by String exceeds the range defined by UINTN, > then > + MAX_UINTN is stored at the location pointed to by Data. > + > + If EndPointer is not NULL, a pointer to the character that stopped the scan > + is stored at the location pointed to by EndPointer. If String has no valid > + hexadecimal digits right after the optional pad spaces, the value of String > + is stored at the location pointed to by EndPointer. > + > + @param String Pointer to a Null-terminated Unicode > string. > + @param EndPointer Pointer to character that stops scan. > + @param Data Pointer to the converted value. > + > + @retval RETURN_SUCCESS Value is translated from String. > + @retval RETURN_INVALID_PARAMETER If String is NULL. > + If Data is NULL. > + If PcdMaximumUnicodeStringLength is > not > + zero, and String contains more than > + PcdMaximumUnicodeStringLength > Unicode > + characters, not including the > + Null-terminator. > + @retval RETURN_UNSUPPORTED If the number represented by String > exceeds > + the range defined by UINTN. > + > +**/ > +RETURN_STATUS > +EFIAPI > +StrHexToUintnS ( > + IN CONST CHAR16 *String, > + OUT CHAR16 **EndPointer, OPTIONAL > + OUT UINTN *Data > + ); > + > +/** > + Convert a Null-terminated Unicode hexadecimal string to a value of type > + UINT64. > + > + This function outputs a value of type UINT64 by interpreting the contents of > + the Unicode string specified by String as a hexadecimal number. The format of > + the input Unicode string String is: > + > + [spaces][zeros][x][hexadecimal digits]. > + > + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. > + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. > + If "x" appears in the input string, it must be prefixed with at least one 0. > + The function will ignore the pad space, which includes spaces or tab > + characters, before [zeros], [x] or [hexadecimal digit]. The running zero > + before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts > + after [x] or the first valid hexadecimal digit. Then, the function stops at > + the first character that is a not a valid hexadecimal character or NULL, > + whichever one comes first. > + > + If String is NULL, then ASSERT(). > + If Data is NULL, then ASSERT(). > + If String is not aligned in a 16-bit boundary, then ASSERT(). > + If PcdMaximumUnicodeStringLength is not zero, and String contains more > than > + PcdMaximumUnicodeStringLength Unicode characters, not including the > + Null-terminator, then ASSERT(). > + > + If String has no valid hexadecimal digits in the above format, then 0 is > + stored at the location pointed to by Data. > + If the number represented by String exceeds the range defined by UINT64, > then > + MAX_UINT64 is stored at the location pointed to by Data. > + > + If EndPointer is not NULL, a pointer to the character that stopped the scan > + is stored at the location pointed to by EndPointer. If String has no valid > + hexadecimal digits right after the optional pad spaces, the value of String > + is stored at the location pointed to by EndPointer. > + > + @param String Pointer to a Null-terminated Unicode > string. > + @param EndPointer Pointer to character that stops scan. > + @param Data Pointer to the converted value. > + > + @retval RETURN_SUCCESS Value is translated from String. > + @retval RETURN_INVALID_PARAMETER If String is NULL. > + If Data is NULL. > + If PcdMaximumUnicodeStringLength is > not > + zero, and String contains more than > + PcdMaximumUnicodeStringLength > Unicode > + characters, not including the > + Null-terminator. > + @retval RETURN_UNSUPPORTED If the number represented by String > exceeds > + the range defined by UINT64. > + > +**/ > +RETURN_STATUS > +EFIAPI > +StrHexToUint64S ( > + IN CONST CHAR16 *String, > + OUT CHAR16 **EndPointer, OPTIONAL > + OUT UINT64 *Data > + ); > + > +/** > Returns the length of a Null-terminated Ascii string. > > This function is similar as strlen_s defined in C11. > @@ -582,6 +816,234 @@ AsciiStrnCatS ( > IN UINTN Length > ); > > +/** > + Convert a Null-terminated Ascii decimal string to a value of type UINTN. > + > + This function outputs a value of type UINTN by interpreting the contents of > + the Ascii string specified by String as a decimal number. The format of the > + input Ascii string String is: > + > + [spaces] [decimal digits]. > + > + The valid decimal digit character is in the range [0-9]. The function will > + ignore the pad space, which includes spaces or tab characters, before > + [decimal digits]. The running zero in the beginning of [decimal digits] will > + be ignored. Then, the function stops at the first character that is a not a > + valid decimal character or a Null-terminator, whichever one comes first. > + > + If String is NULL, then ASSERT(). > + If Data is NULL, then ASSERT(). > + If PcdMaximumAsciiStringLength is not zero, and String contains more than > + PcdMaximumAsciiStringLength Ascii characters, not including the > + Null-terminator, then ASSERT(). > + > + If String has no valid decimal digits in the above format, then 0 is stored > + at the location pointed to by Data. > + If the number represented by String exceeds the range defined by UINTN, > then > + MAX_UINTN is stored at the location pointed to by Data. > + > + If EndPointer is not NULL, a pointer to the character that stopped the scan > + is stored at the location pointed to by EndPointer. If String has no valid > + decimal digits right after the optional pad spaces, the value of String is > + stored at the location pointed to by EndPointer. > + > + @param String Pointer to a Null-terminated Ascii > string. > + @param EndPointer Pointer to character that stops scan. > + @param Data Pointer to the converted value. > + > + @retval RETURN_SUCCESS Value is translated from String. > + @retval RETURN_INVALID_PARAMETER If String is NULL. > + If Data is NULL. > + If PcdMaximumAsciiStringLength is not > zero, > + and String contains more than > + PcdMaximumAsciiStringLength Ascii > + characters, not including the > + Null-terminator. > + @retval RETURN_UNSUPPORTED If the number represented by String > exceeds > + the range defined by UINTN. > + > +**/ > +RETURN_STATUS > +EFIAPI > +AsciiStrDecimalToUintnS ( > + IN CONST CHAR8 *String, > + OUT CHAR8 **EndPointer, OPTIONAL > + OUT UINTN *Data > + ); > + > +/** > + Convert a Null-terminated Ascii decimal string to a value of type UINT64. > + > + This function outputs a value of type UINT64 by interpreting the contents of > + the Ascii string specified by String as a decimal number. The format of the > + input Ascii string String is: > + > + [spaces] [decimal digits]. > + > + The valid decimal digit character is in the range [0-9]. The function will > + ignore the pad space, which includes spaces or tab characters, before > + [decimal digits]. The running zero in the beginning of [decimal digits] will > + be ignored. Then, the function stops at the first character that is a not a > + valid decimal character or a Null-terminator, whichever one comes first. > + > + If String is NULL, then ASSERT(). > + If Data is NULL, then ASSERT(). > + If PcdMaximumAsciiStringLength is not zero, and String contains more than > + PcdMaximumAsciiStringLength Ascii characters, not including the > + Null-terminator, then ASSERT(). > + > + If String has no valid decimal digits in the above format, then 0 is stored > + at the location pointed to by Data. > + If the number represented by String exceeds the range defined by UINT64, > then > + MAX_UINT64 is stored at the location pointed to by Data. > + > + If EndPointer is not NULL, a pointer to the character that stopped the scan > + is stored at the location pointed to by EndPointer. If String has no valid > + decimal digits right after the optional pad spaces, the value of String is > + stored at the location pointed to by EndPointer. > + > + @param String Pointer to a Null-terminated Ascii > string. > + @param EndPointer Pointer to character that stops scan. > + @param Data Pointer to the converted value. > + > + @retval RETURN_SUCCESS Value is translated from String. > + @retval RETURN_INVALID_PARAMETER If String is NULL. > + If Data is NULL. > + If PcdMaximumAsciiStringLength is not > zero, > + and String contains more than > + PcdMaximumAsciiStringLength Ascii > + characters, not including the > + Null-terminator. > + @retval RETURN_UNSUPPORTED If the number represented by String > exceeds > + the range defined by UINT64. > + > +**/ > +RETURN_STATUS > +EFIAPI > +AsciiStrDecimalToUint64S ( > + IN CONST CHAR8 *String, > + OUT CHAR8 **EndPointer, OPTIONAL > + OUT UINT64 *Data > + ); > + > +/** > + Convert a Null-terminated Ascii hexadecimal string to a value of type UINTN. > + > + This function outputs a value of type UINTN by interpreting the contents of > + the Ascii string specified by String as a hexadecimal number. The format of > + the input Ascii string String is: > + > + [spaces][zeros][x][hexadecimal digits]. > + > + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. > + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If > + "x" appears in the input string, it must be prefixed with at least one 0. The > + function will ignore the pad space, which includes spaces or tab characters, > + before [zeros], [x] or [hexadecimal digits]. The running zero before [x] or > + [hexadecimal digits] will be ignored. Then, the decoding starts after [x] or > + the first valid hexadecimal digit. Then, the function stops at the first > + character that is a not a valid hexadecimal character or Null-terminator, > + whichever on comes first. > + > + If String is NULL, then ASSERT(). > + If Data is NULL, then ASSERT(). > + If PcdMaximumAsciiStringLength is not zero, and String contains more than > + PcdMaximumAsciiStringLength Ascii characters, not including the > + Null-terminator, then ASSERT(). > + > + If String has no valid hexadecimal digits in the above format, then 0 is > + stored at the location pointed to by Data. > + If the number represented by String exceeds the range defined by UINTN, > then > + MAX_UINTN is stored at the location pointed to by Data. > + > + If EndPointer is not NULL, a pointer to the character that stopped the scan > + is stored at the location pointed to by EndPointer. If String has no valid > + hexadecimal digits right after the optional pad spaces, the value of String > + is stored at the location pointed to by EndPointer. > + > + @param String Pointer to a Null-terminated Ascii > string. > + @param EndPointer Pointer to character that stops scan. > + @param Data Pointer to the converted value. > + > + @retval RETURN_SUCCESS Value is translated from String. > + @retval RETURN_INVALID_PARAMETER If String is NULL. > + If Data is NULL. > + If PcdMaximumAsciiStringLength is not > zero, > + and String contains more than > + PcdMaximumAsciiStringLength Ascii > + characters, not including the > + Null-terminator. > + @retval RETURN_UNSUPPORTED If the number represented by String > exceeds > + the range defined by UINTN. > + > +**/ > +RETURN_STATUS > +EFIAPI > +AsciiStrHexToUintnS ( > + IN CONST CHAR8 *String, > + OUT CHAR8 **EndPointer, OPTIONAL > + OUT UINTN *Data > + ); > + > +/** > + Convert a Null-terminated Ascii hexadecimal string to a value of type UINT64. > + > + This function outputs a value of type UINT64 by interpreting the contents of > + the Ascii string specified by String as a hexadecimal number. The format of > + the input Ascii string String is: > + > + [spaces][zeros][x][hexadecimal digits]. > + > + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. > + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If > + "x" appears in the input string, it must be prefixed with at least one 0. The > + function will ignore the pad space, which includes spaces or tab characters, > + before [zeros], [x] or [hexadecimal digits]. The running zero before [x] or > + [hexadecimal digits] will be ignored. Then, the decoding starts after [x] or > + the first valid hexadecimal digit. Then, the function stops at the first > + character that is a not a valid hexadecimal character or Null-terminator, > + whichever on comes first. > + > + If String is NULL, then ASSERT(). > + If Data is NULL, then ASSERT(). > + If PcdMaximumAsciiStringLength is not zero, and String contains more than > + PcdMaximumAsciiStringLength Ascii characters, not including the > + Null-terminator, then ASSERT(). > + > + If String has no valid hexadecimal digits in the above format, then 0 is > + stored at the location pointed to by Data. > + If the number represented by String exceeds the range defined by UINT64, > then > + MAX_UINT64 is stored at the location pointed to by Data. > + > + If EndPointer is not NULL, a pointer to the character that stopped the scan > + is stored at the location pointed to by EndPointer. If String has no valid > + hexadecimal digits right after the optional pad spaces, the value of String > + is stored at the location pointed to by EndPointer. > + > + @param String Pointer to a Null-terminated Ascii > string. > + @param EndPointer Pointer to character that stops scan. > + @param Data Pointer to the converted value. > + > + @retval RETURN_SUCCESS Value is translated from String. > + @retval RETURN_INVALID_PARAMETER If String is NULL. > + If Data is NULL. > + If PcdMaximumAsciiStringLength is not > zero, > + and String contains more than > + PcdMaximumAsciiStringLength Ascii > + characters, not including the > + Null-terminator. > + @retval RETURN_UNSUPPORTED If the number represented by String > exceeds > + the range defined by UINT64. > + > +**/ > +RETURN_STATUS > +EFIAPI > +AsciiStrHexToUint64S ( > + IN CONST CHAR8 *String, > + OUT CHAR8 **EndPointer, OPTIONAL > + OUT UINT64 *Data > + ); > + > > #ifndef DISABLE_NEW_DEPRECATED_INTERFACES > > diff --git a/MdePkg/Library/BaseLib/BaseLibInternals.h > b/MdePkg/Library/BaseLib/BaseLibInternals.h > index a8f712b..ea387ce 100644 > --- a/MdePkg/Library/BaseLib/BaseLibInternals.h > +++ b/MdePkg/Library/BaseLib/BaseLibInternals.h > @@ -1,7 +1,7 @@ > /** @file > Declaration of internal functions in BaseLib. > > - Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR> > + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR> > This program and the accompanying materials > are licensed and made available under the terms and conditions of the BSD > License > which accompanies this distribution. The full text of the license may be > found at > @@ -477,6 +477,170 @@ InternalLongJump ( > ); > > > +/** > + Check if a Unicode character is a decimal character. > + > + This internal function checks if a Unicode character is a > + decimal character. The valid decimal character is from > + L'0' to L'9'. > + > + @param Char The character to check against. > + > + @retval TRUE If the Char is a decmial character. > + @retval FALSE If the Char is not a decmial character. > + > +**/ > +BOOLEAN > +EFIAPI > +InternalIsDecimalDigitCharacter ( > + IN CHAR16 Char > + ); > + > + > +/** > + Convert a Unicode character to upper case only if > + it maps to a valid small-case ASCII character. > + > + This internal function only deal with Unicode character > + which maps to a valid small-case ASCII character, i.e. > + L'a' to L'z'. For other Unicode character, the input character > + is returned directly. > + > + @param Char The character to convert. > + > + @retval LowerCharacter If the Char is with range L'a' to L'z'. > + @retval Unchanged Otherwise. > + > +**/ > +CHAR16 > +EFIAPI > +InternalCharToUpper ( > + IN CHAR16 Char > + ); > + > + > +/** > + Convert a Unicode character to numerical value. > + > + This internal function only deal with Unicode character > + which maps to a valid hexadecimal ASII character, i.e. > + L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other > + Unicode character, the value returned does not make sense. > + > + @param Char The character to convert. > + > + @return The numerical value converted. > + > +**/ > +UINTN > +EFIAPI > +InternalHexCharToUintn ( > + IN CHAR16 Char > + ); > + > + > +/** > + Check if a Unicode character is a hexadecimal character. > + > + This internal function checks if a Unicode character is a > + decimal character. The valid hexadecimal character is > + L'0' to L'9', L'a' to L'f', or L'A' to L'F'. > + > + > + @param Char The character to check against. > + > + @retval TRUE If the Char is a hexadecmial character. > + @retval FALSE If the Char is not a hexadecmial character. > + > +**/ > +BOOLEAN > +EFIAPI > +InternalIsHexaDecimalDigitCharacter ( > + IN CHAR16 Char > + ); > + > + > +/** > + Check if a ASCII character is a decimal character. > + > + This internal function checks if a Unicode character is a > + decimal character. The valid decimal character is from > + '0' to '9'. > + > + @param Char The character to check against. > + > + @retval TRUE If the Char is a decmial character. > + @retval FALSE If the Char is not a decmial character. > + > +**/ > +BOOLEAN > +EFIAPI > +InternalAsciiIsDecimalDigitCharacter ( > + IN CHAR8 Char > + ); > + > + > +/** > + Converts a lowercase Ascii character to upper one. > + > + If Chr is lowercase Ascii character, then converts it to upper one. > + > + If Value >= 0xA0, then ASSERT(). > + If (Value & 0x0F) >= 0x0A, then ASSERT(). > + > + @param Chr one Ascii character > + > + @return The uppercase value of Ascii character > + > +**/ > +CHAR8 > +EFIAPI > +InternalBaseLibAsciiToUpper ( > + IN CHAR8 Chr > + ); > + > + > +/** > + Check if a ASCII character is a hexadecimal character. > + > + This internal function checks if a ASCII character is a > + decimal character. The valid hexadecimal character is > + L'0' to L'9', L'a' to L'f', or L'A' to L'F'. > + > + > + @param Char The character to check against. > + > + @retval TRUE If the Char is a hexadecmial character. > + @retval FALSE If the Char is not a hexadecmial character. > + > +**/ > +BOOLEAN > +EFIAPI > +InternalAsciiIsHexaDecimalDigitCharacter ( > + IN CHAR8 Char > + ); > + > + > +/** > + Convert a ASCII character to numerical value. > + > + This internal function only deal with Unicode character > + which maps to a valid hexadecimal ASII character, i.e. > + '0' to '9', 'a' to 'f' or 'A' to 'F'. For other > + ASCII character, the value returned does not make sense. > + > + @param Char The character to convert. > + > + @return The numerical value converted. > + > +**/ > +UINTN > +EFIAPI > +InternalAsciiHexCharToUintn ( > + IN CHAR8 Char > + ); > + > + > // > // Ia32 and x64 specific functions > // > diff --git a/MdePkg/Library/BaseLib/SafeString.c > b/MdePkg/Library/BaseLib/SafeString.c > index f80db9f..5edc6ef 100644 > --- a/MdePkg/Library/BaseLib/SafeString.c > +++ b/MdePkg/Library/BaseLib/SafeString.c > @@ -12,10 +12,7 @@ > > **/ > > -#include <Base.h> > -#include <Library/DebugLib.h> > -#include <Library/PcdLib.h> > -#include <Library/BaseLib.h> > +#include "BaseLibInternals.h" > > #define RSIZE_MAX (PcdGet32 (PcdMaximumUnicodeStringLength)) > > @@ -585,6 +582,498 @@ StrnCatS ( > } > > /** > + Convert a Null-terminated Unicode decimal string to a value of type UINTN. > + > + This function outputs a value of type UINTN by interpreting the contents of > + the Unicode string specified by String as a decimal number. The format of the > + input Unicode string String is: > + > + [spaces] [decimal digits]. > + > + The valid decimal digit character is in the range [0-9]. The function will > + ignore the pad space, which includes spaces or tab characters, before > + [decimal digits]. The running zero in the beginning of [decimal digits] will > + be ignored. Then, the function stops at the first character that is a not a > + valid decimal character or a Null-terminator, whichever one comes first. > + > + If String is NULL, then ASSERT(). > + If Data is NULL, then ASSERT(). > + If String is not aligned in a 16-bit boundary, then ASSERT(). > + If PcdMaximumUnicodeStringLength is not zero, and String contains more > than > + PcdMaximumUnicodeStringLength Unicode characters, not including the > + Null-terminator, then ASSERT(). > + > + If String has no valid decimal digits in the above format, then 0 is stored > + at the location pointed to by Data. > + If the number represented by String exceeds the range defined by UINTN, > then > + MAX_UINTN is stored at the location pointed to by Data. > + > + If EndPointer is not NULL, a pointer to the character that stopped the scan > + is stored at the location pointed to by EndPointer. If String has no valid > + decimal digits right after the optional pad spaces, the value of String is > + stored at the location pointed to by EndPointer. > + > + @param String Pointer to a Null-terminated Unicode > string. > + @param EndPointer Pointer to character that stops scan. > + @param Data Pointer to the converted value. > + > + @retval RETURN_SUCCESS Value is translated from String. > + @retval RETURN_INVALID_PARAMETER If String is NULL. > + If Data is NULL. > + If PcdMaximumUnicodeStringLength is > not > + zero, and String contains more than > + PcdMaximumUnicodeStringLength > Unicode > + characters, not including the > + Null-terminator. > + @retval RETURN_UNSUPPORTED If the number represented by String > exceeds > + the range defined by UINTN. > + > +**/ > +RETURN_STATUS > +EFIAPI > +StrDecimalToUintnS ( > + IN CONST CHAR16 *String, > + OUT CHAR16 **EndPointer, OPTIONAL > + OUT UINTN *Data > + ) > +{ > + ASSERT (((UINTN) String & BIT0) == 0); > + > + // > + // 1. Neither String nor Data shall be a null pointer. > + // > + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), > RETURN_INVALID_PARAMETER); > + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), > RETURN_INVALID_PARAMETER); > + > + // > + // 2. The length of String shall not be greater than RSIZE_MAX. > + // > + if (RSIZE_MAX != 0) { > + SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= > RSIZE_MAX), RETURN_INVALID_PARAMETER); > + } > + > + if (EndPointer != NULL) { > + *EndPointer = (CHAR16 *) String; > + } > + > + // > + // Ignore the pad spaces (space or tab) > + // > + while ((*String == L' ') || (*String == L'\t')) { > + String++; > + } > + > + // > + // Ignore leading Zeros after the spaces > + // > + while (*String == L'0') { > + String++; > + } > + > + *Data = 0; > + > + while (InternalIsDecimalDigitCharacter (*String)) { > + // > + // If the number represented by String overflows according to the range > + // defined by UINTN, then MAX_UINTN is stored in *Data and > + // RETURN_UNSUPPORTED is returned. > + // > + if (*Data > ((MAX_UINTN - (*String - L'0')) / 10)) { > + *Data = MAX_UINTN; > + if (EndPointer != NULL) { > + *EndPointer = (CHAR16 *) String; > + } > + return RETURN_UNSUPPORTED; > + } > + > + *Data = *Data * 10 + (*String - L'0'); > + String++; > + } > + > + if (EndPointer != NULL) { > + *EndPointer = (CHAR16 *) String; > + } > + return RETURN_SUCCESS; > +} > + > +/** > + Convert a Null-terminated Unicode decimal string to a value of type UINT64. > + > + This function outputs a value of type UINT64 by interpreting the contents of > + the Unicode string specified by String as a decimal number. The format of the > + input Unicode string String is: > + > + [spaces] [decimal digits]. > + > + The valid decimal digit character is in the range [0-9]. The function will > + ignore the pad space, which includes spaces or tab characters, before > + [decimal digits]. The running zero in the beginning of [decimal digits] will > + be ignored. Then, the function stops at the first character that is a not a > + valid decimal character or a Null-terminator, whichever one comes first. > + > + If String is NULL, then ASSERT(). > + If Data is NULL, then ASSERT(). > + If String is not aligned in a 16-bit boundary, then ASSERT(). > + If PcdMaximumUnicodeStringLength is not zero, and String contains more > than > + PcdMaximumUnicodeStringLength Unicode characters, not including the > + Null-terminator, then ASSERT(). > + > + If String has no valid decimal digits in the above format, then 0 is stored > + at the location pointed to by Data. > + If the number represented by String exceeds the range defined by UINT64, > then > + MAX_UINT64 is stored at the location pointed to by Data. > + > + If EndPointer is not NULL, a pointer to the character that stopped the scan > + is stored at the location pointed to by EndPointer. If String has no valid > + decimal digits right after the optional pad spaces, the value of String is > + stored at the location pointed to by EndPointer. > + > + @param String Pointer to a Null-terminated Unicode > string. > + @param EndPointer Pointer to character that stops scan. > + @param Data Pointer to the converted value. > + > + @retval RETURN_SUCCESS Value is translated from String. > + @retval RETURN_INVALID_PARAMETER If String is NULL. > + If Data is NULL. > + If PcdMaximumUnicodeStringLength is > not > + zero, and String contains more than > + PcdMaximumUnicodeStringLength > Unicode > + characters, not including the > + Null-terminator. > + @retval RETURN_UNSUPPORTED If the number represented by String > exceeds > + the range defined by UINT64. > + > +**/ > +RETURN_STATUS > +EFIAPI > +StrDecimalToUint64S ( > + IN CONST CHAR16 *String, > + OUT CHAR16 **EndPointer, OPTIONAL > + OUT UINT64 *Data > + ) > +{ > + ASSERT (((UINTN) String & BIT0) == 0); > + > + // > + // 1. Neither String nor Data shall be a null pointer. > + // > + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), > RETURN_INVALID_PARAMETER); > + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), > RETURN_INVALID_PARAMETER); > + > + // > + // 2. The length of String shall not be greater than RSIZE_MAX. > + // > + if (RSIZE_MAX != 0) { > + SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= > RSIZE_MAX), RETURN_INVALID_PARAMETER); > + } > + > + if (EndPointer != NULL) { > + *EndPointer = (CHAR16 *) String; > + } > + > + // > + // Ignore the pad spaces (space or tab) > + // > + while ((*String == L' ') || (*String == L'\t')) { > + String++; > + } > + > + // > + // Ignore leading Zeros after the spaces > + // > + while (*String == L'0') { > + String++; > + } > + > + *Data = 0; > + > + while (InternalIsDecimalDigitCharacter (*String)) { > + // > + // If the number represented by String overflows according to the range > + // defined by UINT64, then MAX_UINT64 is stored in *Data and > + // RETURN_UNSUPPORTED is returned. > + // > + if (*Data > DivU64x32 (MAX_UINT64 - (*String - L'0'), 10)) { > + *Data = MAX_UINT64; > + if (EndPointer != NULL) { > + *EndPointer = (CHAR16 *) String; > + } > + return RETURN_UNSUPPORTED; > + } > + > + *Data = MultU64x32 (*Data, 10) + (*String - L'0'); > + String++; > + } > + > + if (EndPointer != NULL) { > + *EndPointer = (CHAR16 *) String; > + } > + return RETURN_SUCCESS; > +} > + > +/** > + Convert a Null-terminated Unicode hexadecimal string to a value of type > + UINTN. > + > + This function outputs a value of type UINTN by interpreting the contents of > + the Unicode string specified by String as a hexadecimal number. The format of > + the input Unicode string String is: > + > + [spaces][zeros][x][hexadecimal digits]. > + > + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. > + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. > + If "x" appears in the input string, it must be prefixed with at least one 0. > + The function will ignore the pad space, which includes spaces or tab > + characters, before [zeros], [x] or [hexadecimal digit]. The running zero > + before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts > + after [x] or the first valid hexadecimal digit. Then, the function stops at > + the first character that is a not a valid hexadecimal character or NULL, > + whichever one comes first. > + > + If String is NULL, then ASSERT(). > + If Data is NULL, then ASSERT(). > + If String is not aligned in a 16-bit boundary, then ASSERT(). > + If PcdMaximumUnicodeStringLength is not zero, and String contains more > than > + PcdMaximumUnicodeStringLength Unicode characters, not including the > + Null-terminator, then ASSERT(). > + > + If String has no valid hexadecimal digits in the above format, then 0 is > + stored at the location pointed to by Data. > + If the number represented by String exceeds the range defined by UINTN, > then > + MAX_UINTN is stored at the location pointed to by Data. > + > + If EndPointer is not NULL, a pointer to the character that stopped the scan > + is stored at the location pointed to by EndPointer. If String has no valid > + hexadecimal digits right after the optional pad spaces, the value of String > + is stored at the location pointed to by EndPointer. > + > + @param String Pointer to a Null-terminated Unicode > string. > + @param EndPointer Pointer to character that stops scan. > + @param Data Pointer to the converted value. > + > + @retval RETURN_SUCCESS Value is translated from String. > + @retval RETURN_INVALID_PARAMETER If String is NULL. > + If Data is NULL. > + If PcdMaximumUnicodeStringLength is > not > + zero, and String contains more than > + PcdMaximumUnicodeStringLength > Unicode > + characters, not including the > + Null-terminator. > + @retval RETURN_UNSUPPORTED If the number represented by String > exceeds > + the range defined by UINTN. > + > +**/ > +RETURN_STATUS > +EFIAPI > +StrHexToUintnS ( > + IN CONST CHAR16 *String, > + OUT CHAR16 **EndPointer, OPTIONAL > + OUT UINTN *Data > + ) > +{ > + ASSERT (((UINTN) String & BIT0) == 0); > + > + // > + // 1. Neither String nor Data shall be a null pointer. > + // > + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), > RETURN_INVALID_PARAMETER); > + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), > RETURN_INVALID_PARAMETER); > + > + // > + // 2. The length of String shall not be greater than RSIZE_MAX. > + // > + if (RSIZE_MAX != 0) { > + SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= > RSIZE_MAX), RETURN_INVALID_PARAMETER); > + } > + > + if (EndPointer != NULL) { > + *EndPointer = (CHAR16 *) String; > + } > + > + // > + // Ignore the pad spaces (space or tab) > + // > + while ((*String == L' ') || (*String == L'\t')) { > + String++; > + } > + > + // > + // Ignore leading Zeros after the spaces > + // > + while (*String == L'0') { > + String++; > + } > + > + if (InternalCharToUpper (*String) == L'X') { > + if (*(String - 1) != L'0') { > + *Data = 0; > + return RETURN_SUCCESS; > + } > + // > + // Skip the 'X' > + // > + String++; > + } > + > + *Data = 0; > + > + while (InternalIsHexaDecimalDigitCharacter (*String)) { > + // > + // If the number represented by String overflows according to the range > + // defined by UINTN, then MAX_UINTN is stored in *Data and > + // RETURN_UNSUPPORTED is returned. > + // > + if (*Data > ((MAX_UINTN - InternalHexCharToUintn (*String)) >> 4)) { > + *Data = MAX_UINTN; > + if (EndPointer != NULL) { > + *EndPointer = (CHAR16 *) String; > + } > + return RETURN_UNSUPPORTED; > + } > + > + *Data = (*Data << 4) + InternalHexCharToUintn (*String); > + String++; > + } > + > + if (EndPointer != NULL) { > + *EndPointer = (CHAR16 *) String; > + } > + return RETURN_SUCCESS; > +} > + > +/** > + Convert a Null-terminated Unicode hexadecimal string to a value of type > + UINT64. > + > + This function outputs a value of type UINT64 by interpreting the contents of > + the Unicode string specified by String as a hexadecimal number. The format of > + the input Unicode string String is: > + > + [spaces][zeros][x][hexadecimal digits]. > + > + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. > + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. > + If "x" appears in the input string, it must be prefixed with at least one 0. > + The function will ignore the pad space, which includes spaces or tab > + characters, before [zeros], [x] or [hexadecimal digit]. The running zero > + before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts > + after [x] or the first valid hexadecimal digit. Then, the function stops at > + the first character that is a not a valid hexadecimal character or NULL, > + whichever one comes first. > + > + If String is NULL, then ASSERT(). > + If Data is NULL, then ASSERT(). > + If String is not aligned in a 16-bit boundary, then ASSERT(). > + If PcdMaximumUnicodeStringLength is not zero, and String contains more > than > + PcdMaximumUnicodeStringLength Unicode characters, not including the > + Null-terminator, then ASSERT(). > + > + If String has no valid hexadecimal digits in the above format, then 0 is > + stored at the location pointed to by Data. > + If the number represented by String exceeds the range defined by UINT64, > then > + MAX_UINT64 is stored at the location pointed to by Data. > + > + If EndPointer is not NULL, a pointer to the character that stopped the scan > + is stored at the location pointed to by EndPointer. If String has no valid > + hexadecimal digits right after the optional pad spaces, the value of String > + is stored at the location pointed to by EndPointer. > + > + @param String Pointer to a Null-terminated Unicode > string. > + @param EndPointer Pointer to character that stops scan. > + @param Data Pointer to the converted value. > + > + @retval RETURN_SUCCESS Value is translated from String. > + @retval RETURN_INVALID_PARAMETER If String is NULL. > + If Data is NULL. > + If PcdMaximumUnicodeStringLength is > not > + zero, and String contains more than > + PcdMaximumUnicodeStringLength > Unicode > + characters, not including the > + Null-terminator. > + @retval RETURN_UNSUPPORTED If the number represented by String > exceeds > + the range defined by UINT64. > + > +**/ > +RETURN_STATUS > +EFIAPI > +StrHexToUint64S ( > + IN CONST CHAR16 *String, > + OUT CHAR16 **EndPointer, OPTIONAL > + OUT UINT64 *Data > + ) > +{ > + ASSERT (((UINTN) String & BIT0) == 0); > + > + // > + // 1. Neither String nor Data shall be a null pointer. > + // > + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), > RETURN_INVALID_PARAMETER); > + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), > RETURN_INVALID_PARAMETER); > + > + // > + // 2. The length of String shall not be greater than RSIZE_MAX. > + // > + if (RSIZE_MAX != 0) { > + SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= > RSIZE_MAX), RETURN_INVALID_PARAMETER); > + } > + > + if (EndPointer != NULL) { > + *EndPointer = (CHAR16 *) String; > + } > + > + // > + // Ignore the pad spaces (space or tab) > + // > + while ((*String == L' ') || (*String == L'\t')) { > + String++; > + } > + > + // > + // Ignore leading Zeros after the spaces > + // > + while (*String == L'0') { > + String++; > + } > + > + if (InternalCharToUpper (*String) == L'X') { > + if (*(String - 1) != L'0') { > + *Data = 0; > + return RETURN_SUCCESS; > + } > + // > + // Skip the 'X' > + // > + String++; > + } > + > + *Data = 0; > + > + while (InternalIsHexaDecimalDigitCharacter (*String)) { > + // > + // If the number represented by String overflows according to the range > + // defined by UINT64, then MAX_UINT64 is stored in *Data and > + // RETURN_UNSUPPORTED is returned. > + // > + if (*Data > RShiftU64 (MAX_UINT64 - InternalHexCharToUintn (*String), 4)) > { > + *Data = MAX_UINT64; > + if (EndPointer != NULL) { > + *EndPointer = (CHAR16 *) String; > + } > + return RETURN_UNSUPPORTED; > + } > + > + *Data = LShiftU64 (*Data, 4) + InternalHexCharToUintn (*String); > + String++; > + } > + > + if (EndPointer != NULL) { > + *EndPointer = (CHAR16 *) String; > + } > + return RETURN_SUCCESS; > +} > + > +/** > Returns the length of a Null-terminated Ascii string. > > This function is similar as strlen_s defined in C11. > @@ -1041,6 +1530,484 @@ AsciiStrnCatS ( > } > > /** > + Convert a Null-terminated Ascii decimal string to a value of type UINTN. > + > + This function outputs a value of type UINTN by interpreting the contents of > + the Ascii string specified by String as a decimal number. The format of the > + input Ascii string String is: > + > + [spaces] [decimal digits]. > + > + The valid decimal digit character is in the range [0-9]. The function will > + ignore the pad space, which includes spaces or tab characters, before > + [decimal digits]. The running zero in the beginning of [decimal digits] will > + be ignored. Then, the function stops at the first character that is a not a > + valid decimal character or a Null-terminator, whichever one comes first. > + > + If String is NULL, then ASSERT(). > + If Data is NULL, then ASSERT(). > + If PcdMaximumAsciiStringLength is not zero, and String contains more than > + PcdMaximumAsciiStringLength Ascii characters, not including the > + Null-terminator, then ASSERT(). > + > + If String has no valid decimal digits in the above format, then 0 is stored > + at the location pointed to by Data. > + If the number represented by String exceeds the range defined by UINTN, > then > + MAX_UINTN is stored at the location pointed to by Data. > + > + If EndPointer is not NULL, a pointer to the character that stopped the scan > + is stored at the location pointed to by EndPointer. If String has no valid > + decimal digits right after the optional pad spaces, the value of String is > + stored at the location pointed to by EndPointer. > + > + @param String Pointer to a Null-terminated Ascii > string. > + @param EndPointer Pointer to character that stops scan. > + @param Data Pointer to the converted value. > + > + @retval RETURN_SUCCESS Value is translated from String. > + @retval RETURN_INVALID_PARAMETER If String is NULL. > + If Data is NULL. > + If PcdMaximumAsciiStringLength is not > zero, > + and String contains more than > + PcdMaximumAsciiStringLength Ascii > + characters, not including the > + Null-terminator. > + @retval RETURN_UNSUPPORTED If the number represented by String > exceeds > + the range defined by UINTN. > + > +**/ > +RETURN_STATUS > +EFIAPI > +AsciiStrDecimalToUintnS ( > + IN CONST CHAR8 *String, > + OUT CHAR8 **EndPointer, OPTIONAL > + OUT UINTN *Data > + ) > +{ > + // > + // 1. Neither String nor Data shall be a null pointer. > + // > + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), > RETURN_INVALID_PARAMETER); > + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), > RETURN_INVALID_PARAMETER); > + > + // > + // 2. The length of String shall not be greater than ASCII_RSIZE_MAX. > + // > + if (ASCII_RSIZE_MAX != 0) { > + SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, > ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); > + } > + > + if (EndPointer != NULL) { > + *EndPointer = (CHAR8 *) String; > + } > + > + // > + // Ignore the pad spaces (space or tab) > + // > + while ((*String == ' ') || (*String == '\t')) { > + String++; > + } > + > + // > + // Ignore leading Zeros after the spaces > + // > + while (*String == '0') { > + String++; > + } > + > + *Data = 0; > + > + while (InternalAsciiIsDecimalDigitCharacter (*String)) { > + // > + // If the number represented by String overflows according to the range > + // defined by UINTN, then MAX_UINTN is stored in *Data and > + // RETURN_UNSUPPORTED is returned. > + // > + if (*Data > ((MAX_UINTN - (*String - '0')) / 10)) { > + *Data = MAX_UINTN; > + if (EndPointer != NULL) { > + *EndPointer = (CHAR8 *) String; > + } > + return RETURN_UNSUPPORTED; > + } > + > + *Data = *Data * 10 + (*String - '0'); > + String++; > + } > + > + if (EndPointer != NULL) { > + *EndPointer = (CHAR8 *) String; > + } > + return RETURN_SUCCESS; > +} > + > +/** > + Convert a Null-terminated Ascii decimal string to a value of type UINT64. > + > + This function outputs a value of type UINT64 by interpreting the contents of > + the Ascii string specified by String as a decimal number. The format of the > + input Ascii string String is: > + > + [spaces] [decimal digits]. > + > + The valid decimal digit character is in the range [0-9]. The function will > + ignore the pad space, which includes spaces or tab characters, before > + [decimal digits]. The running zero in the beginning of [decimal digits] will > + be ignored. Then, the function stops at the first character that is a not a > + valid decimal character or a Null-terminator, whichever one comes first. > + > + If String is NULL, then ASSERT(). > + If Data is NULL, then ASSERT(). > + If PcdMaximumAsciiStringLength is not zero, and String contains more than > + PcdMaximumAsciiStringLength Ascii characters, not including the > + Null-terminator, then ASSERT(). > + > + If String has no valid decimal digits in the above format, then 0 is stored > + at the location pointed to by Data. > + If the number represented by String exceeds the range defined by UINT64, > then > + MAX_UINT64 is stored at the location pointed to by Data. > + > + If EndPointer is not NULL, a pointer to the character that stopped the scan > + is stored at the location pointed to by EndPointer. If String has no valid > + decimal digits right after the optional pad spaces, the value of String is > + stored at the location pointed to by EndPointer. > + > + @param String Pointer to a Null-terminated Ascii > string. > + @param EndPointer Pointer to character that stops scan. > + @param Data Pointer to the converted value. > + > + @retval RETURN_SUCCESS Value is translated from String. > + @retval RETURN_INVALID_PARAMETER If String is NULL. > + If Data is NULL. > + If PcdMaximumAsciiStringLength is not > zero, > + and String contains more than > + PcdMaximumAsciiStringLength Ascii > + characters, not including the > + Null-terminator. > + @retval RETURN_UNSUPPORTED If the number represented by String > exceeds > + the range defined by UINT64. > + > +**/ > +RETURN_STATUS > +EFIAPI > +AsciiStrDecimalToUint64S ( > + IN CONST CHAR8 *String, > + OUT CHAR8 **EndPointer, OPTIONAL > + OUT UINT64 *Data > + ) > +{ > + // > + // 1. Neither String nor Data shall be a null pointer. > + // > + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), > RETURN_INVALID_PARAMETER); > + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), > RETURN_INVALID_PARAMETER); > + > + // > + // 2. The length of String shall not be greater than ASCII_RSIZE_MAX. > + // > + if (ASCII_RSIZE_MAX != 0) { > + SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, > ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); > + } > + > + if (EndPointer != NULL) { > + *EndPointer = (CHAR8 *) String; > + } > + > + // > + // Ignore the pad spaces (space or tab) > + // > + while ((*String == ' ') || (*String == '\t')) { > + String++; > + } > + > + // > + // Ignore leading Zeros after the spaces > + // > + while (*String == '0') { > + String++; > + } > + > + *Data = 0; > + > + while (InternalAsciiIsDecimalDigitCharacter (*String)) { > + // > + // If the number represented by String overflows according to the range > + // defined by UINT64, then MAX_UINT64 is stored in *Data and > + // RETURN_UNSUPPORTED is returned. > + // > + if (*Data > DivU64x32 (MAX_UINT64 - (*String - '0'), 10)) { > + *Data = MAX_UINT64; > + if (EndPointer != NULL) { > + *EndPointer = (CHAR8 *) String; > + } > + return RETURN_UNSUPPORTED; > + } > + > + *Data = MultU64x32 (*Data, 10) + (*String - '0'); > + String++; > + } > + > + if (EndPointer != NULL) { > + *EndPointer = (CHAR8 *) String; > + } > + return RETURN_SUCCESS; > +} > + > +/** > + Convert a Null-terminated Ascii hexadecimal string to a value of type UINTN. > + > + This function outputs a value of type UINTN by interpreting the contents of > + the Ascii string specified by String as a hexadecimal number. The format of > + the input Ascii string String is: > + > + [spaces][zeros][x][hexadecimal digits]. > + > + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. > + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If > + "x" appears in the input string, it must be prefixed with at least one 0. The > + function will ignore the pad space, which includes spaces or tab characters, > + before [zeros], [x] or [hexadecimal digits]. The running zero before [x] or > + [hexadecimal digits] will be ignored. Then, the decoding starts after [x] or > + the first valid hexadecimal digit. Then, the function stops at the first > + character that is a not a valid hexadecimal character or Null-terminator, > + whichever on comes first. > + > + If String is NULL, then ASSERT(). > + If Data is NULL, then ASSERT(). > + If PcdMaximumAsciiStringLength is not zero, and String contains more than > + PcdMaximumAsciiStringLength Ascii characters, not including the > + Null-terminator, then ASSERT(). > + > + If String has no valid hexadecimal digits in the above format, then 0 is > + stored at the location pointed to by Data. > + If the number represented by String exceeds the range defined by UINTN, > then > + MAX_UINTN is stored at the location pointed to by Data. > + > + If EndPointer is not NULL, a pointer to the character that stopped the scan > + is stored at the location pointed to by EndPointer. If String has no valid > + hexadecimal digits right after the optional pad spaces, the value of String > + is stored at the location pointed to by EndPointer. > + > + @param String Pointer to a Null-terminated Ascii > string. > + @param EndPointer Pointer to character that stops scan. > + @param Data Pointer to the converted value. > + > + @retval RETURN_SUCCESS Value is translated from String. > + @retval RETURN_INVALID_PARAMETER If String is NULL. > + If Data is NULL. > + If PcdMaximumAsciiStringLength is not > zero, > + and String contains more than > + PcdMaximumAsciiStringLength Ascii > + characters, not including the > + Null-terminator. > + @retval RETURN_UNSUPPORTED If the number represented by String > exceeds > + the range defined by UINTN. > + > +**/ > +RETURN_STATUS > +EFIAPI > +AsciiStrHexToUintnS ( > + IN CONST CHAR8 *String, > + OUT CHAR8 **EndPointer, OPTIONAL > + OUT UINTN *Data > + ) > +{ > + // > + // 1. Neither String nor Data shall be a null pointer. > + // > + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), > RETURN_INVALID_PARAMETER); > + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), > RETURN_INVALID_PARAMETER); > + > + // > + // 2. The length of String shall not be greater than ASCII_RSIZE_MAX. > + // > + if (ASCII_RSIZE_MAX != 0) { > + SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, > ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); > + } > + > + if (EndPointer != NULL) { > + *EndPointer = (CHAR8 *) String; > + } > + > + // > + // Ignore the pad spaces (space or tab) > + // > + while ((*String == ' ') || (*String == '\t')) { > + String++; > + } > + > + // > + // Ignore leading Zeros after the spaces > + // > + while (*String == '0') { > + String++; > + } > + > + if (InternalBaseLibAsciiToUpper (*String) == 'X') { > + if (*(String - 1) != '0') { > + *Data = 0; > + return RETURN_SUCCESS; > + } > + // > + // Skip the 'X' > + // > + String++; > + } > + > + *Data = 0; > + > + while (InternalAsciiIsHexaDecimalDigitCharacter (*String)) { > + // > + // If the number represented by String overflows according to the range > + // defined by UINTN, then MAX_UINTN is stored in *Data and > + // RETURN_UNSUPPORTED is returned. > + // > + if (*Data > ((MAX_UINTN - InternalAsciiHexCharToUintn (*String)) >> 4)) { > + *Data = MAX_UINTN; > + if (EndPointer != NULL) { > + *EndPointer = (CHAR8 *) String; > + } > + return RETURN_UNSUPPORTED; > + } > + > + *Data = (*Data << 4) + InternalAsciiHexCharToUintn (*String); > + String++; > + } > + > + if (EndPointer != NULL) { > + *EndPointer = (CHAR8 *) String; > + } > + return RETURN_SUCCESS; > +} > + > +/** > + Convert a Null-terminated Ascii hexadecimal string to a value of type UINT64. > + > + This function outputs a value of type UINT64 by interpreting the contents of > + the Ascii string specified by String as a hexadecimal number. The format of > + the input Ascii string String is: > + > + [spaces][zeros][x][hexadecimal digits]. > + > + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. > + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If > + "x" appears in the input string, it must be prefixed with at least one 0. The > + function will ignore the pad space, which includes spaces or tab characters, > + before [zeros], [x] or [hexadecimal digits]. The running zero before [x] or > + [hexadecimal digits] will be ignored. Then, the decoding starts after [x] or > + the first valid hexadecimal digit. Then, the function stops at the first > + character that is a not a valid hexadecimal character or Null-terminator, > + whichever on comes first. > + > + If String is NULL, then ASSERT(). > + If Data is NULL, then ASSERT(). > + If PcdMaximumAsciiStringLength is not zero, and String contains more than > + PcdMaximumAsciiStringLength Ascii characters, not including the > + Null-terminator, then ASSERT(). > + > + If String has no valid hexadecimal digits in the above format, then 0 is > + stored at the location pointed to by Data. > + If the number represented by String exceeds the range defined by UINT64, > then > + MAX_UINT64 is stored at the location pointed to by Data. > + > + If EndPointer is not NULL, a pointer to the character that stopped the scan > + is stored at the location pointed to by EndPointer. If String has no valid > + hexadecimal digits right after the optional pad spaces, the value of String > + is stored at the location pointed to by EndPointer. > + > + @param String Pointer to a Null-terminated Ascii > string. > + @param EndPointer Pointer to character that stops scan. > + @param Data Pointer to the converted value. > + > + @retval RETURN_SUCCESS Value is translated from String. > + @retval RETURN_INVALID_PARAMETER If String is NULL. > + If Data is NULL. > + If PcdMaximumAsciiStringLength is not > zero, > + and String contains more than > + PcdMaximumAsciiStringLength Ascii > + characters, not including the > + Null-terminator. > + @retval RETURN_UNSUPPORTED If the number represented by String > exceeds > + the range defined by UINT64. > + > +**/ > +RETURN_STATUS > +EFIAPI > +AsciiStrHexToUint64S ( > + IN CONST CHAR8 *String, > + OUT CHAR8 **EndPointer, OPTIONAL > + OUT UINT64 *Data > + ) > +{ > + // > + // 1. Neither String nor Data shall be a null pointer. > + // > + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), > RETURN_INVALID_PARAMETER); > + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), > RETURN_INVALID_PARAMETER); > + > + // > + // 2. The length of String shall not be greater than ASCII_RSIZE_MAX. > + // > + if (ASCII_RSIZE_MAX != 0) { > + SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, > ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); > + } > + > + if (EndPointer != NULL) { > + *EndPointer = (CHAR8 *) String; > + } > + > + // > + // Ignore the pad spaces (space or tab) > + // > + while ((*String == ' ') || (*String == '\t')) { > + String++; > + } > + > + // > + // Ignore leading Zeros after the spaces > + // > + while (*String == '0') { > + String++; > + } > + > + if (InternalBaseLibAsciiToUpper (*String) == 'X') { > + if (*(String - 1) != '0') { > + *Data = 0; > + return RETURN_SUCCESS; > + } > + // > + // Skip the 'X' > + // > + String++; > + } > + > + *Data = 0; > + > + while (InternalAsciiIsHexaDecimalDigitCharacter (*String)) { > + // > + // If the number represented by String overflows according to the range > + // defined by UINT64, then MAX_UINT64 is stored in *Data and > + // RETURN_UNSUPPORTED is returned. > + // > + if (*Data > RShiftU64 (MAX_UINT64 - InternalAsciiHexCharToUintn (*String), > 4)) { > + *Data = MAX_UINT64; > + if (EndPointer != NULL) { > + *EndPointer = (CHAR8 *) String; > + } > + return RETURN_UNSUPPORTED; > + } > + > + *Data = LShiftU64 (*Data, 4) + InternalAsciiHexCharToUintn (*String); > + String++; > + } > + > + if (EndPointer != NULL) { > + *EndPointer = (CHAR8 *) String; > + } > + return RETURN_SUCCESS; > +} > + > +/** > Convert a Null-terminated Unicode string to a Null-terminated > ASCII string. > > -- > 1.9.5.msysgit.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/4] MdePkg/BaseLib: Enhance the return value for string to uint functions 2017-01-04 11:22 [PATCH 0/4] Add and refine sting APIs in MdePkg/BaseLib Hao Wu 2017-01-04 11:22 ` [PATCH 1/4] MdePkg/BaseLib: Add safe string functions [Ascii]StrnSizeS Hao Wu 2017-01-04 11:22 ` [PATCH 2/4] MdePkg/BaseLib: Add safe string functions that convert str to value Hao Wu @ 2017-01-04 11:22 ` Hao Wu 2017-01-09 2:03 ` Yao, Jiewen 2017-01-04 11:22 ` [PATCH 4/4] MdePkg/BaseLib: Add safe string functions [U|A]StrnTo[A|U]StrS Hao Wu 3 siblings, 1 reply; 9+ messages in thread From: Hao Wu @ 2017-01-04 11:22 UTC (permalink / raw) To: edk2-devel; +Cc: Hao Wu, Jiewen Yao, Jiaxin Wu, Liming Gao, Michael Kinney For the following 8 APIs in MdePkg/BaseLib: [Ascii]StrDecimalToUintn [Ascii]StrDecimalToUint64 [Ascii]StrHexToUintn [Ascii]StrHexToUint64 They will ASSERT for DEBUG build when the input string exceeds the range of UINTN/UINT64. However, for RELEASE build, incorrect value will be returned. This commit refines those APIs to direcly call their enhanced counterparts (with trailing 'S' in API names) so as to remove those exceed-range ASSERT checks and to make those APIs to return MAX_UINTN/MAX_UINT64 instead. Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Jiaxin Wu <jiaxin.wu@intel.com> Cc: Liming Gao <liming.gao@intel.com> Cc: Michael Kinney <michael.d.kinney@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Hao Wu <hao.a.wu@intel.com> --- MdePkg/Include/Library/BaseLib.h | 16 +- MdePkg/Library/BaseLib/String.c | 334 ++------------------------------------- 2 files changed, 25 insertions(+), 325 deletions(-) diff --git a/MdePkg/Include/Library/BaseLib.h b/MdePkg/Include/Library/BaseLib.h index 52011ee..abea7b6 100644 --- a/MdePkg/Include/Library/BaseLib.h +++ b/MdePkg/Include/Library/BaseLib.h @@ -1395,7 +1395,7 @@ StrStr ( If String has no pad spaces or valid decimal digits, then 0 is returned. If the number represented by String overflows according - to the range defined by UINTN, then ASSERT(). + to the range defined by UINTN, then MAX_UINTN is returned. If PcdMaximumUnicodeStringLength is not zero, and String contains more than PcdMaximumUnicodeStringLength Unicode characters not including @@ -1435,7 +1435,7 @@ StrDecimalToUintn ( If String has no pad spaces or valid decimal digits, then 0 is returned. If the number represented by String overflows according - to the range defined by UINT64, then ASSERT(). + to the range defined by UINT64, then MAX_UINT64 is returned. If PcdMaximumUnicodeStringLength is not zero, and String contains more than PcdMaximumUnicodeStringLength Unicode characters not including @@ -1477,7 +1477,7 @@ StrDecimalToUint64 ( If String has no leading pad spaces, leading zeros or valid hexadecimal digits, then zero is returned. If the number represented by String overflows according to the range defined by - UINTN, then ASSERT(). + UINTN, then MAX_UINTN is returned. If PcdMaximumUnicodeStringLength is not zero, and String contains more than PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, @@ -1519,7 +1519,7 @@ StrHexToUintn ( If String has no leading pad spaces, leading zeros or valid hexadecimal digits, then zero is returned. If the number represented by String overflows according to the range defined by - UINT64, then ASSERT(). + UINT64, then MAX_UINT64 is returned. If PcdMaximumUnicodeStringLength is not zero, and String contains more than PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, @@ -1997,7 +1997,7 @@ AsciiStrStr ( If String has only pad spaces, then 0 is returned. If String has no pad spaces or valid decimal digits, then 0 is returned. If the number represented by String overflows according to the range defined by - UINTN, then ASSERT(). + UINTN, then MAX_UINTN is returned. If String is NULL, then ASSERT(). If PcdMaximumAsciiStringLength is not zero, and String contains more than PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, @@ -2034,7 +2034,7 @@ AsciiStrDecimalToUintn ( If String has only pad spaces, then 0 is returned. If String has no pad spaces or valid decimal digits, then 0 is returned. If the number represented by String overflows according to the range defined by - UINT64, then ASSERT(). + UINT64, then MAX_UINT64 is returned. If String is NULL, then ASSERT(). If PcdMaximumAsciiStringLength is not zero, and String contains more than PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, @@ -2075,7 +2075,7 @@ AsciiStrDecimalToUint64 ( 0 is returned. If the number represented by String overflows according to the range defined by UINTN, - then ASSERT(). + then MAX_UINTN is returned. If String is NULL, then ASSERT(). If PcdMaximumAsciiStringLength is not zero, and String contains more than PcdMaximumAsciiStringLength ASCII characters not including @@ -2116,7 +2116,7 @@ AsciiStrHexToUintn ( 0 is returned. If the number represented by String overflows according to the range defined by UINT64, - then ASSERT(). + then MAX_UINT64 is returned. If String is NULL, then ASSERT(). If PcdMaximumAsciiStringLength is not zero, and String contains more than PcdMaximumAsciiStringLength ASCII characters not including diff --git a/MdePkg/Library/BaseLib/String.c b/MdePkg/Library/BaseLib/String.c index fa96d1c..e84bf50 100644 --- a/MdePkg/Library/BaseLib/String.c +++ b/MdePkg/Library/BaseLib/String.c @@ -1,7 +1,7 @@ /** @file Unicode and ASCII string primitives. - Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR> + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR> This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -638,7 +638,7 @@ InternalIsHexaDecimalDigitCharacter ( If String has no pad spaces or valid decimal digits, then 0 is returned. If the number represented by String overflows according - to the range defined by UINTN, then ASSERT(). + to the range defined by UINTN, then MAX_UINTN is returned. If PcdMaximumUnicodeStringLength is not zero, and String contains more than PcdMaximumUnicodeStringLength Unicode characters, not including @@ -656,40 +656,8 @@ StrDecimalToUintn ( ) { UINTN Result; - - // - // ASSERT String is less long than PcdMaximumUnicodeStringLength. - // Length tests are performed inside StrLen(). - // - ASSERT (StrSize (String) != 0); - - // - // Ignore the pad spaces (space or tab) - // - while ((*String == L' ') || (*String == L'\t')) { - String++; - } - - // - // Ignore leading Zeros after the spaces - // - while (*String == L'0') { - String++; - } - - Result = 0; - - while (InternalIsDecimalDigitCharacter (*String)) { - // - // If the number represented by String overflows according - // to the range defined by UINTN, then ASSERT(). - // - ASSERT (Result <= ((((UINTN) ~0) - (*String - L'0')) / 10)); - Result = Result * 10 + (*String - L'0'); - String++; - } - + StrDecimalToUintnS (String, (CHAR16 **) NULL, &Result); return Result; } @@ -717,7 +685,7 @@ StrDecimalToUintn ( If String has no pad spaces or valid decimal digits, then 0 is returned. If the number represented by String overflows according - to the range defined by UINT64, then ASSERT(). + to the range defined by UINT64, then MAX_UINT64 is returned. If PcdMaximumUnicodeStringLength is not zero, and String contains more than PcdMaximumUnicodeStringLength Unicode characters, not including @@ -736,39 +704,7 @@ StrDecimalToUint64 ( { UINT64 Result; - // - // ASSERT String is less long than PcdMaximumUnicodeStringLength. - // Length tests are performed inside StrLen(). - // - ASSERT (StrSize (String) != 0); - - // - // Ignore the pad spaces (space or tab) - // - while ((*String == L' ') || (*String == L'\t')) { - String++; - } - - // - // Ignore leading Zeros after the spaces - // - while (*String == L'0') { - String++; - } - - Result = 0; - - while (InternalIsDecimalDigitCharacter (*String)) { - // - // If the number represented by String overflows according - // to the range defined by UINTN, then ASSERT(). - // - ASSERT (Result <= DivU64x32 (((UINT64) ~0) - (*String - L'0') , 10)); - - Result = MultU64x32 (Result, 10) + (*String - L'0'); - String++; - } - + StrDecimalToUint64S (String, (CHAR16 **) NULL, &Result); return Result; } @@ -796,7 +732,7 @@ StrDecimalToUint64 ( If String has no leading pad spaces, leading zeros or valid hexadecimal digits, then zero is returned. If the number represented by String overflows according to the range defined by - UINTN, then ASSERT(). + UINTN, then MAX_UINTN is returned. If PcdMaximumUnicodeStringLength is not zero, and String contains more than PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, @@ -815,49 +751,7 @@ StrHexToUintn ( { UINTN Result; - // - // ASSERT String is less long than PcdMaximumUnicodeStringLength. - // Length tests are performed inside StrLen(). - // - ASSERT (StrSize (String) != 0); - - // - // Ignore the pad spaces (space or tab) - // - while ((*String == L' ') || (*String == L'\t')) { - String++; - } - - // - // Ignore leading Zeros after the spaces - // - while (*String == L'0') { - String++; - } - - if (InternalCharToUpper (*String) == L'X') { - if (*(String - 1) != L'0') { - return 0; - } - // - // Skip the 'X' - // - String++; - } - - Result = 0; - - while (InternalIsHexaDecimalDigitCharacter (*String)) { - // - // If the Hex Number represented by String overflows according - // to the range defined by UINTN, then ASSERT(). - // - ASSERT (Result <= ((((UINTN) ~0) - InternalHexCharToUintn (*String)) >> 4)); - - Result = (Result << 4) + InternalHexCharToUintn (*String); - String++; - } - + StrHexToUintnS (String, (CHAR16 **) NULL, &Result); return Result; } @@ -886,7 +780,7 @@ StrHexToUintn ( If String has no leading pad spaces, leading zeros or valid hexadecimal digits, then zero is returned. If the number represented by String overflows according to the range defined by - UINT64, then ASSERT(). + UINT64, then MAX_UINT64 is returned. If PcdMaximumUnicodeStringLength is not zero, and String contains more than PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, @@ -905,51 +799,7 @@ StrHexToUint64 ( { UINT64 Result; - // - // ASSERT String is less long than PcdMaximumUnicodeStringLength. - // Length tests are performed inside StrLen(). - // - ASSERT (StrSize (String) != 0); - - // - // Ignore the pad spaces (space or tab) - // - while ((*String == L' ') || (*String == L'\t')) { - String++; - } - - // - // Ignore leading Zeros after the spaces - // - while (*String == L'0') { - String++; - } - - if (InternalCharToUpper (*String) == L'X') { - ASSERT (*(String - 1) == L'0'); - if (*(String - 1) != L'0') { - return 0; - } - // - // Skip the 'X' - // - String++; - } - - Result = 0; - - while (InternalIsHexaDecimalDigitCharacter (*String)) { - // - // If the Hex Number represented by String overflows according - // to the range defined by UINTN, then ASSERT(). - // - ASSERT (Result <= RShiftU64 (((UINT64) ~0) - InternalHexCharToUintn (*String) , 4)); - - Result = LShiftU64 (Result, 4); - Result = Result + InternalHexCharToUintn (*String); - String++; - } - + StrHexToUint64S (String, (CHAR16 **) NULL, &Result); return Result; } @@ -1681,7 +1531,7 @@ AsciiStrStr ( If String has only pad spaces, then 0 is returned. If String has no pad spaces or valid decimal digits, then 0 is returned. If the number represented by String overflows according to the range defined by - UINTN, then ASSERT(). + UINTN, then MAX_UINTN is returned. If String is NULL, then ASSERT(). If PcdMaximumAsciiStringLength is not zero, and String contains more than PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, @@ -1700,38 +1550,7 @@ AsciiStrDecimalToUintn ( { UINTN Result; - // - // ASSERT Strings is less long than PcdMaximumAsciiStringLength - // - ASSERT (AsciiStrSize (String) != 0); - - // - // Ignore the pad spaces (space or tab) - // - while ((*String == ' ') || (*String == '\t' )) { - String++; - } - - // - // Ignore leading Zeros after the spaces - // - while (*String == '0') { - String++; - } - - Result = 0; - - while (InternalAsciiIsDecimalDigitCharacter (*String)) { - // - // If the number represented by String overflows according - // to the range defined by UINTN, then ASSERT(). - // - ASSERT (Result <= ((((UINTN) ~0) - (*String - L'0')) / 10)); - - Result = Result * 10 + (*String - '0'); - String++; - } - + AsciiStrDecimalToUintnS (String, (CHAR8 **) NULL, &Result); return Result; } @@ -1755,7 +1574,7 @@ AsciiStrDecimalToUintn ( If String has only pad spaces, then 0 is returned. If String has no pad spaces or valid decimal digits, then 0 is returned. If the number represented by String overflows according to the range defined by - UINT64, then ASSERT(). + UINT64, then MAX_UINT64 is returned. If String is NULL, then ASSERT(). If PcdMaximumAsciiStringLength is not zero, and String contains more than PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, @@ -1774,38 +1593,7 @@ AsciiStrDecimalToUint64 ( { UINT64 Result; - // - // ASSERT Strings is less long than PcdMaximumAsciiStringLength - // - ASSERT (AsciiStrSize (String) != 0); - - // - // Ignore the pad spaces (space or tab) - // - while ((*String == ' ') || (*String == '\t' )) { - String++; - } - - // - // Ignore leading Zeros after the spaces - // - while (*String == '0') { - String++; - } - - Result = 0; - - while (InternalAsciiIsDecimalDigitCharacter (*String)) { - // - // If the number represented by String overflows according - // to the range defined by UINTN, then ASSERT(). - // - ASSERT (Result <= DivU64x32 (((UINT64) ~0) - (*String - L'0') , 10)); - - Result = MultU64x32 (Result, 10) + (*String - '0'); - String++; - } - + AsciiStrDecimalToUint64S (String, (CHAR8 **) NULL, &Result); return Result; } @@ -1832,7 +1620,7 @@ AsciiStrDecimalToUint64 ( 0 is returned. If the number represented by String overflows according to the range defined by UINTN, - then ASSERT(). + then MAX_UINTN is returned. If String is NULL, then ASSERT(). If PcdMaximumAsciiStringLength is not zero, and String contains more than PcdMaximumAsciiStringLength ASCII characters not including @@ -1851,49 +1639,7 @@ AsciiStrHexToUintn ( { UINTN Result; - // - // ASSERT Strings is less long than PcdMaximumAsciiStringLength - // - ASSERT (AsciiStrSize (String) != 0); - - // - // Ignore the pad spaces (space or tab) - // - while ((*String == ' ') || (*String == '\t' )) { - String++; - } - - // - // Ignore leading Zeros after the spaces - // - while (*String == '0') { - String++; - } - - if (InternalBaseLibAsciiToUpper (*String) == 'X') { - ASSERT (*(String - 1) == '0'); - if (*(String - 1) != '0') { - return 0; - } - // - // Skip the 'X' - // - String++; - } - - Result = 0; - - while (InternalAsciiIsHexaDecimalDigitCharacter (*String)) { - // - // If the Hex Number represented by String overflows according - // to the range defined by UINTN, then ASSERT(). - // - ASSERT (Result <= ((((UINTN) ~0) - InternalHexCharToUintn (*String)) >> 4)); - - Result = (Result << 4) + InternalAsciiHexCharToUintn (*String); - String++; - } - + AsciiStrHexToUintnS (String, (CHAR8 **) NULL, &Result); return Result; } @@ -1921,7 +1667,7 @@ AsciiStrHexToUintn ( 0 is returned. If the number represented by String overflows according to the range defined by UINT64, - then ASSERT(). + then MAX_UINT64 is returned. If String is NULL, then ASSERT(). If PcdMaximumAsciiStringLength is not zero, and String contains more than PcdMaximumAsciiStringLength ASCII characters not including @@ -1940,53 +1686,7 @@ AsciiStrHexToUint64 ( { UINT64 Result; - // - // ASSERT Strings is less long than PcdMaximumAsciiStringLength - // - ASSERT (AsciiStrSize (String) != 0); - - // - // Ignore the pad spaces (space or tab) and leading Zeros - // - // - // Ignore the pad spaces (space or tab) - // - while ((*String == ' ') || (*String == '\t' )) { - String++; - } - - // - // Ignore leading Zeros after the spaces - // - while (*String == '0') { - String++; - } - - if (InternalBaseLibAsciiToUpper (*String) == 'X') { - ASSERT (*(String - 1) == '0'); - if (*(String - 1) != '0') { - return 0; - } - // - // Skip the 'X' - // - String++; - } - - Result = 0; - - while (InternalAsciiIsHexaDecimalDigitCharacter (*String)) { - // - // If the Hex Number represented by String overflows according - // to the range defined by UINTN, then ASSERT(). - // - ASSERT (Result <= RShiftU64 (((UINT64) ~0) - InternalHexCharToUintn (*String) , 4)); - - Result = LShiftU64 (Result, 4); - Result = Result + InternalAsciiHexCharToUintn (*String); - String++; - } - + AsciiStrHexToUint64S (String, (CHAR8 **) NULL, &Result); return Result; } -- 1.9.5.msysgit.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 3/4] MdePkg/BaseLib: Enhance the return value for string to uint functions 2017-01-04 11:22 ` [PATCH 3/4] MdePkg/BaseLib: Enhance the return value for string to uint functions Hao Wu @ 2017-01-09 2:03 ` Yao, Jiewen 0 siblings, 0 replies; 9+ messages in thread From: Yao, Jiewen @ 2017-01-09 2:03 UTC (permalink / raw) To: Wu, Hao A, edk2-devel@lists.01.org Cc: Wu, Jiaxin, Gao, Liming, Kinney, Michael D Reviewed-by: Jiewen.yao@Intel.com > -----Original Message----- > From: Wu, Hao A > Sent: Wednesday, January 4, 2017 7:23 PM > To: edk2-devel@lists.01.org > Cc: Wu, Hao A <hao.a.wu@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wu, > Jiaxin <jiaxin.wu@intel.com>; Gao, Liming <liming.gao@intel.com>; Kinney, > Michael D <michael.d.kinney@intel.com> > Subject: [PATCH 3/4] MdePkg/BaseLib: Enhance the return value for string to uint > functions > > For the following 8 APIs in MdePkg/BaseLib: > [Ascii]StrDecimalToUintn > [Ascii]StrDecimalToUint64 > [Ascii]StrHexToUintn > [Ascii]StrHexToUint64 > > They will ASSERT for DEBUG build when the input string exceeds the range > of UINTN/UINT64. However, for RELEASE build, incorrect value will be > returned. > > This commit refines those APIs to direcly call their enhanced counterparts > (with trailing 'S' in API names) so as to remove those exceed-range ASSERT > checks and to make those APIs to return MAX_UINTN/MAX_UINT64 instead. > > Cc: Jiewen Yao <jiewen.yao@intel.com> > Cc: Jiaxin Wu <jiaxin.wu@intel.com> > Cc: Liming Gao <liming.gao@intel.com> > Cc: Michael Kinney <michael.d.kinney@intel.com> > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Hao Wu <hao.a.wu@intel.com> > --- > MdePkg/Include/Library/BaseLib.h | 16 +- > MdePkg/Library/BaseLib/String.c | 334 ++------------------------------------- > 2 files changed, 25 insertions(+), 325 deletions(-) > > diff --git a/MdePkg/Include/Library/BaseLib.h > b/MdePkg/Include/Library/BaseLib.h > index 52011ee..abea7b6 100644 > --- a/MdePkg/Include/Library/BaseLib.h > +++ b/MdePkg/Include/Library/BaseLib.h > @@ -1395,7 +1395,7 @@ StrStr ( > If String has no pad spaces or valid decimal digits, > then 0 is returned. > If the number represented by String overflows according > - to the range defined by UINTN, then ASSERT(). > + to the range defined by UINTN, then MAX_UINTN is returned. > > If PcdMaximumUnicodeStringLength is not zero, and String contains > more than PcdMaximumUnicodeStringLength Unicode characters not > including > @@ -1435,7 +1435,7 @@ StrDecimalToUintn ( > If String has no pad spaces or valid decimal digits, > then 0 is returned. > If the number represented by String overflows according > - to the range defined by UINT64, then ASSERT(). > + to the range defined by UINT64, then MAX_UINT64 is returned. > > If PcdMaximumUnicodeStringLength is not zero, and String contains > more than PcdMaximumUnicodeStringLength Unicode characters not > including > @@ -1477,7 +1477,7 @@ StrDecimalToUint64 ( > If String has no leading pad spaces, leading zeros or valid hexadecimal digits, > then zero is returned. > If the number represented by String overflows according to the range > defined by > - UINTN, then ASSERT(). > + UINTN, then MAX_UINTN is returned. > > If PcdMaximumUnicodeStringLength is not zero, and String contains more > than > PcdMaximumUnicodeStringLength Unicode characters not including the > Null-terminator, > @@ -1519,7 +1519,7 @@ StrHexToUintn ( > If String has no leading pad spaces, leading zeros or valid hexadecimal digits, > then zero is returned. > If the number represented by String overflows according to the range > defined by > - UINT64, then ASSERT(). > + UINT64, then MAX_UINT64 is returned. > > If PcdMaximumUnicodeStringLength is not zero, and String contains more > than > PcdMaximumUnicodeStringLength Unicode characters not including the > Null-terminator, > @@ -1997,7 +1997,7 @@ AsciiStrStr ( > If String has only pad spaces, then 0 is returned. > If String has no pad spaces or valid decimal digits, then 0 is returned. > If the number represented by String overflows according to the range > defined by > - UINTN, then ASSERT(). > + UINTN, then MAX_UINTN is returned. > If String is NULL, then ASSERT(). > If PcdMaximumAsciiStringLength is not zero, and String contains more than > PcdMaximumAsciiStringLength ASCII characters not including the > Null-terminator, > @@ -2034,7 +2034,7 @@ AsciiStrDecimalToUintn ( > If String has only pad spaces, then 0 is returned. > If String has no pad spaces or valid decimal digits, then 0 is returned. > If the number represented by String overflows according to the range > defined by > - UINT64, then ASSERT(). > + UINT64, then MAX_UINT64 is returned. > If String is NULL, then ASSERT(). > If PcdMaximumAsciiStringLength is not zero, and String contains more than > PcdMaximumAsciiStringLength ASCII characters not including the > Null-terminator, > @@ -2075,7 +2075,7 @@ AsciiStrDecimalToUint64 ( > 0 is returned. > > If the number represented by String overflows according to the range > defined by UINTN, > - then ASSERT(). > + then MAX_UINTN is returned. > If String is NULL, then ASSERT(). > If PcdMaximumAsciiStringLength is not zero, > and String contains more than PcdMaximumAsciiStringLength ASCII characters > not including > @@ -2116,7 +2116,7 @@ AsciiStrHexToUintn ( > 0 is returned. > > If the number represented by String overflows according to the range > defined by UINT64, > - then ASSERT(). > + then MAX_UINT64 is returned. > If String is NULL, then ASSERT(). > If PcdMaximumAsciiStringLength is not zero, > and String contains more than PcdMaximumAsciiStringLength ASCII characters > not including > diff --git a/MdePkg/Library/BaseLib/String.c b/MdePkg/Library/BaseLib/String.c > index fa96d1c..e84bf50 100644 > --- a/MdePkg/Library/BaseLib/String.c > +++ b/MdePkg/Library/BaseLib/String.c > @@ -1,7 +1,7 @@ > /** @file > Unicode and ASCII string primitives. > > - Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR> > + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR> > This program and the accompanying materials > are licensed and made available under the terms and conditions of the BSD > License > which accompanies this distribution. The full text of the license may be > found at > @@ -638,7 +638,7 @@ InternalIsHexaDecimalDigitCharacter ( > If String has no pad spaces or valid decimal digits, > then 0 is returned. > If the number represented by String overflows according > - to the range defined by UINTN, then ASSERT(). > + to the range defined by UINTN, then MAX_UINTN is returned. > > If PcdMaximumUnicodeStringLength is not zero, and String contains > more than PcdMaximumUnicodeStringLength Unicode characters, not > including > @@ -656,40 +656,8 @@ StrDecimalToUintn ( > ) > { > UINTN Result; > - > - // > - // ASSERT String is less long than PcdMaximumUnicodeStringLength. > - // Length tests are performed inside StrLen(). > - // > - ASSERT (StrSize (String) != 0); > - > - // > - // Ignore the pad spaces (space or tab) > - // > - while ((*String == L' ') || (*String == L'\t')) { > - String++; > - } > - > - // > - // Ignore leading Zeros after the spaces > - // > - while (*String == L'0') { > - String++; > - } > - > - Result = 0; > - > - while (InternalIsDecimalDigitCharacter (*String)) { > - // > - // If the number represented by String overflows according > - // to the range defined by UINTN, then ASSERT(). > - // > - ASSERT (Result <= ((((UINTN) ~0) - (*String - L'0')) / 10)); > > - Result = Result * 10 + (*String - L'0'); > - String++; > - } > - > + StrDecimalToUintnS (String, (CHAR16 **) NULL, &Result); > return Result; > } > > @@ -717,7 +685,7 @@ StrDecimalToUintn ( > If String has no pad spaces or valid decimal digits, > then 0 is returned. > If the number represented by String overflows according > - to the range defined by UINT64, then ASSERT(). > + to the range defined by UINT64, then MAX_UINT64 is returned. > > If PcdMaximumUnicodeStringLength is not zero, and String contains > more than PcdMaximumUnicodeStringLength Unicode characters, not > including > @@ -736,39 +704,7 @@ StrDecimalToUint64 ( > { > UINT64 Result; > > - // > - // ASSERT String is less long than PcdMaximumUnicodeStringLength. > - // Length tests are performed inside StrLen(). > - // > - ASSERT (StrSize (String) != 0); > - > - // > - // Ignore the pad spaces (space or tab) > - // > - while ((*String == L' ') || (*String == L'\t')) { > - String++; > - } > - > - // > - // Ignore leading Zeros after the spaces > - // > - while (*String == L'0') { > - String++; > - } > - > - Result = 0; > - > - while (InternalIsDecimalDigitCharacter (*String)) { > - // > - // If the number represented by String overflows according > - // to the range defined by UINTN, then ASSERT(). > - // > - ASSERT (Result <= DivU64x32 (((UINT64) ~0) - (*String - L'0') , 10)); > - > - Result = MultU64x32 (Result, 10) + (*String - L'0'); > - String++; > - } > - > + StrDecimalToUint64S (String, (CHAR16 **) NULL, &Result); > return Result; > } > > @@ -796,7 +732,7 @@ StrDecimalToUint64 ( > If String has no leading pad spaces, leading zeros or valid hexadecimal digits, > then zero is returned. > If the number represented by String overflows according to the range > defined by > - UINTN, then ASSERT(). > + UINTN, then MAX_UINTN is returned. > > If PcdMaximumUnicodeStringLength is not zero, and String contains more > than > PcdMaximumUnicodeStringLength Unicode characters, not including the > Null-terminator, > @@ -815,49 +751,7 @@ StrHexToUintn ( > { > UINTN Result; > > - // > - // ASSERT String is less long than PcdMaximumUnicodeStringLength. > - // Length tests are performed inside StrLen(). > - // > - ASSERT (StrSize (String) != 0); > - > - // > - // Ignore the pad spaces (space or tab) > - // > - while ((*String == L' ') || (*String == L'\t')) { > - String++; > - } > - > - // > - // Ignore leading Zeros after the spaces > - // > - while (*String == L'0') { > - String++; > - } > - > - if (InternalCharToUpper (*String) == L'X') { > - if (*(String - 1) != L'0') { > - return 0; > - } > - // > - // Skip the 'X' > - // > - String++; > - } > - > - Result = 0; > - > - while (InternalIsHexaDecimalDigitCharacter (*String)) { > - // > - // If the Hex Number represented by String overflows according > - // to the range defined by UINTN, then ASSERT(). > - // > - ASSERT (Result <= ((((UINTN) ~0) - InternalHexCharToUintn (*String)) >> > 4)); > - > - Result = (Result << 4) + InternalHexCharToUintn (*String); > - String++; > - } > - > + StrHexToUintnS (String, (CHAR16 **) NULL, &Result); > return Result; > } > > @@ -886,7 +780,7 @@ StrHexToUintn ( > If String has no leading pad spaces, leading zeros or valid hexadecimal digits, > then zero is returned. > If the number represented by String overflows according to the range > defined by > - UINT64, then ASSERT(). > + UINT64, then MAX_UINT64 is returned. > > If PcdMaximumUnicodeStringLength is not zero, and String contains more > than > PcdMaximumUnicodeStringLength Unicode characters, not including the > Null-terminator, > @@ -905,51 +799,7 @@ StrHexToUint64 ( > { > UINT64 Result; > > - // > - // ASSERT String is less long than PcdMaximumUnicodeStringLength. > - // Length tests are performed inside StrLen(). > - // > - ASSERT (StrSize (String) != 0); > - > - // > - // Ignore the pad spaces (space or tab) > - // > - while ((*String == L' ') || (*String == L'\t')) { > - String++; > - } > - > - // > - // Ignore leading Zeros after the spaces > - // > - while (*String == L'0') { > - String++; > - } > - > - if (InternalCharToUpper (*String) == L'X') { > - ASSERT (*(String - 1) == L'0'); > - if (*(String - 1) != L'0') { > - return 0; > - } > - // > - // Skip the 'X' > - // > - String++; > - } > - > - Result = 0; > - > - while (InternalIsHexaDecimalDigitCharacter (*String)) { > - // > - // If the Hex Number represented by String overflows according > - // to the range defined by UINTN, then ASSERT(). > - // > - ASSERT (Result <= RShiftU64 (((UINT64) ~0) - InternalHexCharToUintn > (*String) , 4)); > - > - Result = LShiftU64 (Result, 4); > - Result = Result + InternalHexCharToUintn (*String); > - String++; > - } > - > + StrHexToUint64S (String, (CHAR16 **) NULL, &Result); > return Result; > } > > @@ -1681,7 +1531,7 @@ AsciiStrStr ( > If String has only pad spaces, then 0 is returned. > If String has no pad spaces or valid decimal digits, then 0 is returned. > If the number represented by String overflows according to the range > defined by > - UINTN, then ASSERT(). > + UINTN, then MAX_UINTN is returned. > If String is NULL, then ASSERT(). > If PcdMaximumAsciiStringLength is not zero, and String contains more than > PcdMaximumAsciiStringLength ASCII characters not including the > Null-terminator, > @@ -1700,38 +1550,7 @@ AsciiStrDecimalToUintn ( > { > UINTN Result; > > - // > - // ASSERT Strings is less long than PcdMaximumAsciiStringLength > - // > - ASSERT (AsciiStrSize (String) != 0); > - > - // > - // Ignore the pad spaces (space or tab) > - // > - while ((*String == ' ') || (*String == '\t' )) { > - String++; > - } > - > - // > - // Ignore leading Zeros after the spaces > - // > - while (*String == '0') { > - String++; > - } > - > - Result = 0; > - > - while (InternalAsciiIsDecimalDigitCharacter (*String)) { > - // > - // If the number represented by String overflows according > - // to the range defined by UINTN, then ASSERT(). > - // > - ASSERT (Result <= ((((UINTN) ~0) - (*String - L'0')) / 10)); > - > - Result = Result * 10 + (*String - '0'); > - String++; > - } > - > + AsciiStrDecimalToUintnS (String, (CHAR8 **) NULL, &Result); > return Result; > } > > @@ -1755,7 +1574,7 @@ AsciiStrDecimalToUintn ( > If String has only pad spaces, then 0 is returned. > If String has no pad spaces or valid decimal digits, then 0 is returned. > If the number represented by String overflows according to the range > defined by > - UINT64, then ASSERT(). > + UINT64, then MAX_UINT64 is returned. > If String is NULL, then ASSERT(). > If PcdMaximumAsciiStringLength is not zero, and String contains more than > PcdMaximumAsciiStringLength ASCII characters not including the > Null-terminator, > @@ -1774,38 +1593,7 @@ AsciiStrDecimalToUint64 ( > { > UINT64 Result; > > - // > - // ASSERT Strings is less long than PcdMaximumAsciiStringLength > - // > - ASSERT (AsciiStrSize (String) != 0); > - > - // > - // Ignore the pad spaces (space or tab) > - // > - while ((*String == ' ') || (*String == '\t' )) { > - String++; > - } > - > - // > - // Ignore leading Zeros after the spaces > - // > - while (*String == '0') { > - String++; > - } > - > - Result = 0; > - > - while (InternalAsciiIsDecimalDigitCharacter (*String)) { > - // > - // If the number represented by String overflows according > - // to the range defined by UINTN, then ASSERT(). > - // > - ASSERT (Result <= DivU64x32 (((UINT64) ~0) - (*String - L'0') , 10)); > - > - Result = MultU64x32 (Result, 10) + (*String - '0'); > - String++; > - } > - > + AsciiStrDecimalToUint64S (String, (CHAR8 **) NULL, &Result); > return Result; > } > > @@ -1832,7 +1620,7 @@ AsciiStrDecimalToUint64 ( > 0 is returned. > > If the number represented by String overflows according to the range > defined by UINTN, > - then ASSERT(). > + then MAX_UINTN is returned. > If String is NULL, then ASSERT(). > If PcdMaximumAsciiStringLength is not zero, > and String contains more than PcdMaximumAsciiStringLength ASCII characters > not including > @@ -1851,49 +1639,7 @@ AsciiStrHexToUintn ( > { > UINTN Result; > > - // > - // ASSERT Strings is less long than PcdMaximumAsciiStringLength > - // > - ASSERT (AsciiStrSize (String) != 0); > - > - // > - // Ignore the pad spaces (space or tab) > - // > - while ((*String == ' ') || (*String == '\t' )) { > - String++; > - } > - > - // > - // Ignore leading Zeros after the spaces > - // > - while (*String == '0') { > - String++; > - } > - > - if (InternalBaseLibAsciiToUpper (*String) == 'X') { > - ASSERT (*(String - 1) == '0'); > - if (*(String - 1) != '0') { > - return 0; > - } > - // > - // Skip the 'X' > - // > - String++; > - } > - > - Result = 0; > - > - while (InternalAsciiIsHexaDecimalDigitCharacter (*String)) { > - // > - // If the Hex Number represented by String overflows according > - // to the range defined by UINTN, then ASSERT(). > - // > - ASSERT (Result <= ((((UINTN) ~0) - InternalHexCharToUintn (*String)) >> > 4)); > - > - Result = (Result << 4) + InternalAsciiHexCharToUintn (*String); > - String++; > - } > - > + AsciiStrHexToUintnS (String, (CHAR8 **) NULL, &Result); > return Result; > } > > @@ -1921,7 +1667,7 @@ AsciiStrHexToUintn ( > 0 is returned. > > If the number represented by String overflows according to the range > defined by UINT64, > - then ASSERT(). > + then MAX_UINT64 is returned. > If String is NULL, then ASSERT(). > If PcdMaximumAsciiStringLength is not zero, > and String contains more than PcdMaximumAsciiStringLength ASCII characters > not including > @@ -1940,53 +1686,7 @@ AsciiStrHexToUint64 ( > { > UINT64 Result; > > - // > - // ASSERT Strings is less long than PcdMaximumAsciiStringLength > - // > - ASSERT (AsciiStrSize (String) != 0); > - > - // > - // Ignore the pad spaces (space or tab) and leading Zeros > - // > - // > - // Ignore the pad spaces (space or tab) > - // > - while ((*String == ' ') || (*String == '\t' )) { > - String++; > - } > - > - // > - // Ignore leading Zeros after the spaces > - // > - while (*String == '0') { > - String++; > - } > - > - if (InternalBaseLibAsciiToUpper (*String) == 'X') { > - ASSERT (*(String - 1) == '0'); > - if (*(String - 1) != '0') { > - return 0; > - } > - // > - // Skip the 'X' > - // > - String++; > - } > - > - Result = 0; > - > - while (InternalAsciiIsHexaDecimalDigitCharacter (*String)) { > - // > - // If the Hex Number represented by String overflows according > - // to the range defined by UINTN, then ASSERT(). > - // > - ASSERT (Result <= RShiftU64 (((UINT64) ~0) - InternalHexCharToUintn > (*String) , 4)); > - > - Result = LShiftU64 (Result, 4); > - Result = Result + InternalAsciiHexCharToUintn (*String); > - String++; > - } > - > + AsciiStrHexToUint64S (String, (CHAR8 **) NULL, &Result); > return Result; > } > > -- > 1.9.5.msysgit.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/4] MdePkg/BaseLib: Add safe string functions [U|A]StrnTo[A|U]StrS 2017-01-04 11:22 [PATCH 0/4] Add and refine sting APIs in MdePkg/BaseLib Hao Wu ` (2 preceding siblings ...) 2017-01-04 11:22 ` [PATCH 3/4] MdePkg/BaseLib: Enhance the return value for string to uint functions Hao Wu @ 2017-01-04 11:22 ` Hao Wu 2017-01-09 2:03 ` Yao, Jiewen 3 siblings, 1 reply; 9+ messages in thread From: Hao Wu @ 2017-01-04 11:22 UTC (permalink / raw) To: edk2-devel; +Cc: Hao Wu, Jiewen Yao, Liming Gao, Michael Kinney Add the following 2 APIs: UnicodeStrnToAsciiStrS AsciiStrnToUnicodeStrS These APIs are used to enhance APIs UnicodeStrToAsciiStrS and AsciiStrToUnicodeStrS (without 'n' in names) by: 1. Adds an input parameter 'Length' to specify the maximum number of Ascii/Unicode characters to convert. 2. Adds an output parameter 'DestinationLength' to indicate the number of Ascii/Unicode characters successfully converted. Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Liming Gao <liming.gao@intel.com> Cc: Michael Kinney <michael.d.kinney@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Hao Wu <hao.a.wu@intel.com> --- MdePkg/Include/Library/BaseLib.h | 107 ++++++++++++++++ MdePkg/Library/BaseLib/SafeString.c | 237 ++++++++++++++++++++++++++++++++++++ 2 files changed, 344 insertions(+) diff --git a/MdePkg/Include/Library/BaseLib.h b/MdePkg/Include/Library/BaseLib.h index abea7b6..d71ccb7 100644 --- a/MdePkg/Include/Library/BaseLib.h +++ b/MdePkg/Include/Library/BaseLib.h @@ -1631,6 +1631,60 @@ UnicodeStrToAsciiStrS ( IN UINTN DestMax ); +/** + Convert not more than Length successive characters from a Null-terminated + Unicode string to a Null-terminated Ascii string. If no null char is copied + from Source, then Destination[Length] is always set to null. + + This function converts not more than Length successive characters from the + Unicode string Source to the Ascii string Destination by copying the lower 8 + bits of each Unicode character. The function terminates the Ascii string + Destination by appending a Null-terminator character at the end. + + The caller is responsible to make sure Destination points to a buffer with size + equal or greater than ((StrLen (Source) + 1) * sizeof (CHAR8)) in bytes. + + If any Unicode characters in Source contain non-zero value in the upper 8 + bits, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + If an error would be returned, then the function will also ASSERT(). + + If an error is returned, then the Destination is unmodified. + + @param Source The pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to + convert. + @param Destination The pointer to a Null-terminated Ascii string. + @param DestMax The maximum number of Destination Ascii + char, including terminating null char. + @param DestinationLength The number of Unicode characters converted. + + @retval RETURN_SUCCESS String is converted. + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If DestinationLength is NULL. + If PcdMaximumAsciiStringLength is not zero, + and Length or DestMax is greater than + PcdMaximumAsciiStringLength. + If PcdMaximumUnicodeStringLength is not + zero, and Length or DestMax is greater than + PcdMaximumUnicodeStringLength. + If DestMax is 0. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than + MIN(StrLen(Source), Length). + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. + +**/ +RETURN_STATUS +EFIAPI +UnicodeStrnToAsciiStrS ( + IN CONST CHAR16 *Source, + IN UINTN Length, + OUT CHAR8 *Destination, + IN UINTN DestMax, + OUT UINTN *DestinationLength + ); + #ifndef DISABLE_NEW_DEPRECATED_INTERFACES /** @@ -2219,6 +2273,59 @@ AsciiStrToUnicodeStrS ( ); /** + Convert not more than Length successive characters from a Null-terminated + Ascii string to a Null-terminated Unicode string. If no null char is copied + from Source, then Destination[Length] is always set to null. + + This function converts not more than Length successive characters from the + Ascii string Source to the Unicode string Destination. The function + terminates the Unicode string Destination by appending a Null-terminator + character at the end. + + The caller is responsible to make sure Destination points to a buffer with + size not smaller than + ((MIN(AsciiStrLen(Source), Length) + 1) * sizeof (CHAR8)) in bytes. + + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If an error would be returned, then the function will also ASSERT(). + + If an error is returned, then Destination and DestinationLength are + unmodified. + + @param Source The pointer to a Null-terminated Ascii string. + @param Length The maximum number of Ascii characters to convert. + @param Destination The pointer to a Null-terminated Unicode string. + @param DestMax The maximum number of Destination Unicode char, + including terminating null char. + @param DestinationLength The number of Ascii characters converted. + + @retval RETURN_SUCCESS String is converted. + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If DestinationLength is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and Length or DestMax is greater than + PcdMaximumUnicodeStringLength. + If PcdMaximumAsciiStringLength is not zero, + and Length or DestMax is greater than + PcdMaximumAsciiStringLength. + If DestMax is 0. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than + MIN(AsciiStrLen(Source), Length). + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrnToUnicodeStrS ( + IN CONST CHAR8 *Source, + IN UINTN Length, + OUT CHAR16 *Destination, + IN UINTN DestMax, + OUT UINTN *DestinationLength + ); + +/** Converts an 8-bit value to an 8-bit BCD value. Converts the 8-bit value specified by Value to BCD. The BCD value is diff --git a/MdePkg/Library/BaseLib/SafeString.c b/MdePkg/Library/BaseLib/SafeString.c index 5edc6ef..315059e 100644 --- a/MdePkg/Library/BaseLib/SafeString.c +++ b/MdePkg/Library/BaseLib/SafeString.c @@ -2108,6 +2108,128 @@ UnicodeStrToAsciiStrS ( return RETURN_SUCCESS; } +/** + Convert not more than Length successive characters from a Null-terminated + Unicode string to a Null-terminated Ascii string. If no null char is copied + from Source, then Destination[Length] is always set to null. + + This function converts not more than Length successive characters from the + Unicode string Source to the Ascii string Destination by copying the lower 8 + bits of each Unicode character. The function terminates the Ascii string + Destination by appending a Null-terminator character at the end. + + The caller is responsible to make sure Destination points to a buffer with + size not smaller than ((MIN(StrLen(Source), Length) + 1) * sizeof (CHAR8)) + in bytes. + + If any Unicode characters in Source contain non-zero value in the upper 8 + bits, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + If an error would be returned, then the function will also ASSERT(). + + If an error is returned, then Destination and DestinationLength are + unmodified. + + @param Source The pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to + convert. + @param Destination The pointer to a Null-terminated Ascii string. + @param DestMax The maximum number of Destination Ascii char, + including terminating null char. + @param DestinationLength The number of Unicode characters converted. + + @retval RETURN_SUCCESS String is converted. + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If DestinationLength is NULL. + If PcdMaximumAsciiStringLength is not zero, + and Length or DestMax is greater than + PcdMaximumAsciiStringLength. + If PcdMaximumUnicodeStringLength is not + zero, and Length or DestMax is greater than + PcdMaximumUnicodeStringLength. + If DestMax is 0. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than + MIN(StrLen(Source), Length). + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. + +**/ +RETURN_STATUS +EFIAPI +UnicodeStrnToAsciiStrS ( + IN CONST CHAR16 *Source, + IN UINTN Length, + OUT CHAR8 *Destination, + IN UINTN DestMax, + OUT UINTN *DestinationLength + ) +{ + UINTN SourceLen; + + ASSERT (((UINTN) Source & BIT0) == 0); + + // + // 1. None of Destination, Source or DestinationLength shall be a null + // pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((DestinationLength != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Neither Length nor DestMax shall be greater than ASCII_RSIZE_MAX or + // RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. If Length is not less than DestMax, then DestMax shall be greater than + // StrnLenS(Source, DestMax). + // + SourceLen = StrnLenS (Source, DestMax); + if (Length >= DestMax) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + } + + // + // 5. Copying shall not take place between objects that overlap. + // + if (SourceLen > Length) { + SourceLen = Length; + } + SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)), RETURN_ACCESS_DENIED); + + *DestinationLength = 0; + + // + // Convert string + // + while ((*Source != 0) && (SourceLen > 0)) { + // + // If any Unicode characters in Source contain non-zero value in the upper + // 8 bits, then ASSERT(). + // + ASSERT (*Source < 0x100); + *(Destination++) = (CHAR8) *(Source++); + SourceLen--; + (*DestinationLength)++; + } + *Destination = 0; + + return RETURN_SUCCESS; +} /** Convert one Null-terminated ASCII string to a Null-terminated @@ -2200,3 +2322,118 @@ AsciiStrToUnicodeStrS ( return RETURN_SUCCESS; } + +/** + Convert not more than Length successive characters from a Null-terminated + Ascii string to a Null-terminated Unicode string. If no null char is copied + from Source, then Destination[Length] is always set to null. + + This function converts not more than Length successive characters from the + Ascii string Source to the Unicode string Destination. The function + terminates the Unicode string Destination by appending a Null-terminator + character at the end. + + The caller is responsible to make sure Destination points to a buffer with + size not smaller than + ((MIN(AsciiStrLen(Source), Length) + 1) * sizeof (CHAR8)) in bytes. + + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If an error would be returned, then the function will also ASSERT(). + + If an error is returned, then Destination and DestinationLength are + unmodified. + + @param Source The pointer to a Null-terminated Ascii string. + @param Length The maximum number of Ascii characters to convert. + @param Destination The pointer to a Null-terminated Unicode string. + @param DestMax The maximum number of Destination Unicode char, + including terminating null char. + @param DestinationLength The number of Ascii characters converted. + + @retval RETURN_SUCCESS String is converted. + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If DestinationLength is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and Length or DestMax is greater than + PcdMaximumUnicodeStringLength. + If PcdMaximumAsciiStringLength is not zero, + and Length or DestMax is greater than + PcdMaximumAsciiStringLength. + If DestMax is 0. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than + MIN(AsciiStrLen(Source), Length). + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrnToUnicodeStrS ( + IN CONST CHAR8 *Source, + IN UINTN Length, + OUT CHAR16 *Destination, + IN UINTN DestMax, + OUT UINTN *DestinationLength + ) +{ + UINTN SourceLen; + + ASSERT (((UINTN) Destination & BIT0) == 0); + + // + // 1. None of Destination, Source or DestinationLength shall be a null + // pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((DestinationLength != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Neither Length nor DestMax shall be greater than ASCII_RSIZE_MAX or + // RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. If Length is not less than DestMax, then DestMax shall be greater than + // AsciiStrnLenS(Source, DestMax). + // + SourceLen = AsciiStrnLenS (Source, DestMax); + if (Length >= DestMax) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + } + + // + // 5. Copying shall not take place between objects that overlap. + // + if (SourceLen > Length) { + SourceLen = Length; + } + SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax * sizeof(CHAR16), (VOID *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + *DestinationLength = 0; + + // + // Convert string + // + while ((*Source != 0) && (SourceLen > 0)) { + *(Destination++) = (CHAR16)*(Source++); + SourceLen--; + (*DestinationLength)++; + } + *Destination = 0; + + return RETURN_SUCCESS; +} -- 1.9.5.msysgit.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 4/4] MdePkg/BaseLib: Add safe string functions [U|A]StrnTo[A|U]StrS 2017-01-04 11:22 ` [PATCH 4/4] MdePkg/BaseLib: Add safe string functions [U|A]StrnTo[A|U]StrS Hao Wu @ 2017-01-09 2:03 ` Yao, Jiewen 0 siblings, 0 replies; 9+ messages in thread From: Yao, Jiewen @ 2017-01-09 2:03 UTC (permalink / raw) To: Wu, Hao A, edk2-devel@lists.01.org; +Cc: Gao, Liming, Kinney, Michael D Reviewed-by: Jiewen.yao@intel.com > -----Original Message----- > From: Wu, Hao A > Sent: Wednesday, January 4, 2017 7:23 PM > To: edk2-devel@lists.01.org > Cc: Wu, Hao A <hao.a.wu@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; > Gao, Liming <liming.gao@intel.com>; Kinney, Michael D > <michael.d.kinney@intel.com> > Subject: [PATCH 4/4] MdePkg/BaseLib: Add safe string functions > [U|A]StrnTo[A|U]StrS > > Add the following 2 APIs: > UnicodeStrnToAsciiStrS > AsciiStrnToUnicodeStrS > > These APIs are used to enhance APIs UnicodeStrToAsciiStrS and > AsciiStrToUnicodeStrS (without 'n' in names) by: > 1. Adds an input parameter 'Length' to specify the maximum number of > Ascii/Unicode characters to convert. > 2. Adds an output parameter 'DestinationLength' to indicate the number of > Ascii/Unicode characters successfully converted. > > Cc: Jiewen Yao <jiewen.yao@intel.com> > Cc: Liming Gao <liming.gao@intel.com> > Cc: Michael Kinney <michael.d.kinney@intel.com> > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Hao Wu <hao.a.wu@intel.com> > --- > MdePkg/Include/Library/BaseLib.h | 107 ++++++++++++++++ > MdePkg/Library/BaseLib/SafeString.c | 237 > ++++++++++++++++++++++++++++++++++++ > 2 files changed, 344 insertions(+) > > diff --git a/MdePkg/Include/Library/BaseLib.h > b/MdePkg/Include/Library/BaseLib.h > index abea7b6..d71ccb7 100644 > --- a/MdePkg/Include/Library/BaseLib.h > +++ b/MdePkg/Include/Library/BaseLib.h > @@ -1631,6 +1631,60 @@ UnicodeStrToAsciiStrS ( > IN UINTN DestMax > ); > > +/** > + Convert not more than Length successive characters from a Null-terminated > + Unicode string to a Null-terminated Ascii string. If no null char is copied > + from Source, then Destination[Length] is always set to null. > + > + This function converts not more than Length successive characters from the > + Unicode string Source to the Ascii string Destination by copying the lower 8 > + bits of each Unicode character. The function terminates the Ascii string > + Destination by appending a Null-terminator character at the end. > + > + The caller is responsible to make sure Destination points to a buffer with size > + equal or greater than ((StrLen (Source) + 1) * sizeof (CHAR8)) in bytes. > + > + If any Unicode characters in Source contain non-zero value in the upper 8 > + bits, then ASSERT(). > + If Source is not aligned on a 16-bit boundary, then ASSERT(). > + If an error would be returned, then the function will also ASSERT(). > + > + If an error is returned, then the Destination is unmodified. > + > + @param Source The pointer to a Null-terminated Unicode > string. > + @param Length The maximum number of Unicode > characters to > + convert. > + @param Destination The pointer to a Null-terminated Ascii string. > + @param DestMax The maximum number of Destination Ascii > + char, including terminating null char. > + @param DestinationLength The number of Unicode characters converted. > + > + @retval RETURN_SUCCESS String is converted. > + @retval RETURN_INVALID_PARAMETER If Destination is NULL. > + If Source is NULL. > + If DestinationLength is NULL. > + If PcdMaximumAsciiStringLength is > not zero, > + and Length or DestMax is greater than > + PcdMaximumAsciiStringLength. > + If PcdMaximumUnicodeStringLength > is not > + zero, and Length or DestMax is > greater than > + PcdMaximumUnicodeStringLength. > + If DestMax is 0. > + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than > + MIN(StrLen(Source), Length). > + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. > + > +**/ > +RETURN_STATUS > +EFIAPI > +UnicodeStrnToAsciiStrS ( > + IN CONST CHAR16 *Source, > + IN UINTN Length, > + OUT CHAR8 *Destination, > + IN UINTN DestMax, > + OUT UINTN *DestinationLength > + ); > + > #ifndef DISABLE_NEW_DEPRECATED_INTERFACES > > /** > @@ -2219,6 +2273,59 @@ AsciiStrToUnicodeStrS ( > ); > > /** > + Convert not more than Length successive characters from a Null-terminated > + Ascii string to a Null-terminated Unicode string. If no null char is copied > + from Source, then Destination[Length] is always set to null. > + > + This function converts not more than Length successive characters from the > + Ascii string Source to the Unicode string Destination. The function > + terminates the Unicode string Destination by appending a Null-terminator > + character at the end. > + > + The caller is responsible to make sure Destination points to a buffer with > + size not smaller than > + ((MIN(AsciiStrLen(Source), Length) + 1) * sizeof (CHAR8)) in bytes. > + > + If Destination is not aligned on a 16-bit boundary, then ASSERT(). > + If an error would be returned, then the function will also ASSERT(). > + > + If an error is returned, then Destination and DestinationLength are > + unmodified. > + > + @param Source The pointer to a Null-terminated Ascii string. > + @param Length The maximum number of Ascii characters to > convert. > + @param Destination The pointer to a Null-terminated Unicode > string. > + @param DestMax The maximum number of Destination > Unicode char, > + including terminating null char. > + @param DestinationLength The number of Ascii characters converted. > + > + @retval RETURN_SUCCESS String is converted. > + @retval RETURN_INVALID_PARAMETER If Destination is NULL. > + If Source is NULL. > + If DestinationLength is NULL. > + If PcdMaximumUnicodeStringLength > is not > + zero, and Length or DestMax is > greater than > + PcdMaximumUnicodeStringLength. > + If PcdMaximumAsciiStringLength is > not zero, > + and Length or DestMax is greater than > + PcdMaximumAsciiStringLength. > + If DestMax is 0. > + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than > + MIN(AsciiStrLen(Source), Length). > + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. > + > +**/ > +RETURN_STATUS > +EFIAPI > +AsciiStrnToUnicodeStrS ( > + IN CONST CHAR8 *Source, > + IN UINTN Length, > + OUT CHAR16 *Destination, > + IN UINTN DestMax, > + OUT UINTN *DestinationLength > + ); > + > +/** > Converts an 8-bit value to an 8-bit BCD value. > > Converts the 8-bit value specified by Value to BCD. The BCD value is > diff --git a/MdePkg/Library/BaseLib/SafeString.c > b/MdePkg/Library/BaseLib/SafeString.c > index 5edc6ef..315059e 100644 > --- a/MdePkg/Library/BaseLib/SafeString.c > +++ b/MdePkg/Library/BaseLib/SafeString.c > @@ -2108,6 +2108,128 @@ UnicodeStrToAsciiStrS ( > return RETURN_SUCCESS; > } > > +/** > + Convert not more than Length successive characters from a Null-terminated > + Unicode string to a Null-terminated Ascii string. If no null char is copied > + from Source, then Destination[Length] is always set to null. > + > + This function converts not more than Length successive characters from the > + Unicode string Source to the Ascii string Destination by copying the lower 8 > + bits of each Unicode character. The function terminates the Ascii string > + Destination by appending a Null-terminator character at the end. > + > + The caller is responsible to make sure Destination points to a buffer with > + size not smaller than ((MIN(StrLen(Source), Length) + 1) * sizeof (CHAR8)) > + in bytes. > + > + If any Unicode characters in Source contain non-zero value in the upper 8 > + bits, then ASSERT(). > + If Source is not aligned on a 16-bit boundary, then ASSERT(). > + If an error would be returned, then the function will also ASSERT(). > + > + If an error is returned, then Destination and DestinationLength are > + unmodified. > + > + @param Source The pointer to a Null-terminated Unicode > string. > + @param Length The maximum number of Unicode > characters to > + convert. > + @param Destination The pointer to a Null-terminated Ascii string. > + @param DestMax The maximum number of Destination Ascii > char, > + including terminating null char. > + @param DestinationLength The number of Unicode characters converted. > + > + @retval RETURN_SUCCESS String is converted. > + @retval RETURN_INVALID_PARAMETER If Destination is NULL. > + If Source is NULL. > + If DestinationLength is NULL. > + If PcdMaximumAsciiStringLength is > not zero, > + and Length or DestMax is greater than > + PcdMaximumAsciiStringLength. > + If PcdMaximumUnicodeStringLength > is not > + zero, and Length or DestMax is > greater than > + PcdMaximumUnicodeStringLength. > + If DestMax is 0. > + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than > + MIN(StrLen(Source), Length). > + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. > + > +**/ > +RETURN_STATUS > +EFIAPI > +UnicodeStrnToAsciiStrS ( > + IN CONST CHAR16 *Source, > + IN UINTN Length, > + OUT CHAR8 *Destination, > + IN UINTN DestMax, > + OUT UINTN *DestinationLength > + ) > +{ > + UINTN SourceLen; > + > + ASSERT (((UINTN) Source & BIT0) == 0); > + > + // > + // 1. None of Destination, Source or DestinationLength shall be a null > + // pointer. > + // > + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), > RETURN_INVALID_PARAMETER); > + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), > RETURN_INVALID_PARAMETER); > + SAFE_STRING_CONSTRAINT_CHECK ((DestinationLength != NULL), > RETURN_INVALID_PARAMETER); > + > + // > + // 2. Neither Length nor DestMax shall be greater than ASCII_RSIZE_MAX or > + // RSIZE_MAX. > + // > + if (ASCII_RSIZE_MAX != 0) { > + SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), > RETURN_INVALID_PARAMETER); > + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), > RETURN_INVALID_PARAMETER); > + } > + if (RSIZE_MAX != 0) { > + SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), > RETURN_INVALID_PARAMETER); > + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), > RETURN_INVALID_PARAMETER); > + } > + > + // > + // 3. DestMax shall not equal zero. > + // > + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), > RETURN_INVALID_PARAMETER); > + > + // > + // 4. If Length is not less than DestMax, then DestMax shall be greater than > + // StrnLenS(Source, DestMax). > + // > + SourceLen = StrnLenS (Source, DestMax); > + if (Length >= DestMax) { > + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), > RETURN_BUFFER_TOO_SMALL); > + } > + > + // > + // 5. Copying shall not take place between objects that overlap. > + // > + if (SourceLen > Length) { > + SourceLen = Length; > + } > + SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap > (Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)), > RETURN_ACCESS_DENIED); > + > + *DestinationLength = 0; > + > + // > + // Convert string > + // > + while ((*Source != 0) && (SourceLen > 0)) { > + // > + // If any Unicode characters in Source contain non-zero value in the upper > + // 8 bits, then ASSERT(). > + // > + ASSERT (*Source < 0x100); > + *(Destination++) = (CHAR8) *(Source++); > + SourceLen--; > + (*DestinationLength)++; > + } > + *Destination = 0; > + > + return RETURN_SUCCESS; > +} > > /** > Convert one Null-terminated ASCII string to a Null-terminated > @@ -2200,3 +2322,118 @@ AsciiStrToUnicodeStrS ( > > return RETURN_SUCCESS; > } > + > +/** > + Convert not more than Length successive characters from a Null-terminated > + Ascii string to a Null-terminated Unicode string. If no null char is copied > + from Source, then Destination[Length] is always set to null. > + > + This function converts not more than Length successive characters from the > + Ascii string Source to the Unicode string Destination. The function > + terminates the Unicode string Destination by appending a Null-terminator > + character at the end. > + > + The caller is responsible to make sure Destination points to a buffer with > + size not smaller than > + ((MIN(AsciiStrLen(Source), Length) + 1) * sizeof (CHAR8)) in bytes. > + > + If Destination is not aligned on a 16-bit boundary, then ASSERT(). > + If an error would be returned, then the function will also ASSERT(). > + > + If an error is returned, then Destination and DestinationLength are > + unmodified. > + > + @param Source The pointer to a Null-terminated Ascii string. > + @param Length The maximum number of Ascii characters to > convert. > + @param Destination The pointer to a Null-terminated Unicode > string. > + @param DestMax The maximum number of Destination > Unicode char, > + including terminating null char. > + @param DestinationLength The number of Ascii characters converted. > + > + @retval RETURN_SUCCESS String is converted. > + @retval RETURN_INVALID_PARAMETER If Destination is NULL. > + If Source is NULL. > + If DestinationLength is NULL. > + If PcdMaximumUnicodeStringLength > is not > + zero, and Length or DestMax is > greater than > + PcdMaximumUnicodeStringLength. > + If PcdMaximumAsciiStringLength is > not zero, > + and Length or DestMax is greater than > + PcdMaximumAsciiStringLength. > + If DestMax is 0. > + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than > + MIN(AsciiStrLen(Source), Length). > + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. > + > +**/ > +RETURN_STATUS > +EFIAPI > +AsciiStrnToUnicodeStrS ( > + IN CONST CHAR8 *Source, > + IN UINTN Length, > + OUT CHAR16 *Destination, > + IN UINTN DestMax, > + OUT UINTN *DestinationLength > + ) > +{ > + UINTN SourceLen; > + > + ASSERT (((UINTN) Destination & BIT0) == 0); > + > + // > + // 1. None of Destination, Source or DestinationLength shall be a null > + // pointer. > + // > + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), > RETURN_INVALID_PARAMETER); > + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), > RETURN_INVALID_PARAMETER); > + SAFE_STRING_CONSTRAINT_CHECK ((DestinationLength != NULL), > RETURN_INVALID_PARAMETER); > + > + // > + // 2. Neither Length nor DestMax shall be greater than ASCII_RSIZE_MAX or > + // RSIZE_MAX. > + // > + if (RSIZE_MAX != 0) { > + SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), > RETURN_INVALID_PARAMETER); > + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), > RETURN_INVALID_PARAMETER); > + } > + if (ASCII_RSIZE_MAX != 0) { > + SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), > RETURN_INVALID_PARAMETER); > + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), > RETURN_INVALID_PARAMETER); > + } > + > + // > + // 3. DestMax shall not equal zero. > + // > + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), > RETURN_INVALID_PARAMETER); > + > + // > + // 4. If Length is not less than DestMax, then DestMax shall be greater than > + // AsciiStrnLenS(Source, DestMax). > + // > + SourceLen = AsciiStrnLenS (Source, DestMax); > + if (Length >= DestMax) { > + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), > RETURN_BUFFER_TOO_SMALL); > + } > + > + // > + // 5. Copying shall not take place between objects that overlap. > + // > + if (SourceLen > Length) { > + SourceLen = Length; > + } > + SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap > (Destination, DestMax * sizeof(CHAR16), (VOID *)Source, SourceLen + 1), > RETURN_ACCESS_DENIED); > + > + *DestinationLength = 0; > + > + // > + // Convert string > + // > + while ((*Source != 0) && (SourceLen > 0)) { > + *(Destination++) = (CHAR16)*(Source++); > + SourceLen--; > + (*DestinationLength)++; > + } > + *Destination = 0; > + > + return RETURN_SUCCESS; > +} > -- > 1.9.5.msysgit.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2017-01-09 2:03 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2017-01-04 11:22 [PATCH 0/4] Add and refine sting APIs in MdePkg/BaseLib Hao Wu 2017-01-04 11:22 ` [PATCH 1/4] MdePkg/BaseLib: Add safe string functions [Ascii]StrnSizeS Hao Wu 2017-01-05 2:02 ` Yao, Jiewen 2017-01-04 11:22 ` [PATCH 2/4] MdePkg/BaseLib: Add safe string functions that convert str to value Hao Wu 2017-01-09 2:02 ` Yao, Jiewen 2017-01-04 11:22 ` [PATCH 3/4] MdePkg/BaseLib: Enhance the return value for string to uint functions Hao Wu 2017-01-09 2:03 ` Yao, Jiewen 2017-01-04 11:22 ` [PATCH 4/4] MdePkg/BaseLib: Add safe string functions [U|A]StrnTo[A|U]StrS Hao Wu 2017-01-09 2:03 ` Yao, Jiewen
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox