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