]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdePkg/BaseLib: Add safe string functions [U|A]StrnTo[A|U]StrS
authorHao Wu <hao.a.wu@intel.com>
Tue, 13 Dec 2016 08:00:35 +0000 (16:00 +0800)
committerHao Wu <hao.a.wu@intel.com>
Mon, 9 Jan 2017 05:59:34 +0000 (13:59 +0800)
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.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
MdePkg/Include/Library/BaseLib.h
MdePkg/Library/BaseLib/SafeString.c

index abea7b6724aed4c741e6e1d987ef76f39e23a076..d71ccb7e8e0aa20e0532fcc882315e03345d03f5 100644 (file)
@@ -1631,6 +1631,60 @@ UnicodeStrToAsciiStrS (
   IN      UINTN                     DestMax\r
   );\r
 \r
   IN      UINTN                     DestMax\r
   );\r
 \r
+/**\r
+  Convert not more than Length successive characters from a Null-terminated\r
+  Unicode string to a Null-terminated Ascii string. If no null char is copied\r
+  from Source, then Destination[Length] is always set to null.\r
+\r
+  This function converts not more than Length successive characters from the\r
+  Unicode string Source to the Ascii string Destination by copying the lower 8\r
+  bits of each Unicode character. The function terminates the Ascii string\r
+  Destination by appending a Null-terminator character at the end.\r
+\r
+  The caller is responsible to make sure Destination points to a buffer with size\r
+  equal or greater than ((StrLen (Source) + 1) * sizeof (CHAR8)) in bytes.\r
+\r
+  If any Unicode characters in Source contain non-zero value in the upper 8\r
+  bits, then ASSERT().\r
+  If Source is not aligned on a 16-bit boundary, then ASSERT().\r
+  If an error would be returned, then the function will also ASSERT().\r
+\r
+  If an error is returned, then the Destination is unmodified.\r
+\r
+  @param  Source             The pointer to a Null-terminated Unicode string.\r
+  @param  Length             The maximum number of Unicode characters to\r
+                             convert.\r
+  @param  Destination        The pointer to a Null-terminated Ascii string.\r
+  @param  DestMax            The maximum number of Destination Ascii\r
+                             char, including terminating null char.\r
+  @param  DestinationLength  The number of Unicode characters converted.\r
+\r
+  @retval RETURN_SUCCESS            String is converted.\r
+  @retval RETURN_INVALID_PARAMETER  If Destination is NULL.\r
+                                    If Source is NULL.\r
+                                    If DestinationLength is NULL.\r
+                                    If PcdMaximumAsciiStringLength is not zero,\r
+                                    and Length or DestMax is greater than\r
+                                    PcdMaximumAsciiStringLength.\r
+                                    If PcdMaximumUnicodeStringLength is not\r
+                                    zero, and Length or DestMax is greater than\r
+                                    PcdMaximumUnicodeStringLength.\r
+                                    If DestMax is 0.\r
+  @retval RETURN_BUFFER_TOO_SMALL   If DestMax is NOT greater than\r
+                                    MIN(StrLen(Source), Length).\r
+  @retval RETURN_ACCESS_DENIED      If Source and Destination overlap.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+UnicodeStrnToAsciiStrS (\r
+  IN      CONST CHAR16              *Source,\r
+  IN      UINTN                     Length,\r
+  OUT     CHAR8                     *Destination,\r
+  IN      UINTN                     DestMax,\r
+  OUT     UINTN                     *DestinationLength\r
+  );\r
+\r
 #ifndef DISABLE_NEW_DEPRECATED_INTERFACES\r
 \r
 /**\r
 #ifndef DISABLE_NEW_DEPRECATED_INTERFACES\r
 \r
 /**\r
@@ -2218,6 +2272,59 @@ AsciiStrToUnicodeStrS (
   IN      UINTN                     DestMax\r
   );\r
 \r
   IN      UINTN                     DestMax\r
   );\r
 \r
+/**\r
+  Convert not more than Length successive characters from a Null-terminated\r
+  Ascii string to a Null-terminated Unicode string. If no null char is copied\r
+  from Source, then Destination[Length] is always set to null.\r
+\r
+  This function converts not more than Length successive characters from the\r
+  Ascii string Source to the Unicode string Destination. The function\r
+  terminates the Unicode string Destination by appending a Null-terminator\r
+  character at the end.\r
+\r
+  The caller is responsible to make sure Destination points to a buffer with\r
+  size not smaller than\r
+  ((MIN(AsciiStrLen(Source), Length) + 1) * sizeof (CHAR8)) in bytes.\r
+\r
+  If Destination is not aligned on a 16-bit boundary, then ASSERT().\r
+  If an error would be returned, then the function will also ASSERT().\r
+\r
+  If an error is returned, then Destination and DestinationLength are\r
+  unmodified.\r
+\r
+  @param  Source             The pointer to a Null-terminated Ascii string.\r
+  @param  Length             The maximum number of Ascii characters to convert.\r
+  @param  Destination        The pointer to a Null-terminated Unicode string.\r
+  @param  DestMax            The maximum number of Destination Unicode char,\r
+                             including terminating null char.\r
+  @param  DestinationLength  The number of Ascii characters converted.\r
+\r
+  @retval RETURN_SUCCESS            String is converted.\r
+  @retval RETURN_INVALID_PARAMETER  If Destination is NULL.\r
+                                    If Source is NULL.\r
+                                    If DestinationLength is NULL.\r
+                                    If PcdMaximumUnicodeStringLength is not\r
+                                    zero, and Length or DestMax is greater than\r
+                                    PcdMaximumUnicodeStringLength.\r
+                                    If PcdMaximumAsciiStringLength is not zero,\r
+                                    and Length or DestMax is greater than\r
+                                    PcdMaximumAsciiStringLength.\r
+                                    If DestMax is 0.\r
+  @retval RETURN_BUFFER_TOO_SMALL   If DestMax is NOT greater than\r
+                                    MIN(AsciiStrLen(Source), Length).\r
+  @retval RETURN_ACCESS_DENIED      If Source and Destination overlap.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+AsciiStrnToUnicodeStrS (\r
+  IN      CONST CHAR8               *Source,\r
+  IN      UINTN                     Length,\r
+  OUT     CHAR16                    *Destination,\r
+  IN      UINTN                     DestMax,\r
+  OUT     UINTN                     *DestinationLength\r
+  );\r
+\r
 /**\r
   Converts an 8-bit value to an 8-bit BCD value.\r
 \r
 /**\r
   Converts an 8-bit value to an 8-bit BCD value.\r
 \r
index 5edc6ef06211483ca6b1981197a7431b210353fb..315059e5dcdc983a47fc12c9f428325435c5e2dc 100644 (file)
@@ -2108,6 +2108,128 @@ UnicodeStrToAsciiStrS (
   return RETURN_SUCCESS;\r
 }\r
 \r
   return RETURN_SUCCESS;\r
 }\r
 \r
+/**\r
+  Convert not more than Length successive characters from a Null-terminated\r
+  Unicode string to a Null-terminated Ascii string. If no null char is copied\r
+  from Source, then Destination[Length] is always set to null.\r
+\r
+  This function converts not more than Length successive characters from the\r
+  Unicode string Source to the Ascii string Destination by copying the lower 8\r
+  bits of each Unicode character. The function terminates the Ascii string\r
+  Destination by appending a Null-terminator character at the end.\r
+\r
+  The caller is responsible to make sure Destination points to a buffer with\r
+  size not smaller than ((MIN(StrLen(Source), Length) + 1) * sizeof (CHAR8))\r
+  in bytes.\r
+\r
+  If any Unicode characters in Source contain non-zero value in the upper 8\r
+  bits, then ASSERT().\r
+  If Source is not aligned on a 16-bit boundary, then ASSERT().\r
+  If an error would be returned, then the function will also ASSERT().\r
+\r
+  If an error is returned, then Destination and DestinationLength are\r
+  unmodified.\r
+\r
+  @param  Source             The pointer to a Null-terminated Unicode string.\r
+  @param  Length             The maximum number of Unicode characters to\r
+                             convert.\r
+  @param  Destination        The pointer to a Null-terminated Ascii string.\r
+  @param  DestMax            The maximum number of Destination Ascii char,\r
+                             including terminating null char.\r
+  @param  DestinationLength  The number of Unicode characters converted.\r
+\r
+  @retval RETURN_SUCCESS            String is converted.\r
+  @retval RETURN_INVALID_PARAMETER  If Destination is NULL.\r
+                                    If Source is NULL.\r
+                                    If DestinationLength is NULL.\r
+                                    If PcdMaximumAsciiStringLength is not zero,\r
+                                    and Length or DestMax is greater than\r
+                                    PcdMaximumAsciiStringLength.\r
+                                    If PcdMaximumUnicodeStringLength is not\r
+                                    zero, and Length or DestMax is greater than\r
+                                    PcdMaximumUnicodeStringLength.\r
+                                    If DestMax is 0.\r
+  @retval RETURN_BUFFER_TOO_SMALL   If DestMax is NOT greater than\r
+                                    MIN(StrLen(Source), Length).\r
+  @retval RETURN_ACCESS_DENIED      If Source and Destination overlap.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+UnicodeStrnToAsciiStrS (\r
+  IN      CONST CHAR16              *Source,\r
+  IN      UINTN                     Length,\r
+  OUT     CHAR8                     *Destination,\r
+  IN      UINTN                     DestMax,\r
+  OUT     UINTN                     *DestinationLength\r
+  )\r
+{\r
+  UINTN            SourceLen;\r
+\r
+  ASSERT (((UINTN) Source & BIT0) == 0);\r
+\r
+  //\r
+  // 1. None of Destination, Source or DestinationLength shall be a null\r
+  // pointer.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((DestinationLength != NULL), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 2. Neither Length nor DestMax shall be greater than ASCII_RSIZE_MAX or\r
+  // RSIZE_MAX.\r
+  //\r
+  if (ASCII_RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+  if (RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+\r
+  //\r
+  // 3. DestMax shall not equal zero.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 4. If Length is not less than DestMax, then DestMax shall be greater than\r
+  // StrnLenS(Source, DestMax).\r
+  //\r
+  SourceLen = StrnLenS (Source, DestMax);\r
+  if (Length >= DestMax) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);\r
+  }\r
+\r
+  //\r
+  // 5. Copying shall not take place between objects that overlap.\r
+  //\r
+  if (SourceLen > Length) {\r
+    SourceLen = Length;\r
+  }\r
+  SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)), RETURN_ACCESS_DENIED);\r
+\r
+  *DestinationLength = 0;\r
+\r
+  //\r
+  // Convert string\r
+  //\r
+  while ((*Source != 0) && (SourceLen > 0)) {\r
+    //\r
+    // If any Unicode characters in Source contain non-zero value in the upper\r
+    // 8 bits, then ASSERT().\r
+    //\r
+    ASSERT (*Source < 0x100);\r
+    *(Destination++) = (CHAR8) *(Source++);\r
+    SourceLen--;\r
+    (*DestinationLength)++;\r
+  }\r
+  *Destination = 0;\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
 \r
 /**\r
   Convert one Null-terminated ASCII string to a Null-terminated\r
 \r
 /**\r
   Convert one Null-terminated ASCII string to a Null-terminated\r
@@ -2200,3 +2322,118 @@ AsciiStrToUnicodeStrS (
 \r
   return RETURN_SUCCESS;\r
 }\r
 \r
   return RETURN_SUCCESS;\r
 }\r
+\r
+/**\r
+  Convert not more than Length successive characters from a Null-terminated\r
+  Ascii string to a Null-terminated Unicode string. If no null char is copied\r
+  from Source, then Destination[Length] is always set to null.\r
+\r
+  This function converts not more than Length successive characters from the\r
+  Ascii string Source to the Unicode string Destination. The function\r
+  terminates the Unicode string Destination by appending a Null-terminator\r
+  character at the end.\r
+\r
+  The caller is responsible to make sure Destination points to a buffer with\r
+  size not smaller than\r
+  ((MIN(AsciiStrLen(Source), Length) + 1) * sizeof (CHAR8)) in bytes.\r
+\r
+  If Destination is not aligned on a 16-bit boundary, then ASSERT().\r
+  If an error would be returned, then the function will also ASSERT().\r
+\r
+  If an error is returned, then Destination and DestinationLength are\r
+  unmodified.\r
+\r
+  @param  Source             The pointer to a Null-terminated Ascii string.\r
+  @param  Length             The maximum number of Ascii characters to convert.\r
+  @param  Destination        The pointer to a Null-terminated Unicode string.\r
+  @param  DestMax            The maximum number of Destination Unicode char,\r
+                             including terminating null char.\r
+  @param  DestinationLength  The number of Ascii characters converted.\r
+\r
+  @retval RETURN_SUCCESS            String is converted.\r
+  @retval RETURN_INVALID_PARAMETER  If Destination is NULL.\r
+                                    If Source is NULL.\r
+                                    If DestinationLength is NULL.\r
+                                    If PcdMaximumUnicodeStringLength is not\r
+                                    zero, and Length or DestMax is greater than\r
+                                    PcdMaximumUnicodeStringLength.\r
+                                    If PcdMaximumAsciiStringLength is not zero,\r
+                                    and Length or DestMax is greater than\r
+                                    PcdMaximumAsciiStringLength.\r
+                                    If DestMax is 0.\r
+  @retval RETURN_BUFFER_TOO_SMALL   If DestMax is NOT greater than\r
+                                    MIN(AsciiStrLen(Source), Length).\r
+  @retval RETURN_ACCESS_DENIED      If Source and Destination overlap.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+AsciiStrnToUnicodeStrS (\r
+  IN      CONST CHAR8               *Source,\r
+  IN      UINTN                     Length,\r
+  OUT     CHAR16                    *Destination,\r
+  IN      UINTN                     DestMax,\r
+  OUT     UINTN                     *DestinationLength\r
+  )\r
+{\r
+  UINTN            SourceLen;\r
+\r
+  ASSERT (((UINTN) Destination & BIT0) == 0);\r
+\r
+  //\r
+  // 1. None of Destination, Source or DestinationLength shall be a null\r
+  // pointer.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);\r
+  SAFE_STRING_CONSTRAINT_CHECK ((DestinationLength != NULL), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 2. Neither Length nor DestMax shall be greater than ASCII_RSIZE_MAX or\r
+  // RSIZE_MAX.\r
+  //\r
+  if (RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+  if (ASCII_RSIZE_MAX != 0) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
+  }\r
+\r
+  //\r
+  // 3. DestMax shall not equal zero.\r
+  //\r
+  SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);\r
+\r
+  //\r
+  // 4. If Length is not less than DestMax, then DestMax shall be greater than\r
+  // AsciiStrnLenS(Source, DestMax).\r
+  //\r
+  SourceLen = AsciiStrnLenS (Source, DestMax);\r
+  if (Length >= DestMax) {\r
+    SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);\r
+  }\r
+\r
+  //\r
+  // 5. Copying shall not take place between objects that overlap.\r
+  //\r
+  if (SourceLen > Length) {\r
+    SourceLen = Length;\r
+  }\r
+  SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax * sizeof(CHAR16), (VOID *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);\r
+\r
+  *DestinationLength = 0;\r
+\r
+  //\r
+  // Convert string\r
+  //\r
+  while ((*Source != 0) && (SourceLen > 0)) {\r
+    *(Destination++) = (CHAR16)*(Source++);\r
+    SourceLen--;\r
+    (*DestinationLength)++;\r
+  }\r
+  *Destination = 0;\r
+\r
+  return RETURN_SUCCESS;\r
+}\r