1 /** @file
2   Safe String functions.
3 
4   Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
5   This program and the accompanying materials
6   are licensed and made available under the terms and conditions of the BSD License
7   which accompanies this distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php.
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include <Base.h>
16 #include <Library/DebugLib.h>
17 #include <Library/PcdLib.h>
18 #include <Library/BaseLib.h>
19 
20 #define RSIZE_MAX  (PcdGet32 (PcdMaximumUnicodeStringLength))
21 
22 #define ASCII_RSIZE_MAX  (PcdGet32 (PcdMaximumAsciiStringLength))
23 
24 #define SAFE_STRING_CONSTRAINT_CHECK(Expression, Status)  \
25   do { \
26     ASSERT (Expression); \
27     if (!(Expression)) { \
28       return Status; \
29     } \
30   } while (FALSE)
31 
32 /**
33   Returns if 2 memory blocks are overlapped.
34 
35   @param  Base1  Base address of 1st memory block.
36   @param  Size1  Size of 1st memory block.
37   @param  Base2  Base address of 2nd memory block.
38   @param  Size2  Size of 2nd memory block.
39 
40   @retval TRUE  2 memory blocks are overlapped.
41   @retval FALSE 2 memory blocks are not overlapped.
42 **/
43 BOOLEAN
InternalSafeStringIsOverlap(IN VOID * Base1,IN UINTN Size1,IN VOID * Base2,IN UINTN Size2)44 InternalSafeStringIsOverlap (
45   IN VOID    *Base1,
46   IN UINTN   Size1,
47   IN VOID    *Base2,
48   IN UINTN   Size2
49   )
50 {
51   if ((((UINTN)Base1 >= (UINTN)Base2) && ((UINTN)Base1 < (UINTN)Base2 + Size2)) ||
52       (((UINTN)Base2 >= (UINTN)Base1) && ((UINTN)Base2 < (UINTN)Base1 + Size1))) {
53     return TRUE;
54   }
55   return FALSE;
56 }
57 
58 /**
59   Returns if 2 Unicode strings are not overlapped.
60 
61   @param  Str1   Start address of 1st Unicode string.
62   @param  Size1  The number of char in 1st Unicode string,
63                  including terminating null char.
64   @param  Str2   Start address of 2nd Unicode string.
65   @param  Size2  The number of char in 2nd Unicode string,
66                  including terminating null char.
67 
68   @retval TRUE  2 Unicode strings are NOT overlapped.
69   @retval FALSE 2 Unicode strings are overlapped.
70 **/
71 BOOLEAN
InternalSafeStringNoStrOverlap(IN CHAR16 * Str1,IN UINTN Size1,IN CHAR16 * Str2,IN UINTN Size2)72 InternalSafeStringNoStrOverlap (
73   IN CHAR16  *Str1,
74   IN UINTN   Size1,
75   IN CHAR16  *Str2,
76   IN UINTN   Size2
77   )
78 {
79   return !InternalSafeStringIsOverlap (Str1, Size1 * sizeof(CHAR16), Str2, Size2 * sizeof(CHAR16));
80 }
81 
82 /**
83   Returns if 2 Ascii strings are not overlapped.
84 
85   @param  Str1   Start address of 1st Ascii string.
86   @param  Size1  The number of char in 1st Ascii string,
87                  including terminating null char.
88   @param  Str2   Start address of 2nd Ascii string.
89   @param  Size2  The number of char in 2nd Ascii string,
90                  including terminating null char.
91 
92   @retval TRUE  2 Ascii strings are NOT overlapped.
93   @retval FALSE 2 Ascii strings are overlapped.
94 **/
95 BOOLEAN
InternalSafeStringNoAsciiStrOverlap(IN CHAR8 * Str1,IN UINTN Size1,IN CHAR8 * Str2,IN UINTN Size2)96 InternalSafeStringNoAsciiStrOverlap (
97   IN CHAR8   *Str1,
98   IN UINTN   Size1,
99   IN CHAR8   *Str2,
100   IN UINTN   Size2
101   )
102 {
103   return !InternalSafeStringIsOverlap (Str1, Size1, Str2, Size2);
104 }
105 
106 /**
107   Returns the length of a Null-terminated Unicode string.
108 
109   If String is not aligned on a 16-bit boundary, then ASSERT().
110 
111   @param  String   A pointer to a Null-terminated Unicode string.
112   @param  MaxSize  The maximum number of Destination Unicode
113                    char, including terminating null char.
114 
115   @retval 0        If String is NULL.
116   @retval MaxSize  If there is no null character in the first MaxSize characters of String.
117   @return The number of characters that percede the terminating null character.
118 
119 **/
120 UINTN
121 EFIAPI
StrnLenS(IN CONST CHAR16 * String,IN UINTN MaxSize)122 StrnLenS (
123   IN CONST CHAR16              *String,
124   IN UINTN                     MaxSize
125   )
126 {
127   UINTN                             Length;
128 
129   ASSERT (((UINTN) String & BIT0) == 0);
130 
131   //
132   // If String is a null pointer, then the StrnLenS function returns zero.
133   //
134   if (String == NULL) {
135     return 0;
136   }
137 
138   //
139   // Otherwise, the StrnLenS function returns the number of characters that precede the
140   // terminating null character. If there is no null character in the first MaxSize characters of
141   // String then StrnLenS returns MaxSize. At most the first MaxSize characters of String shall
142   // be accessed by StrnLenS.
143   //
144   for (Length = 0; (Length < MaxSize) && (*String != 0); String++, Length++) {
145     ;
146   }
147   return Length;
148 }
149 
150 /**
151   Copies the string pointed to by Source (including the terminating null char)
152   to the array pointed to by Destination.
153 
154   If Destination is not aligned on a 16-bit boundary, then ASSERT().
155   If Source is not aligned on a 16-bit boundary, then ASSERT().
156   If an error would be returned, then the function will also ASSERT().
157 
158   @param  Destination              A pointer to a Null-terminated Unicode string.
159   @param  DestMax                  The maximum number of Destination Unicode
160                                    char, including terminating null char.
161   @param  Source                   A pointer to a Null-terminated Unicode string.
162 
163   @retval RETURN_SUCCESS           String is copied.
164   @retval RETURN_BUFFER_TOO_SMALL  If DestMax is NOT greater than StrLen(Source).
165   @retval RETURN_INVALID_PARAMETER If Destination is NULL.
166                                    If Source is NULL.
167                                    If PcdMaximumUnicodeStringLength is not zero,
168                                     and DestMax is greater than
169                                     PcdMaximumUnicodeStringLength.
170                                    If DestMax is 0.
171   @retval RETURN_ACCESS_DENIED     If Source and Destination overlap.
172 **/
173 RETURN_STATUS
174 EFIAPI
StrCpyS(OUT CHAR16 * Destination,IN UINTN DestMax,IN CONST CHAR16 * Source)175 StrCpyS (
176   OUT CHAR16       *Destination,
177   IN  UINTN        DestMax,
178   IN  CONST CHAR16 *Source
179   )
180 {
181   UINTN            SourceLen;
182 
183   ASSERT (((UINTN) Destination & BIT0) == 0);
184   ASSERT (((UINTN) Source & BIT0) == 0);
185 
186   //
187   // 1. Neither Destination nor Source shall be a null pointer.
188   //
189   SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
190   SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
191 
192   //
193   // 2. DestMax shall not be greater than RSIZE_MAX.
194   //
195   if (RSIZE_MAX != 0) {
196     SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
197   }
198 
199   //
200   // 3. DestMax shall not equal zero.
201   //
202   SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
203 
204   //
205   // 4. DestMax shall be greater than StrnLenS(Source, DestMax).
206   //
207   SourceLen = StrnLenS (Source, DestMax);
208   SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
209 
210   //
211   // 5. Copying shall not take place between objects that overlap.
212   //
213   SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
214 
215   //
216   // The StrCpyS function copies the string pointed to by Source (including the terminating
217   // null character) into the array pointed to by Destination.
218   //
219   while (*Source != 0) {
220     *(Destination++) = *(Source++);
221   }
222   *Destination = 0;
223 
224   return RETURN_SUCCESS;
225 }
226 
227 /**
228   Copies not more than Length successive char from the string pointed to by
229   Source to the array pointed to by Destination. If no null char is copied from
230   Source, then Destination[Length] is always set to null.
231 
232   If Length > 0 and Destination is not aligned on a 16-bit boundary, then ASSERT().
233   If Length > 0 and Source is not aligned on a 16-bit boundary, then ASSERT().
234   If an error would be returned, then the function will also ASSERT().
235 
236   @param  Destination              A pointer to a Null-terminated Unicode string.
237   @param  DestMax                  The maximum number of Destination Unicode
238                                    char, including terminating null char.
239   @param  Source                   A pointer to a Null-terminated Unicode string.
240   @param  Length                   The maximum number of Unicode characters to copy.
241 
242   @retval RETURN_SUCCESS           String is copied.
243   @retval RETURN_BUFFER_TOO_SMALL  If DestMax is NOT greater than
244                                    MIN(StrLen(Source), Length).
245   @retval RETURN_INVALID_PARAMETER If Destination is NULL.
246                                    If Source is NULL.
247                                    If PcdMaximumUnicodeStringLength is not zero,
248                                     and DestMax is greater than
249                                     PcdMaximumUnicodeStringLength.
250                                    If DestMax is 0.
251   @retval RETURN_ACCESS_DENIED     If Source and Destination overlap.
252 **/
253 RETURN_STATUS
254 EFIAPI
StrnCpyS(OUT CHAR16 * Destination,IN UINTN DestMax,IN CONST CHAR16 * Source,IN UINTN Length)255 StrnCpyS (
256   OUT CHAR16       *Destination,
257   IN  UINTN        DestMax,
258   IN  CONST CHAR16 *Source,
259   IN  UINTN        Length
260   )
261 {
262   UINTN            SourceLen;
263 
264   ASSERT (((UINTN) Destination & BIT0) == 0);
265   ASSERT (((UINTN) Source & BIT0) == 0);
266 
267   //
268   // 1. Neither Destination nor Source shall be a null pointer.
269   //
270   SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
271   SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
272 
273   //
274   // 2. Neither DestMax nor Length shall be greater than RSIZE_MAX
275   //
276   if (RSIZE_MAX != 0) {
277     SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
278     SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
279   }
280 
281   //
282   // 3. DestMax shall not equal zero.
283   //
284   SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
285 
286   //
287   // 4. If Length is not less than DestMax, then DestMax shall be greater than StrnLenS(Source, DestMax).
288   //
289   SourceLen = StrnLenS (Source, DestMax);
290   if (Length >= DestMax) {
291     SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
292   }
293 
294   //
295   // 5. Copying shall not take place between objects that overlap.
296   //
297   if (SourceLen > Length) {
298     SourceLen = Length;
299   }
300   SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
301 
302   //
303   // The StrnCpyS function copies not more than Length successive characters (characters that
304   // follow a null character are not copied) from the array pointed to by Source to the array
305   // pointed to by Destination. If no null character was copied from Source, then Destination[Length] is set to a null
306   // character.
307   //
308   while ((*Source != 0) && (SourceLen > 0)) {
309     *(Destination++) = *(Source++);
310     SourceLen--;
311   }
312   *Destination = 0;
313 
314   return RETURN_SUCCESS;
315 }
316 
317 /**
318   Appends a copy of the string pointed to by Source (including the terminating
319   null char) to the end of the string pointed to by Destination.
320 
321   If Destination is not aligned on a 16-bit boundary, then ASSERT().
322   If Source is not aligned on a 16-bit boundary, then ASSERT().
323   If an error would be returned, then the function will also ASSERT().
324 
325   @param  Destination              A pointer to a Null-terminated Unicode string.
326   @param  DestMax                  The maximum number of Destination Unicode
327                                    char, including terminating null char.
328   @param  Source                   A pointer to a Null-terminated Unicode string.
329 
330   @retval RETURN_SUCCESS           String is appended.
331   @retval RETURN_BAD_BUFFER_SIZE   If DestMax is NOT greater than
332                                    StrLen(Destination).
333   @retval RETURN_BUFFER_TOO_SMALL  If (DestMax - StrLen(Destination)) is NOT
334                                    greater than StrLen(Source).
335   @retval RETURN_INVALID_PARAMETER If Destination is NULL.
336                                    If Source is NULL.
337                                    If PcdMaximumUnicodeStringLength is not zero,
338                                     and DestMax is greater than
339                                     PcdMaximumUnicodeStringLength.
340                                    If DestMax is 0.
341   @retval RETURN_ACCESS_DENIED     If Source and Destination overlap.
342 **/
343 RETURN_STATUS
344 EFIAPI
StrCatS(IN OUT CHAR16 * Destination,IN UINTN DestMax,IN CONST CHAR16 * Source)345 StrCatS (
346   IN OUT CHAR16       *Destination,
347   IN     UINTN        DestMax,
348   IN     CONST CHAR16 *Source
349   )
350 {
351   UINTN               DestLen;
352   UINTN               CopyLen;
353   UINTN               SourceLen;
354 
355   ASSERT (((UINTN) Destination & BIT0) == 0);
356   ASSERT (((UINTN) Source & BIT0) == 0);
357 
358   //
359   // Let CopyLen denote the value DestMax - StrnLenS(Destination, DestMax) upon entry to StrCatS.
360   //
361   DestLen = StrnLenS (Destination, DestMax);
362   CopyLen = DestMax - DestLen;
363 
364   //
365   // 1. Neither Destination nor Source shall be a null pointer.
366   //
367   SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
368   SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
369 
370   //
371   // 2. DestMax shall not be greater than RSIZE_MAX.
372   //
373   if (RSIZE_MAX != 0) {
374     SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
375   }
376 
377   //
378   // 3. DestMax shall not equal zero.
379   //
380   SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
381 
382   //
383   // 4. CopyLen shall not equal zero.
384   //
385   SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE);
386 
387   //
388   // 5. CopyLen shall be greater than StrnLenS(Source, CopyLen).
389   //
390   SourceLen = StrnLenS (Source, CopyLen);
391   SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL);
392 
393   //
394   // 6. Copying shall not take place between objects that overlap.
395   //
396   SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
397 
398   //
399   // The StrCatS function appends a copy of the string pointed to by Source (including the
400   // terminating null character) to the end of the string pointed to by Destination. The initial character
401   // from Source overwrites the null character at the end of Destination.
402   //
403   Destination = Destination + DestLen;
404   while (*Source != 0) {
405     *(Destination++) = *(Source++);
406   }
407   *Destination = 0;
408 
409   return RETURN_SUCCESS;
410 }
411 
412 /**
413   Appends not more than Length successive char from the string pointed to by
414   Source to the end of the string pointed to by Destination. If no null char is
415   copied from Source, then Destination[StrLen(Destination) + Length] is always
416   set to null.
417 
418   If Destination is not aligned on a 16-bit boundary, then ASSERT().
419   If Source is not aligned on a 16-bit boundary, then ASSERT().
420   If an error would be returned, then the function will also ASSERT().
421 
422   @param  Destination              A pointer to a Null-terminated Unicode string.
423   @param  DestMax                  The maximum number of Destination Unicode
424                                    char, including terminating null char.
425   @param  Source                   A pointer to a Null-terminated Unicode string.
426   @param  Length                   The maximum number of Unicode characters to copy.
427 
428   @retval RETURN_SUCCESS           String is appended.
429   @retval RETURN_BAD_BUFFER_SIZE   If DestMax is NOT greater than
430                                    StrLen(Destination).
431   @retval RETURN_BUFFER_TOO_SMALL  If (DestMax - StrLen(Destination)) is NOT
432                                    greater than MIN(StrLen(Source), Length).
433   @retval RETURN_INVALID_PARAMETER If Destination is NULL.
434                                    If Source is NULL.
435                                    If PcdMaximumUnicodeStringLength is not zero,
436                                     and DestMax is greater than
437                                     PcdMaximumUnicodeStringLength.
438                                    If DestMax is 0.
439   @retval RETURN_ACCESS_DENIED     If Source and Destination overlap.
440 **/
441 RETURN_STATUS
442 EFIAPI
StrnCatS(IN OUT CHAR16 * Destination,IN UINTN DestMax,IN CONST CHAR16 * Source,IN UINTN Length)443 StrnCatS (
444   IN OUT CHAR16       *Destination,
445   IN     UINTN        DestMax,
446   IN     CONST CHAR16 *Source,
447   IN     UINTN        Length
448   )
449 {
450   UINTN               DestLen;
451   UINTN               CopyLen;
452   UINTN               SourceLen;
453 
454   ASSERT (((UINTN) Destination & BIT0) == 0);
455   ASSERT (((UINTN) Source & BIT0) == 0);
456 
457   //
458   // Let CopyLen denote the value DestMax - StrnLenS(Destination, DestMax) upon entry to StrnCatS.
459   //
460   DestLen = StrnLenS (Destination, DestMax);
461   CopyLen = DestMax - DestLen;
462 
463   //
464   // 1. Neither Destination nor Source shall be a null pointer.
465   //
466   SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
467   SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
468 
469   //
470   // 2. Neither DestMax nor Length shall be greater than RSIZE_MAX.
471   //
472   if (RSIZE_MAX != 0) {
473     SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
474     SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
475   }
476 
477   //
478   // 3. DestMax shall not equal zero.
479   //
480   SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
481 
482   //
483   // 4. CopyLen shall not equal zero.
484   //
485   SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE);
486 
487   //
488   // 5. If Length is not less than CopyLen, then CopyLen shall be greater than StrnLenS(Source, CopyLen).
489   //
490   SourceLen = StrnLenS (Source, CopyLen);
491   if (Length >= CopyLen) {
492     SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL);
493   }
494 
495   //
496   // 6. Copying shall not take place between objects that overlap.
497   //
498   if (SourceLen > Length) {
499     SourceLen = Length;
500   }
501   SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
502 
503   //
504   // The StrnCatS function appends not more than Length successive characters (characters
505   // that follow a null character are not copied) from the array pointed to by Source to the end of
506   // the string pointed to by Destination. The initial character from Source overwrites the null character at
507   // the end of Destination. If no null character was copied from Source, then Destination[DestMax-CopyLen+Length] is set to
508   // a null character.
509   //
510   Destination = Destination + DestLen;
511   while ((*Source != 0) && (SourceLen > 0)) {
512     *(Destination++) = *(Source++);
513     SourceLen--;
514   }
515   *Destination = 0;
516 
517   return RETURN_SUCCESS;
518 }
519 
520 /**
521   Returns the length of a Null-terminated Ascii string.
522 
523   @param  String   A pointer to a Null-terminated Ascii string.
524   @param  MaxSize  The maximum number of Destination Ascii
525                    char, including terminating null char.
526 
527   @retval 0        If String is NULL.
528   @retval MaxSize  If there is no null character in the first MaxSize characters of String.
529   @return The number of characters that percede the terminating null character.
530 
531 **/
532 UINTN
533 EFIAPI
AsciiStrnLenS(IN CONST CHAR8 * String,IN UINTN MaxSize)534 AsciiStrnLenS (
535   IN CONST CHAR8               *String,
536   IN UINTN                     MaxSize
537   )
538 {
539   UINTN                             Length;
540 
541   //
542   // If String is a null pointer, then the AsciiStrnLenS function returns zero.
543   //
544   if (String == NULL) {
545     return 0;
546   }
547 
548   //
549   // Otherwise, the AsciiStrnLenS function returns the number of characters that precede the
550   // terminating null character. If there is no null character in the first MaxSize characters of
551   // String then AsciiStrnLenS returns MaxSize. At most the first MaxSize characters of String shall
552   // be accessed by AsciiStrnLenS.
553   //
554   for (Length = 0; (Length < MaxSize) && (*String != 0); String++, Length++) {
555     ;
556   }
557   return Length;
558 }
559 
560 /**
561   Copies the string pointed to by Source (including the terminating null char)
562   to the array pointed to by Destination.
563 
564   If an error would be returned, then the function will also ASSERT().
565 
566   @param  Destination              A pointer to a Null-terminated Ascii string.
567   @param  DestMax                  The maximum number of Destination Ascii
568                                    char, including terminating null char.
569   @param  Source                   A pointer to a Null-terminated Ascii string.
570 
571   @retval RETURN_SUCCESS           String is copied.
572   @retval RETURN_BUFFER_TOO_SMALL  If DestMax is NOT greater than StrLen(Source).
573   @retval RETURN_INVALID_PARAMETER If Destination is NULL.
574                                    If Source is NULL.
575                                    If PcdMaximumAsciiStringLength is not zero,
576                                     and DestMax is greater than
577                                     PcdMaximumAsciiStringLength.
578                                    If DestMax is 0.
579   @retval RETURN_ACCESS_DENIED     If Source and Destination overlap.
580 **/
581 RETURN_STATUS
582 EFIAPI
AsciiStrCpyS(OUT CHAR8 * Destination,IN UINTN DestMax,IN CONST CHAR8 * Source)583 AsciiStrCpyS (
584   OUT CHAR8        *Destination,
585   IN  UINTN        DestMax,
586   IN  CONST CHAR8  *Source
587   )
588 {
589   UINTN            SourceLen;
590 
591   //
592   // 1. Neither Destination nor Source shall be a null pointer.
593   //
594   SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
595   SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
596 
597   //
598   // 2. DestMax shall not be greater than ASCII_RSIZE_MAX.
599   //
600   if (ASCII_RSIZE_MAX != 0) {
601     SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
602   }
603 
604   //
605   // 3. DestMax shall not equal zero.
606   //
607   SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
608 
609   //
610   // 4. DestMax shall be greater than AsciiStrnLenS(Source, DestMax).
611   //
612   SourceLen = AsciiStrnLenS (Source, DestMax);
613   SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
614 
615   //
616   // 5. Copying shall not take place between objects that overlap.
617   //
618   SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
619 
620   //
621   // The AsciiStrCpyS function copies the string pointed to by Source (including the terminating
622   // null character) into the array pointed to by Destination.
623   //
624   while (*Source != 0) {
625     *(Destination++) = *(Source++);
626   }
627   *Destination = 0;
628 
629   return RETURN_SUCCESS;
630 }
631 
632 /**
633   Copies not more than Length successive char from the string pointed to by
634   Source to the array pointed to by Destination. If no null char is copied from
635   Source, then Destination[Length] is always set to null.
636 
637   If an error would be returned, then the function will also ASSERT().
638 
639   @param  Destination              A pointer to a Null-terminated Ascii string.
640   @param  DestMax                  The maximum number of Destination Ascii
641                                    char, including terminating null char.
642   @param  Source                   A pointer to a Null-terminated Ascii string.
643   @param  Length                   The maximum number of Ascii characters to copy.
644 
645   @retval RETURN_SUCCESS           String is copied.
646   @retval RETURN_BUFFER_TOO_SMALL  If DestMax is NOT greater than
647                                    MIN(StrLen(Source), Length).
648   @retval RETURN_INVALID_PARAMETER If Destination is NULL.
649                                    If Source is NULL.
650                                    If PcdMaximumAsciiStringLength is not zero,
651                                     and DestMax is greater than
652                                     PcdMaximumAsciiStringLength.
653                                    If DestMax is 0.
654   @retval RETURN_ACCESS_DENIED     If Source and Destination overlap.
655 **/
656 RETURN_STATUS
657 EFIAPI
AsciiStrnCpyS(OUT CHAR8 * Destination,IN UINTN DestMax,IN CONST CHAR8 * Source,IN UINTN Length)658 AsciiStrnCpyS (
659   OUT CHAR8        *Destination,
660   IN  UINTN        DestMax,
661   IN  CONST CHAR8  *Source,
662   IN  UINTN        Length
663   )
664 {
665   UINTN            SourceLen;
666 
667   //
668   // 1. Neither Destination nor Source shall be a null pointer.
669   //
670   SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
671   SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
672 
673   //
674   // 2. Neither DestMax nor Length shall be greater than ASCII_RSIZE_MAX
675   //
676   if (ASCII_RSIZE_MAX != 0) {
677     SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
678     SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
679   }
680 
681   //
682   // 3. DestMax shall not equal zero.
683   //
684   SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
685 
686   //
687   // 4. If Length is not less than DestMax, then DestMax shall be greater than AsciiStrnLenS(Source, DestMax).
688   //
689   SourceLen = AsciiStrnLenS (Source, DestMax);
690   if (Length >= DestMax) {
691     SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
692   }
693 
694   //
695   // 5. Copying shall not take place between objects that overlap.
696   //
697   if (SourceLen > Length) {
698     SourceLen = Length;
699   }
700   SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
701 
702   //
703   // The AsciiStrnCpyS function copies not more than Length successive characters (characters that
704   // follow a null character are not copied) from the array pointed to by Source to the array
705   // pointed to by Destination. If no null character was copied from Source, then Destination[Length] is set to a null
706   // character.
707   //
708   while ((*Source != 0) && (SourceLen > 0)) {
709     *(Destination++) = *(Source++);
710     SourceLen--;
711   }
712   *Destination = 0;
713 
714   return RETURN_SUCCESS;
715 }
716 
717 /**
718   Appends a copy of the string pointed to by Source (including the terminating
719   null char) to the end of the string pointed to by Destination.
720 
721   If an error would be returned, then the function will also ASSERT().
722 
723   @param  Destination              A pointer to a Null-terminated Ascii string.
724   @param  DestMax                  The maximum number of Destination Ascii
725                                    char, including terminating null char.
726   @param  Source                   A pointer to a Null-terminated Ascii string.
727 
728   @retval RETURN_SUCCESS           String is appended.
729   @retval RETURN_BAD_BUFFER_SIZE   If DestMax is NOT greater than
730                                    StrLen(Destination).
731   @retval RETURN_BUFFER_TOO_SMALL  If (DestMax - StrLen(Destination)) is NOT
732                                    greater than StrLen(Source).
733   @retval RETURN_INVALID_PARAMETER If Destination is NULL.
734                                    If Source is NULL.
735                                    If PcdMaximumAsciiStringLength is not zero,
736                                     and DestMax is greater than
737                                     PcdMaximumAsciiStringLength.
738                                    If DestMax is 0.
739   @retval RETURN_ACCESS_DENIED     If Source and Destination overlap.
740 **/
741 RETURN_STATUS
742 EFIAPI
AsciiStrCatS(IN OUT CHAR8 * Destination,IN UINTN DestMax,IN CONST CHAR8 * Source)743 AsciiStrCatS (
744   IN OUT CHAR8        *Destination,
745   IN     UINTN        DestMax,
746   IN     CONST CHAR8  *Source
747   )
748 {
749   UINTN               DestLen;
750   UINTN               CopyLen;
751   UINTN               SourceLen;
752 
753   //
754   // Let CopyLen denote the value DestMax - AsciiStrnLenS(Destination, DestMax) upon entry to AsciiStrCatS.
755   //
756   DestLen = AsciiStrnLenS (Destination, DestMax);
757   CopyLen = DestMax - DestLen;
758 
759   //
760   // 1. Neither Destination nor Source shall be a null pointer.
761   //
762   SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
763   SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
764 
765   //
766   // 2. DestMax shall not be greater than ASCII_RSIZE_MAX.
767   //
768   if (ASCII_RSIZE_MAX != 0) {
769     SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
770   }
771 
772   //
773   // 3. DestMax shall not equal zero.
774   //
775   SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
776 
777   //
778   // 4. CopyLen shall not equal zero.
779   //
780   SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE);
781 
782   //
783   // 5. CopyLen shall be greater than AsciiStrnLenS(Source, CopyLen).
784   //
785   SourceLen = AsciiStrnLenS (Source, CopyLen);
786   SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL);
787 
788   //
789   // 6. Copying shall not take place between objects that overlap.
790   //
791   SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
792 
793   //
794   // The AsciiStrCatS function appends a copy of the string pointed to by Source (including the
795   // terminating null character) to the end of the string pointed to by Destination. The initial character
796   // from Source overwrites the null character at the end of Destination.
797   //
798   Destination = Destination + DestLen;
799   while (*Source != 0) {
800     *(Destination++) = *(Source++);
801   }
802   *Destination = 0;
803 
804   return RETURN_SUCCESS;
805 }
806 
807 /**
808   Appends not more than Length successive char from the string pointed to by
809   Source to the end of the string pointed to by Destination. If no null char is
810   copied from Source, then Destination[StrLen(Destination) + Length] is always
811   set to null.
812 
813   If an error would be returned, then the function will also ASSERT().
814 
815   @param  Destination              A pointer to a Null-terminated Ascii string.
816   @param  DestMax                  The maximum number of Destination Ascii
817                                    char, including terminating null char.
818   @param  Source                   A pointer to a Null-terminated Ascii string.
819   @param  Length                   The maximum number of Ascii characters to copy.
820 
821   @retval RETURN_SUCCESS           String is appended.
822   @retval RETURN_BAD_BUFFER_SIZE   If DestMax is NOT greater than
823                                    StrLen(Destination).
824   @retval RETURN_BUFFER_TOO_SMALL  If (DestMax - StrLen(Destination)) is NOT
825                                    greater than MIN(StrLen(Source), Length).
826   @retval RETURN_INVALID_PARAMETER If Destination is NULL.
827                                    If Source is NULL.
828                                    If PcdMaximumAsciiStringLength is not zero,
829                                     and DestMax is greater than
830                                     PcdMaximumAsciiStringLength.
831                                    If DestMax is 0.
832   @retval RETURN_ACCESS_DENIED     If Source and Destination overlap.
833 **/
834 RETURN_STATUS
835 EFIAPI
AsciiStrnCatS(IN OUT CHAR8 * Destination,IN UINTN DestMax,IN CONST CHAR8 * Source,IN UINTN Length)836 AsciiStrnCatS (
837   IN OUT CHAR8        *Destination,
838   IN     UINTN        DestMax,
839   IN     CONST CHAR8  *Source,
840   IN     UINTN        Length
841   )
842 {
843   UINTN               DestLen;
844   UINTN               CopyLen;
845   UINTN               SourceLen;
846 
847   //
848   // Let CopyLen denote the value DestMax - AsciiStrnLenS(Destination, DestMax) upon entry to AsciiStrnCatS.
849   //
850   DestLen = AsciiStrnLenS (Destination, DestMax);
851   CopyLen = DestMax - DestLen;
852 
853   //
854   // 1. Neither Destination nor Source shall be a null pointer.
855   //
856   SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
857   SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
858 
859   //
860   // 2. Neither DestMax nor Length shall be greater than ASCII_RSIZE_MAX.
861   //
862   if (ASCII_RSIZE_MAX != 0) {
863     SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
864     SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
865   }
866 
867   //
868   // 3. DestMax shall not equal zero.
869   //
870   SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
871 
872   //
873   // 4. CopyLen shall not equal zero.
874   //
875   SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE);
876 
877   //
878   // 5. If Length is not less than CopyLen, then CopyLen shall be greater than AsciiStrnLenS(Source, CopyLen).
879   //
880   SourceLen = AsciiStrnLenS (Source, CopyLen);
881   if (Length >= CopyLen) {
882     SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL);
883   }
884 
885   //
886   // 6. Copying shall not take place between objects that overlap.
887   //
888   if (SourceLen > Length) {
889     SourceLen = Length;
890   }
891   SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
892 
893   //
894   // The AsciiStrnCatS function appends not more than Length successive characters (characters
895   // that follow a null character are not copied) from the array pointed to by Source to the end of
896   // the string pointed to by Destination. The initial character from Source overwrites the null character at
897   // the end of Destination. If no null character was copied from Source, then Destination[DestMax-CopyLen+Length] is set to
898   // a null character.
899   //
900   Destination = Destination + DestLen;
901   while ((*Source != 0) && (SourceLen > 0)) {
902     *(Destination++) = *(Source++);
903     SourceLen--;
904   }
905   *Destination = 0;
906 
907   return RETURN_SUCCESS;
908 }
909