]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/BaseLib/SafeString.c
e4c0759c704adae6d9e329a1c25f44df8ecf9cab
[mirror_edk2.git] / MdePkg / Library / BaseLib / SafeString.c
1 /** @file
2 Safe String functions.
3
4 Copyright (c) 2014 - 2016, 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
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
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
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 This function is similar as strlen_s defined in C11.
110
111 If String is not aligned on a 16-bit boundary, then ASSERT().
112
113 @param String A pointer to a Null-terminated Unicode string.
114 @param MaxSize The maximum number of Destination Unicode
115 char, including terminating null char.
116
117 @retval 0 If String is NULL.
118 @retval MaxSize If there is no null character in the first MaxSize characters of String.
119 @return The number of characters that percede the terminating null character.
120
121 **/
122 UINTN
123 EFIAPI
124 StrnLenS (
125 IN CONST CHAR16 *String,
126 IN UINTN MaxSize
127 )
128 {
129 UINTN Length;
130
131 ASSERT (((UINTN) String & BIT0) == 0);
132
133 //
134 // If String is a null pointer, then the StrnLenS function returns zero.
135 //
136 if (String == NULL) {
137 return 0;
138 }
139
140 //
141 // Otherwise, the StrnLenS function returns the number of characters that precede the
142 // terminating null character. If there is no null character in the first MaxSize characters of
143 // String then StrnLenS returns MaxSize. At most the first MaxSize characters of String shall
144 // be accessed by StrnLenS.
145 //
146 Length = 0;
147 while (String[Length] != 0) {
148 if (Length >= MaxSize - 1) {
149 return MaxSize;
150 }
151 Length++;
152 }
153 return Length;
154 }
155
156 /**
157 Copies the string pointed to by Source (including the terminating null char)
158 to the array pointed to by Destination.
159
160 This function is similar as strcpy_s defined in C11.
161
162 If Destination is not aligned on a 16-bit boundary, then ASSERT().
163 If Source is not aligned on a 16-bit boundary, then ASSERT().
164 If an error would be returned, then the function will also ASSERT().
165
166 If an error is returned, then the Destination is unmodified.
167
168 @param Destination A pointer to a Null-terminated Unicode string.
169 @param DestMax The maximum number of Destination Unicode
170 char, including terminating null char.
171 @param Source A pointer to a Null-terminated Unicode string.
172
173 @retval RETURN_SUCCESS String is copied.
174 @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than StrLen(Source).
175 @retval RETURN_INVALID_PARAMETER If Destination is NULL.
176 If Source is NULL.
177 If PcdMaximumUnicodeStringLength is not zero,
178 and DestMax is greater than
179 PcdMaximumUnicodeStringLength.
180 If DestMax is 0.
181 @retval RETURN_ACCESS_DENIED If Source and Destination overlap.
182 **/
183 RETURN_STATUS
184 EFIAPI
185 StrCpyS (
186 OUT CHAR16 *Destination,
187 IN UINTN DestMax,
188 IN CONST CHAR16 *Source
189 )
190 {
191 UINTN SourceLen;
192
193 ASSERT (((UINTN) Destination & BIT0) == 0);
194 ASSERT (((UINTN) Source & BIT0) == 0);
195
196 //
197 // 1. Neither Destination nor Source shall be a null pointer.
198 //
199 SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
200 SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
201
202 //
203 // 2. DestMax shall not be greater than RSIZE_MAX.
204 //
205 if (RSIZE_MAX != 0) {
206 SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
207 }
208
209 //
210 // 3. DestMax shall not equal zero.
211 //
212 SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
213
214 //
215 // 4. DestMax shall be greater than StrnLenS(Source, DestMax).
216 //
217 SourceLen = StrnLenS (Source, DestMax);
218 SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
219
220 //
221 // 5. Copying shall not take place between objects that overlap.
222 //
223 SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
224
225 //
226 // The StrCpyS function copies the string pointed to by Source (including the terminating
227 // null character) into the array pointed to by Destination.
228 //
229 while (*Source != 0) {
230 *(Destination++) = *(Source++);
231 }
232 *Destination = 0;
233
234 return RETURN_SUCCESS;
235 }
236
237 /**
238 Copies not more than Length successive char from the string pointed to by
239 Source to the array pointed to by Destination. If no null char is copied from
240 Source, then Destination[Length] is always set to null.
241
242 This function is similar as strncpy_s defined in C11.
243
244 If Length > 0 and Destination is not aligned on a 16-bit boundary, then ASSERT().
245 If Length > 0 and Source is not aligned on a 16-bit boundary, then ASSERT().
246 If an error would be returned, then the function will also ASSERT().
247
248 If an error is returned, then the Destination is unmodified.
249
250 @param Destination A pointer to a Null-terminated Unicode string.
251 @param DestMax The maximum number of Destination Unicode
252 char, including terminating null char.
253 @param Source A pointer to a Null-terminated Unicode string.
254 @param Length The maximum number of Unicode characters to copy.
255
256 @retval RETURN_SUCCESS String is copied.
257 @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than
258 MIN(StrLen(Source), Length).
259 @retval RETURN_INVALID_PARAMETER If Destination is NULL.
260 If Source is NULL.
261 If PcdMaximumUnicodeStringLength is not zero,
262 and DestMax is greater than
263 PcdMaximumUnicodeStringLength.
264 If DestMax is 0.
265 @retval RETURN_ACCESS_DENIED If Source and Destination overlap.
266 **/
267 RETURN_STATUS
268 EFIAPI
269 StrnCpyS (
270 OUT CHAR16 *Destination,
271 IN UINTN DestMax,
272 IN CONST CHAR16 *Source,
273 IN UINTN Length
274 )
275 {
276 UINTN SourceLen;
277
278 ASSERT (((UINTN) Destination & BIT0) == 0);
279 ASSERT (((UINTN) Source & BIT0) == 0);
280
281 //
282 // 1. Neither Destination nor Source shall be a null pointer.
283 //
284 SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
285 SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
286
287 //
288 // 2. Neither DestMax nor Length shall be greater than RSIZE_MAX
289 //
290 if (RSIZE_MAX != 0) {
291 SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
292 SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
293 }
294
295 //
296 // 3. DestMax shall not equal zero.
297 //
298 SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
299
300 //
301 // 4. If Length is not less than DestMax, then DestMax shall be greater than StrnLenS(Source, DestMax).
302 //
303 SourceLen = StrnLenS (Source, DestMax);
304 if (Length >= DestMax) {
305 SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
306 }
307
308 //
309 // 5. Copying shall not take place between objects that overlap.
310 //
311 if (SourceLen > Length) {
312 SourceLen = Length;
313 }
314 SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
315
316 //
317 // The StrnCpyS function copies not more than Length successive characters (characters that
318 // follow a null character are not copied) from the array pointed to by Source to the array
319 // pointed to by Destination. If no null character was copied from Source, then Destination[Length] is set to a null
320 // character.
321 //
322 while ((*Source != 0) && (SourceLen > 0)) {
323 *(Destination++) = *(Source++);
324 SourceLen--;
325 }
326 *Destination = 0;
327
328 return RETURN_SUCCESS;
329 }
330
331 /**
332 Appends a copy of the string pointed to by Source (including the terminating
333 null char) to the end of the string pointed to by Destination.
334
335 This function is similar as strcat_s defined in C11.
336
337 If Destination is not aligned on a 16-bit boundary, then ASSERT().
338 If Source is not aligned on a 16-bit boundary, then ASSERT().
339 If an error would be returned, then the function will also ASSERT().
340
341 If an error is returned, then the Destination is unmodified.
342
343 @param Destination A pointer to a Null-terminated Unicode string.
344 @param DestMax The maximum number of Destination Unicode
345 char, including terminating null char.
346 @param Source A pointer to a Null-terminated Unicode string.
347
348 @retval RETURN_SUCCESS String is appended.
349 @retval RETURN_BAD_BUFFER_SIZE If DestMax is NOT greater than
350 StrLen(Destination).
351 @retval RETURN_BUFFER_TOO_SMALL If (DestMax - StrLen(Destination)) is NOT
352 greater than StrLen(Source).
353 @retval RETURN_INVALID_PARAMETER If Destination is NULL.
354 If Source is NULL.
355 If PcdMaximumUnicodeStringLength is not zero,
356 and DestMax is greater than
357 PcdMaximumUnicodeStringLength.
358 If DestMax is 0.
359 @retval RETURN_ACCESS_DENIED If Source and Destination overlap.
360 **/
361 RETURN_STATUS
362 EFIAPI
363 StrCatS (
364 IN OUT CHAR16 *Destination,
365 IN UINTN DestMax,
366 IN CONST CHAR16 *Source
367 )
368 {
369 UINTN DestLen;
370 UINTN CopyLen;
371 UINTN SourceLen;
372
373 ASSERT (((UINTN) Destination & BIT0) == 0);
374 ASSERT (((UINTN) Source & BIT0) == 0);
375
376 //
377 // Let CopyLen denote the value DestMax - StrnLenS(Destination, DestMax) upon entry to StrCatS.
378 //
379 DestLen = StrnLenS (Destination, DestMax);
380 CopyLen = DestMax - DestLen;
381
382 //
383 // 1. Neither Destination nor Source shall be a null pointer.
384 //
385 SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
386 SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
387
388 //
389 // 2. DestMax shall not be greater than RSIZE_MAX.
390 //
391 if (RSIZE_MAX != 0) {
392 SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
393 }
394
395 //
396 // 3. DestMax shall not equal zero.
397 //
398 SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
399
400 //
401 // 4. CopyLen shall not equal zero.
402 //
403 SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE);
404
405 //
406 // 5. CopyLen shall be greater than StrnLenS(Source, CopyLen).
407 //
408 SourceLen = StrnLenS (Source, CopyLen);
409 SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL);
410
411 //
412 // 6. Copying shall not take place between objects that overlap.
413 //
414 SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
415
416 //
417 // The StrCatS function appends a copy of the string pointed to by Source (including the
418 // terminating null character) to the end of the string pointed to by Destination. The initial character
419 // from Source overwrites the null character at the end of Destination.
420 //
421 Destination = Destination + DestLen;
422 while (*Source != 0) {
423 *(Destination++) = *(Source++);
424 }
425 *Destination = 0;
426
427 return RETURN_SUCCESS;
428 }
429
430 /**
431 Appends not more than Length successive char from the string pointed to by
432 Source to the end of the string pointed to by Destination. If no null char is
433 copied from Source, then Destination[StrLen(Destination) + Length] is always
434 set to null.
435
436 This function is similar as strncat_s defined in C11.
437
438 If Destination is not aligned on a 16-bit boundary, then ASSERT().
439 If Source is not aligned on a 16-bit boundary, then ASSERT().
440 If an error would be returned, then the function will also ASSERT().
441
442 If an error is returned, then the Destination is unmodified.
443
444 @param Destination A pointer to a Null-terminated Unicode string.
445 @param DestMax The maximum number of Destination Unicode
446 char, including terminating null char.
447 @param Source A pointer to a Null-terminated Unicode string.
448 @param Length The maximum number of Unicode characters to copy.
449
450 @retval RETURN_SUCCESS String is appended.
451 @retval RETURN_BAD_BUFFER_SIZE If DestMax is NOT greater than
452 StrLen(Destination).
453 @retval RETURN_BUFFER_TOO_SMALL If (DestMax - StrLen(Destination)) is NOT
454 greater than MIN(StrLen(Source), Length).
455 @retval RETURN_INVALID_PARAMETER If Destination is NULL.
456 If Source is NULL.
457 If PcdMaximumUnicodeStringLength is not zero,
458 and DestMax is greater than
459 PcdMaximumUnicodeStringLength.
460 If DestMax is 0.
461 @retval RETURN_ACCESS_DENIED If Source and Destination overlap.
462 **/
463 RETURN_STATUS
464 EFIAPI
465 StrnCatS (
466 IN OUT CHAR16 *Destination,
467 IN UINTN DestMax,
468 IN CONST CHAR16 *Source,
469 IN UINTN Length
470 )
471 {
472 UINTN DestLen;
473 UINTN CopyLen;
474 UINTN SourceLen;
475
476 ASSERT (((UINTN) Destination & BIT0) == 0);
477 ASSERT (((UINTN) Source & BIT0) == 0);
478
479 //
480 // Let CopyLen denote the value DestMax - StrnLenS(Destination, DestMax) upon entry to StrnCatS.
481 //
482 DestLen = StrnLenS (Destination, DestMax);
483 CopyLen = DestMax - DestLen;
484
485 //
486 // 1. Neither Destination nor Source shall be a null pointer.
487 //
488 SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
489 SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
490
491 //
492 // 2. Neither DestMax nor Length shall be greater than RSIZE_MAX.
493 //
494 if (RSIZE_MAX != 0) {
495 SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
496 SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
497 }
498
499 //
500 // 3. DestMax shall not equal zero.
501 //
502 SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
503
504 //
505 // 4. CopyLen shall not equal zero.
506 //
507 SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE);
508
509 //
510 // 5. If Length is not less than CopyLen, then CopyLen shall be greater than StrnLenS(Source, CopyLen).
511 //
512 SourceLen = StrnLenS (Source, CopyLen);
513 if (Length >= CopyLen) {
514 SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL);
515 }
516
517 //
518 // 6. Copying shall not take place between objects that overlap.
519 //
520 if (SourceLen > Length) {
521 SourceLen = Length;
522 }
523 SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
524
525 //
526 // The StrnCatS function appends not more than Length successive characters (characters
527 // that follow a null character are not copied) from the array pointed to by Source to the end of
528 // the string pointed to by Destination. The initial character from Source overwrites the null character at
529 // the end of Destination. If no null character was copied from Source, then Destination[DestMax-CopyLen+Length] is set to
530 // a null character.
531 //
532 Destination = Destination + DestLen;
533 while ((*Source != 0) && (SourceLen > 0)) {
534 *(Destination++) = *(Source++);
535 SourceLen--;
536 }
537 *Destination = 0;
538
539 return RETURN_SUCCESS;
540 }
541
542 /**
543 Returns the length of a Null-terminated Ascii string.
544
545 This function is similar as strlen_s defined in C11.
546
547 @param String A pointer to a Null-terminated Ascii string.
548 @param MaxSize The maximum number of Destination Ascii
549 char, including terminating null char.
550
551 @retval 0 If String is NULL.
552 @retval MaxSize If there is no null character in the first MaxSize characters of String.
553 @return The number of characters that percede the terminating null character.
554
555 **/
556 UINTN
557 EFIAPI
558 AsciiStrnLenS (
559 IN CONST CHAR8 *String,
560 IN UINTN MaxSize
561 )
562 {
563 UINTN Length;
564
565 //
566 // If String is a null pointer, then the AsciiStrnLenS function returns zero.
567 //
568 if (String == NULL) {
569 return 0;
570 }
571
572 //
573 // Otherwise, the AsciiStrnLenS function returns the number of characters that precede the
574 // terminating null character. If there is no null character in the first MaxSize characters of
575 // String then AsciiStrnLenS returns MaxSize. At most the first MaxSize characters of String shall
576 // be accessed by AsciiStrnLenS.
577 //
578 Length = 0;
579 while (String[Length] != 0) {
580 if (Length >= MaxSize - 1) {
581 return MaxSize;
582 }
583 Length++;
584 }
585 return Length;
586 }
587
588 /**
589 Copies the string pointed to by Source (including the terminating null char)
590 to the array pointed to by Destination.
591
592 This function is similar as strcpy_s defined in C11.
593
594 If an error would be returned, then the function will also ASSERT().
595
596 If an error is returned, then the Destination is unmodified.
597
598 @param Destination A pointer to a Null-terminated Ascii string.
599 @param DestMax The maximum number of Destination Ascii
600 char, including terminating null char.
601 @param Source A pointer to a Null-terminated Ascii string.
602
603 @retval RETURN_SUCCESS String is copied.
604 @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than StrLen(Source).
605 @retval RETURN_INVALID_PARAMETER If Destination is NULL.
606 If Source is NULL.
607 If PcdMaximumAsciiStringLength is not zero,
608 and DestMax is greater than
609 PcdMaximumAsciiStringLength.
610 If DestMax is 0.
611 @retval RETURN_ACCESS_DENIED If Source and Destination overlap.
612 **/
613 RETURN_STATUS
614 EFIAPI
615 AsciiStrCpyS (
616 OUT CHAR8 *Destination,
617 IN UINTN DestMax,
618 IN CONST CHAR8 *Source
619 )
620 {
621 UINTN SourceLen;
622
623 //
624 // 1. Neither Destination nor Source shall be a null pointer.
625 //
626 SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
627 SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
628
629 //
630 // 2. DestMax shall not be greater than ASCII_RSIZE_MAX.
631 //
632 if (ASCII_RSIZE_MAX != 0) {
633 SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
634 }
635
636 //
637 // 3. DestMax shall not equal zero.
638 //
639 SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
640
641 //
642 // 4. DestMax shall be greater than AsciiStrnLenS(Source, DestMax).
643 //
644 SourceLen = AsciiStrnLenS (Source, DestMax);
645 SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
646
647 //
648 // 5. Copying shall not take place between objects that overlap.
649 //
650 SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
651
652 //
653 // The AsciiStrCpyS function copies the string pointed to by Source (including the terminating
654 // null character) into the array pointed to by Destination.
655 //
656 while (*Source != 0) {
657 *(Destination++) = *(Source++);
658 }
659 *Destination = 0;
660
661 return RETURN_SUCCESS;
662 }
663
664 /**
665 Copies not more than Length successive char from the string pointed to by
666 Source to the array pointed to by Destination. If no null char is copied from
667 Source, then Destination[Length] is always set to null.
668
669 This function is similar as strncpy_s defined in C11.
670
671 If an error would be returned, then the function will also ASSERT().
672
673 If an error is returned, then the Destination is unmodified.
674
675 @param Destination A pointer to a Null-terminated Ascii string.
676 @param DestMax The maximum number of Destination Ascii
677 char, including terminating null char.
678 @param Source A pointer to a Null-terminated Ascii string.
679 @param Length The maximum number of Ascii characters to copy.
680
681 @retval RETURN_SUCCESS String is copied.
682 @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than
683 MIN(StrLen(Source), Length).
684 @retval RETURN_INVALID_PARAMETER If Destination is NULL.
685 If Source is NULL.
686 If PcdMaximumAsciiStringLength is not zero,
687 and DestMax is greater than
688 PcdMaximumAsciiStringLength.
689 If DestMax is 0.
690 @retval RETURN_ACCESS_DENIED If Source and Destination overlap.
691 **/
692 RETURN_STATUS
693 EFIAPI
694 AsciiStrnCpyS (
695 OUT CHAR8 *Destination,
696 IN UINTN DestMax,
697 IN CONST CHAR8 *Source,
698 IN UINTN Length
699 )
700 {
701 UINTN SourceLen;
702
703 //
704 // 1. Neither Destination nor Source shall be a null pointer.
705 //
706 SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
707 SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
708
709 //
710 // 2. Neither DestMax nor Length shall be greater than ASCII_RSIZE_MAX
711 //
712 if (ASCII_RSIZE_MAX != 0) {
713 SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
714 SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
715 }
716
717 //
718 // 3. DestMax shall not equal zero.
719 //
720 SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
721
722 //
723 // 4. If Length is not less than DestMax, then DestMax shall be greater than AsciiStrnLenS(Source, DestMax).
724 //
725 SourceLen = AsciiStrnLenS (Source, DestMax);
726 if (Length >= DestMax) {
727 SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
728 }
729
730 //
731 // 5. Copying shall not take place between objects that overlap.
732 //
733 if (SourceLen > Length) {
734 SourceLen = Length;
735 }
736 SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
737
738 //
739 // The AsciiStrnCpyS function copies not more than Length successive characters (characters that
740 // follow a null character are not copied) from the array pointed to by Source to the array
741 // pointed to by Destination. If no null character was copied from Source, then Destination[Length] is set to a null
742 // character.
743 //
744 while ((*Source != 0) && (SourceLen > 0)) {
745 *(Destination++) = *(Source++);
746 SourceLen--;
747 }
748 *Destination = 0;
749
750 return RETURN_SUCCESS;
751 }
752
753 /**
754 Appends a copy of the string pointed to by Source (including the terminating
755 null char) to the end of the string pointed to by Destination.
756
757 This function is similar as strcat_s defined in C11.
758
759 If an error would be returned, then the function will also ASSERT().
760
761 If an error is returned, then the Destination is unmodified.
762
763 @param Destination A pointer to a Null-terminated Ascii string.
764 @param DestMax The maximum number of Destination Ascii
765 char, including terminating null char.
766 @param Source A pointer to a Null-terminated Ascii string.
767
768 @retval RETURN_SUCCESS String is appended.
769 @retval RETURN_BAD_BUFFER_SIZE If DestMax is NOT greater than
770 StrLen(Destination).
771 @retval RETURN_BUFFER_TOO_SMALL If (DestMax - StrLen(Destination)) is NOT
772 greater than StrLen(Source).
773 @retval RETURN_INVALID_PARAMETER If Destination is NULL.
774 If Source is NULL.
775 If PcdMaximumAsciiStringLength is not zero,
776 and DestMax is greater than
777 PcdMaximumAsciiStringLength.
778 If DestMax is 0.
779 @retval RETURN_ACCESS_DENIED If Source and Destination overlap.
780 **/
781 RETURN_STATUS
782 EFIAPI
783 AsciiStrCatS (
784 IN OUT CHAR8 *Destination,
785 IN UINTN DestMax,
786 IN CONST CHAR8 *Source
787 )
788 {
789 UINTN DestLen;
790 UINTN CopyLen;
791 UINTN SourceLen;
792
793 //
794 // Let CopyLen denote the value DestMax - AsciiStrnLenS(Destination, DestMax) upon entry to AsciiStrCatS.
795 //
796 DestLen = AsciiStrnLenS (Destination, DestMax);
797 CopyLen = DestMax - DestLen;
798
799 //
800 // 1. Neither Destination nor Source shall be a null pointer.
801 //
802 SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
803 SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
804
805 //
806 // 2. DestMax shall not be greater than ASCII_RSIZE_MAX.
807 //
808 if (ASCII_RSIZE_MAX != 0) {
809 SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
810 }
811
812 //
813 // 3. DestMax shall not equal zero.
814 //
815 SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
816
817 //
818 // 4. CopyLen shall not equal zero.
819 //
820 SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE);
821
822 //
823 // 5. CopyLen shall be greater than AsciiStrnLenS(Source, CopyLen).
824 //
825 SourceLen = AsciiStrnLenS (Source, CopyLen);
826 SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL);
827
828 //
829 // 6. Copying shall not take place between objects that overlap.
830 //
831 SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
832
833 //
834 // The AsciiStrCatS function appends a copy of the string pointed to by Source (including the
835 // terminating null character) to the end of the string pointed to by Destination. The initial character
836 // from Source overwrites the null character at the end of Destination.
837 //
838 Destination = Destination + DestLen;
839 while (*Source != 0) {
840 *(Destination++) = *(Source++);
841 }
842 *Destination = 0;
843
844 return RETURN_SUCCESS;
845 }
846
847 /**
848 Appends not more than Length successive char from the string pointed to by
849 Source to the end of the string pointed to by Destination. If no null char is
850 copied from Source, then Destination[StrLen(Destination) + Length] is always
851 set to null.
852
853 This function is similar as strncat_s defined in C11.
854
855 If an error would be returned, then the function will also ASSERT().
856
857 If an error is returned, then the Destination is unmodified.
858
859 @param Destination A pointer to a Null-terminated Ascii string.
860 @param DestMax The maximum number of Destination Ascii
861 char, including terminating null char.
862 @param Source A pointer to a Null-terminated Ascii string.
863 @param Length The maximum number of Ascii characters to copy.
864
865 @retval RETURN_SUCCESS String is appended.
866 @retval RETURN_BAD_BUFFER_SIZE If DestMax is NOT greater than
867 StrLen(Destination).
868 @retval RETURN_BUFFER_TOO_SMALL If (DestMax - StrLen(Destination)) is NOT
869 greater than MIN(StrLen(Source), Length).
870 @retval RETURN_INVALID_PARAMETER If Destination is NULL.
871 If Source is NULL.
872 If PcdMaximumAsciiStringLength is not zero,
873 and DestMax is greater than
874 PcdMaximumAsciiStringLength.
875 If DestMax is 0.
876 @retval RETURN_ACCESS_DENIED If Source and Destination overlap.
877 **/
878 RETURN_STATUS
879 EFIAPI
880 AsciiStrnCatS (
881 IN OUT CHAR8 *Destination,
882 IN UINTN DestMax,
883 IN CONST CHAR8 *Source,
884 IN UINTN Length
885 )
886 {
887 UINTN DestLen;
888 UINTN CopyLen;
889 UINTN SourceLen;
890
891 //
892 // Let CopyLen denote the value DestMax - AsciiStrnLenS(Destination, DestMax) upon entry to AsciiStrnCatS.
893 //
894 DestLen = AsciiStrnLenS (Destination, DestMax);
895 CopyLen = DestMax - DestLen;
896
897 //
898 // 1. Neither Destination nor Source shall be a null pointer.
899 //
900 SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
901 SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
902
903 //
904 // 2. Neither DestMax nor Length shall be greater than ASCII_RSIZE_MAX.
905 //
906 if (ASCII_RSIZE_MAX != 0) {
907 SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
908 SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
909 }
910
911 //
912 // 3. DestMax shall not equal zero.
913 //
914 SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
915
916 //
917 // 4. CopyLen shall not equal zero.
918 //
919 SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE);
920
921 //
922 // 5. If Length is not less than CopyLen, then CopyLen shall be greater than AsciiStrnLenS(Source, CopyLen).
923 //
924 SourceLen = AsciiStrnLenS (Source, CopyLen);
925 if (Length >= CopyLen) {
926 SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL);
927 }
928
929 //
930 // 6. Copying shall not take place between objects that overlap.
931 //
932 if (SourceLen > Length) {
933 SourceLen = Length;
934 }
935 SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
936
937 //
938 // The AsciiStrnCatS function appends not more than Length successive characters (characters
939 // that follow a null character are not copied) from the array pointed to by Source to the end of
940 // the string pointed to by Destination. The initial character from Source overwrites the null character at
941 // the end of Destination. If no null character was copied from Source, then Destination[DestMax-CopyLen+Length] is set to
942 // a null character.
943 //
944 Destination = Destination + DestLen;
945 while ((*Source != 0) && (SourceLen > 0)) {
946 *(Destination++) = *(Source++);
947 SourceLen--;
948 }
949 *Destination = 0;
950
951 return RETURN_SUCCESS;
952 }
953
954 /**
955 Convert a Null-terminated Unicode string to a Null-terminated
956 ASCII string.
957
958 This function is similar to AsciiStrCpyS.
959
960 This function converts the content of the Unicode string Source
961 to the ASCII string Destination by copying the lower 8 bits of
962 each Unicode character. The function terminates the ASCII string
963 Destination by appending a Null-terminator character at the end.
964
965 The caller is responsible to make sure Destination points to a buffer with size
966 equal or greater than ((StrLen (Source) + 1) * sizeof (CHAR8)) in bytes.
967
968 If any Unicode characters in Source contain non-zero value in
969 the upper 8 bits, then ASSERT().
970
971 If Source is not aligned on a 16-bit boundary, then ASSERT().
972 If an error would be returned, then the function will also ASSERT().
973
974 If an error is returned, then the Destination is unmodified.
975
976 @param Source The pointer to a Null-terminated Unicode string.
977 @param Destination The pointer to a Null-terminated ASCII string.
978 @param DestMax The maximum number of Destination Ascii
979 char, including terminating null char.
980
981 @retval RETURN_SUCCESS String is converted.
982 @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than StrLen(Source).
983 @retval RETURN_INVALID_PARAMETER If Destination is NULL.
984 If Source is NULL.
985 If PcdMaximumAsciiStringLength is not zero,
986 and DestMax is greater than
987 PcdMaximumAsciiStringLength.
988 If PcdMaximumUnicodeStringLength is not zero,
989 and DestMax is greater than
990 PcdMaximumUnicodeStringLength.
991 If DestMax is 0.
992 @retval RETURN_ACCESS_DENIED If Source and Destination overlap.
993
994 **/
995 RETURN_STATUS
996 EFIAPI
997 UnicodeStrToAsciiStrS (
998 IN CONST CHAR16 *Source,
999 OUT CHAR8 *Destination,
1000 IN UINTN DestMax
1001 )
1002 {
1003 UINTN SourceLen;
1004
1005 ASSERT (((UINTN) Source & BIT0) == 0);
1006
1007 //
1008 // 1. Neither Destination nor Source shall be a null pointer.
1009 //
1010 SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
1011 SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
1012
1013 //
1014 // 2. DestMax shall not be greater than ASCII_RSIZE_MAX or RSIZE_MAX.
1015 //
1016 if (ASCII_RSIZE_MAX != 0) {
1017 SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
1018 }
1019 if (RSIZE_MAX != 0) {
1020 SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
1021 }
1022
1023 //
1024 // 3. DestMax shall not equal zero.
1025 //
1026 SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
1027
1028 //
1029 // 4. DestMax shall be greater than StrnLenS (Source, DestMax).
1030 //
1031 SourceLen = StrnLenS (Source, DestMax);
1032 SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
1033
1034 //
1035 // 5. Copying shall not take place between objects that overlap.
1036 //
1037 SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)), RETURN_ACCESS_DENIED);
1038
1039 //
1040 // convert string
1041 //
1042 while (*Source != '\0') {
1043 //
1044 // If any Unicode characters in Source contain
1045 // non-zero value in the upper 8 bits, then ASSERT().
1046 //
1047 ASSERT (*Source < 0x100);
1048 *(Destination++) = (CHAR8) *(Source++);
1049 }
1050 *Destination = '\0';
1051
1052 return RETURN_SUCCESS;
1053 }
1054
1055
1056 /**
1057 Convert one Null-terminated ASCII string to a Null-terminated
1058 Unicode string.
1059
1060 This function is similar to StrCpyS.
1061
1062 This function converts the contents of the ASCII string Source to the Unicode
1063 string Destination. The function terminates the Unicode string Destination by
1064 appending a Null-terminator character at the end.
1065
1066 The caller is responsible to make sure Destination points to a buffer with size
1067 equal or greater than ((AsciiStrLen (Source) + 1) * sizeof (CHAR16)) in bytes.
1068
1069 If Destination is not aligned on a 16-bit boundary, then ASSERT().
1070 If an error would be returned, then the function will also ASSERT().
1071
1072 If an error is returned, then the Destination is unmodified.
1073
1074 @param Source The pointer to a Null-terminated ASCII string.
1075 @param Destination The pointer to a Null-terminated Unicode string.
1076 @param DestMax The maximum number of Destination Unicode
1077 char, including terminating null char.
1078
1079 @retval RETURN_SUCCESS String is converted.
1080 @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than StrLen(Source).
1081 @retval RETURN_INVALID_PARAMETER If Destination is NULL.
1082 If Source is NULL.
1083 If PcdMaximumUnicodeStringLength is not zero,
1084 and DestMax is greater than
1085 PcdMaximumUnicodeStringLength.
1086 If PcdMaximumAsciiStringLength is not zero,
1087 and DestMax is greater than
1088 PcdMaximumAsciiStringLength.
1089 If DestMax is 0.
1090 @retval RETURN_ACCESS_DENIED If Source and Destination overlap.
1091
1092 **/
1093 RETURN_STATUS
1094 EFIAPI
1095 AsciiStrToUnicodeStrS (
1096 IN CONST CHAR8 *Source,
1097 OUT CHAR16 *Destination,
1098 IN UINTN DestMax
1099 )
1100 {
1101 UINTN SourceLen;
1102
1103 ASSERT (((UINTN) Destination & BIT0) == 0);
1104
1105 //
1106 // 1. Neither Destination nor Source shall be a null pointer.
1107 //
1108 SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
1109 SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
1110
1111 //
1112 // 2. DestMax shall not be greater than RSIZE_MAX or ASCII_RSIZE_MAX.
1113 //
1114 if (RSIZE_MAX != 0) {
1115 SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
1116 }
1117 if (ASCII_RSIZE_MAX != 0) {
1118 SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
1119 }
1120
1121 //
1122 // 3. DestMax shall not equal zero.
1123 //
1124 SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
1125
1126 //
1127 // 4. DestMax shall be greater than AsciiStrnLenS(Source, DestMax).
1128 //
1129 SourceLen = AsciiStrnLenS (Source, DestMax);
1130 SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
1131
1132 //
1133 // 5. Copying shall not take place between objects that overlap.
1134 //
1135 SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax * sizeof(CHAR16), (VOID *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
1136
1137 //
1138 // Convert string
1139 //
1140 while (*Source != '\0') {
1141 *(Destination++) = (CHAR16)*(Source++);
1142 }
1143 *Destination = '\0';
1144
1145 return RETURN_SUCCESS;
1146 }