]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/BaseSafeIntLib/SafeIntLibEbc.c
93071cd9465d4b7162da2c98f4e80fa02e9619a1
[mirror_edk2.git] / MdePkg / Library / BaseSafeIntLib / SafeIntLibEbc.c
1 /** @file
2 This library provides helper functions to prevent integer overflow during
3 type conversion, addition, subtraction, and multiplication.
4
5 Copyright (c) 2017, Microsoft Corporation
6
7 All rights reserved.
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10 **/
11
12 #include <Base.h>
13 #include <Library/SafeIntLib.h>
14
15 /**
16 INT32 -> UINTN conversion
17
18 Converts the value specified by Operand to a value specified by Result type
19 and stores the converted value into the caller allocated output buffer
20 specified by Result. The caller must pass in a Result buffer that is at
21 least as large as the Result type.
22
23 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
24
25 If the conversion results in an overflow or an underflow condition, then
26 Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
27
28 @param[in] Operand Operand to be converted to new type
29 @param[out] Result Pointer to the result of conversion
30
31 @retval RETURN_SUCCESS Successful conversion
32 @retval RETURN_BUFFER_TOO_SMALL Overflow
33 @retval RETURN_INVALID_PARAMETER Result is NULL
34 **/
35 RETURN_STATUS
36 EFIAPI
37 SafeInt32ToUintn (
38 IN INT32 Operand,
39 OUT UINTN *Result
40 )
41 {
42 if (sizeof (UINTN) == sizeof (UINT32)) {
43 return SafeInt32ToUint32 (Operand, (UINT32 *)Result);
44 }
45
46 return SafeInt32ToUint64 (Operand, (UINT64 *)Result);
47 }
48
49 /**
50 UINT32 -> INTN conversion
51
52 Converts the value specified by Operand to a value specified by Result type
53 and stores the converted value into the caller allocated output buffer
54 specified by Result. The caller must pass in a Result buffer that is at
55 least as large as the Result type.
56
57 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
58
59 If the conversion results in an overflow or an underflow condition, then
60 Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
61
62 @param[in] Operand Operand to be converted to new type
63 @param[out] Result Pointer to the result of conversion
64
65 @retval RETURN_SUCCESS Successful conversion
66 @retval RETURN_BUFFER_TOO_SMALL Overflow
67 @retval RETURN_INVALID_PARAMETER Result is NULL
68 **/
69 RETURN_STATUS
70 EFIAPI
71 SafeUint32ToIntn (
72 IN UINT32 Operand,
73 OUT INTN *Result
74 )
75 {
76 if (Result == NULL) {
77 return RETURN_INVALID_PARAMETER;
78 }
79
80 if (sizeof (UINTN) == sizeof (UINT32)) {
81 return SafeUint32ToInt32 (Operand, (INT32 *)Result);
82 }
83
84 *Result = Operand;
85 return RETURN_SUCCESS;
86 }
87
88 /**
89 INTN -> INT32 conversion
90
91 Converts the value specified by Operand to a value specified by Result type
92 and stores the converted value into the caller allocated output buffer
93 specified by Result. The caller must pass in a Result buffer that is at
94 least as large as the Result type.
95
96 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
97
98 If the conversion results in an overflow or an underflow condition, then
99 Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
100
101 @param[in] Operand Operand to be converted to new type
102 @param[out] Result Pointer to the result of conversion
103
104 @retval RETURN_SUCCESS Successful conversion
105 @retval RETURN_BUFFER_TOO_SMALL Overflow
106 @retval RETURN_INVALID_PARAMETER Result is NULL
107 **/
108 RETURN_STATUS
109 EFIAPI
110 SafeIntnToInt32 (
111 IN INTN Operand,
112 OUT INT32 *Result
113 )
114 {
115 if (Result == NULL) {
116 return RETURN_INVALID_PARAMETER;
117 }
118
119 if (sizeof (UINTN) == sizeof (UINT32)) {
120 *Result = (INT32)Operand;
121 return RETURN_SUCCESS;
122 }
123
124 return SafeInt64ToInt32 ((INT64)Operand, Result);
125 }
126
127 /**
128 INTN -> UINT32 conversion
129
130 Converts the value specified by Operand to a value specified by Result type
131 and stores the converted value into the caller allocated output buffer
132 specified by Result. The caller must pass in a Result buffer that is at
133 least as large as the Result type.
134
135 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
136
137 If the conversion results in an overflow or an underflow condition, then
138 Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
139
140 @param[in] Operand Operand to be converted to new type
141 @param[out] Result Pointer to the result of conversion
142
143 @retval RETURN_SUCCESS Successful conversion
144 @retval RETURN_BUFFER_TOO_SMALL Overflow
145 @retval RETURN_INVALID_PARAMETER Result is NULL
146 **/
147 RETURN_STATUS
148 EFIAPI
149 SafeIntnToUint32 (
150 IN INTN Operand,
151 OUT UINT32 *Result
152 )
153 {
154 RETURN_STATUS Status;
155
156 if (Result == NULL) {
157 return RETURN_INVALID_PARAMETER;
158 }
159
160 if (sizeof (UINTN) == sizeof (UINT32)) {
161 if (Operand >= 0) {
162 *Result = (UINT32)Operand;
163 Status = RETURN_SUCCESS;
164 } else {
165 *Result = UINT32_ERROR;
166 Status = RETURN_BUFFER_TOO_SMALL;
167 }
168
169 return Status;
170 }
171
172 return SafeInt64ToUint32 ((INT64)Operand, Result);
173 }
174
175 /**
176 UINTN -> UINT32 conversion
177
178 Converts the value specified by Operand to a value specified by Result type
179 and stores the converted value into the caller allocated output buffer
180 specified by Result. The caller must pass in a Result buffer that is at
181 least as large as the Result type.
182
183 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
184
185 If the conversion results in an overflow or an underflow condition, then
186 Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
187
188 @param[in] Operand Operand to be converted to new type
189 @param[out] Result Pointer to the result of conversion
190
191 @retval RETURN_SUCCESS Successful conversion
192 @retval RETURN_BUFFER_TOO_SMALL Overflow
193 @retval RETURN_INVALID_PARAMETER Result is NULL
194 **/
195 RETURN_STATUS
196 EFIAPI
197 SafeUintnToUint32 (
198 IN UINTN Operand,
199 OUT UINT32 *Result
200 )
201 {
202 if (Result == NULL) {
203 return RETURN_INVALID_PARAMETER;
204 }
205
206 if (sizeof (UINTN) == sizeof (UINT32)) {
207 *Result = (UINT32)Operand;
208 return RETURN_SUCCESS;
209 }
210
211 return SafeUint64ToUint32 ((UINT64)Operand, Result);
212 }
213
214 /**
215 UINTN -> INT64 conversion
216
217 Converts the value specified by Operand to a value specified by Result type
218 and stores the converted value into the caller allocated output buffer
219 specified by Result. The caller must pass in a Result buffer that is at
220 least as large as the Result type.
221
222 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
223
224 If the conversion results in an overflow or an underflow condition, then
225 Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
226
227 @param[in] Operand Operand to be converted to new type
228 @param[out] Result Pointer to the result of conversion
229
230 @retval RETURN_SUCCESS Successful conversion
231 @retval RETURN_BUFFER_TOO_SMALL Overflow
232 @retval RETURN_INVALID_PARAMETER Result is NULL
233 **/
234 RETURN_STATUS
235 EFIAPI
236 SafeUintnToInt64 (
237 IN UINTN Operand,
238 OUT INT64 *Result
239 )
240 {
241 if (Result == NULL) {
242 return RETURN_INVALID_PARAMETER;
243 }
244
245 if (sizeof (UINTN) == sizeof (UINT32)) {
246 *Result = (INT64)Operand;
247 return RETURN_SUCCESS;
248 }
249
250 return SafeUint64ToInt64 ((UINT64)Operand, Result);
251 }
252
253 /**
254 INT64 -> INTN conversion
255
256 Converts the value specified by Operand to a value specified by Result type
257 and stores the converted value into the caller allocated output buffer
258 specified by Result. The caller must pass in a Result buffer that is at
259 least as large as the Result type.
260
261 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
262
263 If the conversion results in an overflow or an underflow condition, then
264 Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
265
266 @param[in] Operand Operand to be converted to new type
267 @param[out] Result Pointer to the result of conversion
268
269 @retval RETURN_SUCCESS Successful conversion
270 @retval RETURN_BUFFER_TOO_SMALL Overflow
271 @retval RETURN_INVALID_PARAMETER Result is NULL
272 **/
273 RETURN_STATUS
274 EFIAPI
275 SafeInt64ToIntn (
276 IN INT64 Operand,
277 OUT INTN *Result
278 )
279 {
280 if (Result == NULL) {
281 return RETURN_INVALID_PARAMETER;
282 }
283
284 if (sizeof (UINTN) == sizeof (UINT32)) {
285 return SafeInt64ToInt32 (Operand, (INT32 *)Result);
286 }
287
288 *Result = (INTN)Operand;
289 return RETURN_SUCCESS;
290 }
291
292 /**
293 INT64 -> UINTN conversion
294
295 Converts the value specified by Operand to a value specified by Result type
296 and stores the converted value into the caller allocated output buffer
297 specified by Result. The caller must pass in a Result buffer that is at
298 least as large as the Result type.
299
300 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
301
302 If the conversion results in an overflow or an underflow condition, then
303 Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
304
305 @param[in] Operand Operand to be converted to new type
306 @param[out] Result Pointer to the result of conversion
307
308 @retval RETURN_SUCCESS Successful conversion
309 @retval RETURN_BUFFER_TOO_SMALL Overflow
310 @retval RETURN_INVALID_PARAMETER Result is NULL
311 **/
312 RETURN_STATUS
313 EFIAPI
314 SafeInt64ToUintn (
315 IN INT64 Operand,
316 OUT UINTN *Result
317 )
318 {
319 if (sizeof (UINTN) == sizeof (UINT32)) {
320 return SafeInt64ToUint32 (Operand, (UINT32 *)Result);
321 }
322
323 return SafeInt64ToUint64 (Operand, (UINT64 *)Result);
324 }
325
326 /**
327 UINT64 -> UINTN conversion
328
329 Converts the value specified by Operand to a value specified by Result type
330 and stores the converted value into the caller allocated output buffer
331 specified by Result. The caller must pass in a Result buffer that is at
332 least as large as the Result type.
333
334 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
335
336 If the conversion results in an overflow or an underflow condition, then
337 Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
338
339 @param[in] Operand Operand to be converted to new type
340 @param[out] Result Pointer to the result of conversion
341
342 @retval RETURN_SUCCESS Successful conversion
343 @retval RETURN_BUFFER_TOO_SMALL Overflow
344 @retval RETURN_INVALID_PARAMETER Result is NULL
345 **/
346 RETURN_STATUS
347 EFIAPI
348 SafeUint64ToUintn (
349 IN UINT64 Operand,
350 OUT UINTN *Result
351 )
352 {
353 if (Result == NULL) {
354 return RETURN_INVALID_PARAMETER;
355 }
356
357 if (sizeof (UINTN) == sizeof (UINT32)) {
358 return SafeUint64ToUint32 ((UINT64)Operand, (UINT32 *)Result);
359 }
360
361 *Result = Operand;
362 return RETURN_SUCCESS;
363 }
364
365 /**
366 UINTN addition
367
368 Performs the requested operation using the input parameters into a value
369 specified by Result type and stores the converted value into the caller
370 allocated output buffer specified by Result. The caller must pass in a
371 Result buffer that is at least as large as the Result type.
372
373 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
374
375 If the requested operation results in an overflow or an underflow condition,
376 then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
377
378 @param[in] Augend A number to which addend will be added
379 @param[in] Addend A number to be added to another
380 @param[out] Result Pointer to the result of addition
381
382 @retval RETURN_SUCCESS Successful addition
383 @retval RETURN_BUFFER_TOO_SMALL Overflow
384 @retval RETURN_INVALID_PARAMETER Result is NULL
385 **/
386 RETURN_STATUS
387 EFIAPI
388 SafeUintnAdd (
389 IN UINTN Augend,
390 IN UINTN Addend,
391 OUT UINTN *Result
392 )
393 {
394 RETURN_STATUS Status;
395
396 if (Result == NULL) {
397 return RETURN_INVALID_PARAMETER;
398 }
399
400 if (sizeof (UINTN) == sizeof (UINT32)) {
401 if ((UINT32)(Augend + Addend) >= Augend) {
402 *Result = (Augend + Addend);
403 Status = RETURN_SUCCESS;
404 } else {
405 *Result = UINTN_ERROR;
406 Status = RETURN_BUFFER_TOO_SMALL;
407 }
408
409 return Status;
410 }
411
412 return SafeUint64Add ((UINT64)Augend, (UINT64)Addend, (UINT64 *)Result);
413 }
414
415 /**
416 UINTN subtraction
417
418 Performs the requested operation using the input parameters into a value
419 specified by Result type and stores the converted value into the caller
420 allocated output buffer specified by Result. The caller must pass in a
421 Result buffer that is at least as large as the Result type.
422
423 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
424
425 If the requested operation results in an overflow or an underflow condition,
426 then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
427
428 @param[in] Minuend A number from which another is to be subtracted.
429 @param[in] Subtrahend A number to be subtracted from another
430 @param[out] Result Pointer to the result of subtraction
431
432 @retval RETURN_SUCCESS Successful subtraction
433 @retval RETURN_BUFFER_TOO_SMALL Underflow
434 @retval RETURN_INVALID_PARAMETER Result is NULL
435 **/
436 RETURN_STATUS
437 EFIAPI
438 SafeUintnSub (
439 IN UINTN Minuend,
440 IN UINTN Subtrahend,
441 OUT UINTN *Result
442 )
443 {
444 RETURN_STATUS Status;
445
446 if (Result == NULL) {
447 return RETURN_INVALID_PARAMETER;
448 }
449
450 if (sizeof (UINTN) == sizeof (UINT32)) {
451 if (Minuend >= Subtrahend) {
452 *Result = (Minuend - Subtrahend);
453 Status = RETURN_SUCCESS;
454 } else {
455 *Result = UINTN_ERROR;
456 Status = RETURN_BUFFER_TOO_SMALL;
457 }
458
459 return Status;
460 }
461
462 return SafeUint64Sub ((UINT64)Minuend, (UINT64)Subtrahend, (UINT64 *)Result);
463 }
464
465 /**
466 UINTN multiplication
467
468 Performs the requested operation using the input parameters into a value
469 specified by Result type and stores the converted value into the caller
470 allocated output buffer specified by Result. The caller must pass in a
471 Result buffer that is at least as large as the Result type.
472
473 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
474
475 If the requested operation results in an overflow or an underflow condition,
476 then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
477
478 @param[in] Multiplicand A number that is to be multiplied by another
479 @param[in] Multiplier A number by which the multiplicand is to be multiplied
480 @param[out] Result Pointer to the result of multiplication
481
482 @retval RETURN_SUCCESS Successful multiplication
483 @retval RETURN_BUFFER_TOO_SMALL Overflow
484 @retval RETURN_INVALID_PARAMETER Result is NULL
485 **/
486 RETURN_STATUS
487 EFIAPI
488 SafeUintnMult (
489 IN UINTN Multiplicand,
490 IN UINTN Multiplier,
491 OUT UINTN *Result
492 )
493 {
494 UINT64 IntermediateResult;
495
496 if (sizeof (UINTN) == sizeof (UINT32)) {
497 IntermediateResult = ((UINT64)Multiplicand) *((UINT64)Multiplier);
498
499 return SafeUint64ToUintn (IntermediateResult, Result);
500 }
501
502 return SafeUint64Mult ((UINT64)Multiplicand, (UINT64)Multiplier, (UINT64 *)Result);
503 }
504
505 /**
506 INTN Addition
507
508 Performs the requested operation using the input parameters into a value
509 specified by Result type and stores the converted value into the caller
510 allocated output buffer specified by Result. The caller must pass in a
511 Result buffer that is at least as large as the Result type.
512
513 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
514
515 If the requested operation results in an overflow or an underflow condition,
516 then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
517
518 @param[in] Augend A number to which addend will be added
519 @param[in] Addend A number to be added to another
520 @param[out] Result Pointer to the result of addition
521
522 @retval RETURN_SUCCESS Successful addition
523 @retval RETURN_BUFFER_TOO_SMALL Overflow
524 @retval RETURN_INVALID_PARAMETER Result is NULL
525 **/
526 RETURN_STATUS
527 EFIAPI
528 SafeIntnAdd (
529 IN INTN Augend,
530 IN INTN Addend,
531 OUT INTN *Result
532 )
533 {
534 if (sizeof (UINTN) == sizeof (UINT32)) {
535 return SafeInt64ToIntn (((INT64)Augend) + ((INT64)Addend), Result);
536 }
537
538 return SafeInt64Add ((INT64)Augend, (INT64)Addend, (INT64 *)Result);
539 }
540
541 /**
542 INTN Subtraction
543
544 Performs the requested operation using the input parameters into a value
545 specified by Result type and stores the converted value into the caller
546 allocated output buffer specified by Result. The caller must pass in a
547 Result buffer that is at least as large as the Result type.
548
549 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
550
551 If the requested operation results in an overflow or an underflow condition,
552 then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
553
554 @param[in] Minuend A number from which another is to be subtracted.
555 @param[in] Subtrahend A number to be subtracted from another
556 @param[out] Result Pointer to the result of subtraction
557
558 @retval RETURN_SUCCESS Successful subtraction
559 @retval RETURN_BUFFER_TOO_SMALL Underflow
560 @retval RETURN_INVALID_PARAMETER Result is NULL
561 **/
562 RETURN_STATUS
563 EFIAPI
564 SafeIntnSub (
565 IN INTN Minuend,
566 IN INTN Subtrahend,
567 OUT INTN *Result
568 )
569 {
570 if (sizeof (UINTN) == sizeof (UINT32)) {
571 return SafeInt64ToIntn (((INT64)Minuend) - ((INT64)Subtrahend), Result);
572 }
573
574 return SafeInt64Sub ((INT64)Minuend, (INT64)Subtrahend, (INT64 *)Result);
575 }
576
577 /**
578 INTN multiplication
579
580 Performs the requested operation using the input parameters into a value
581 specified by Result type and stores the converted value into the caller
582 allocated output buffer specified by Result. The caller must pass in a
583 Result buffer that is at least as large as the Result type.
584
585 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
586
587 If the requested operation results in an overflow or an underflow condition,
588 then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
589
590 @param[in] Multiplicand A number that is to be multiplied by another
591 @param[in] Multiplier A number by which the multiplicand is to be multiplied
592 @param[out] Result Pointer to the result of multiplication
593
594 @retval RETURN_SUCCESS Successful multiplication
595 @retval RETURN_BUFFER_TOO_SMALL Overflow
596 @retval RETURN_INVALID_PARAMETER Result is NULL
597 **/
598 RETURN_STATUS
599 EFIAPI
600 SafeIntnMult (
601 IN INTN Multiplicand,
602 IN INTN Multiplier,
603 OUT INTN *Result
604 )
605 {
606 if (sizeof (UINTN) == sizeof (UINT32)) {
607 return SafeInt64ToIntn (((INT64)Multiplicand) *((INT64)Multiplier), Result);
608 }
609
610 return SafeInt64Mult ((INT64)Multiplicand, (INT64)Multiplier, (INT64 *)Result);
611 }