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