2 This library provides helper functions to prevent integer overflow during
3 type conversion, addition, subtraction, and multiplication.
5 Copyright (c) 2017, Microsoft Corporation
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are met:
10 1. Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
24 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <Library/SafeIntLib.h>
33 INT32 -> UINTN conversion
35 Converts the value specified by Operand to a value specified by Result type
36 and stores the converted value into the caller allocated output buffer
37 specified by Result. The caller must pass in a Result buffer that is at
38 least as large as the Result type.
40 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
42 If the conversion results in an overflow or an underflow condition, then
43 Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
45 @param[in] Operand Operand to be converted to new type
46 @param[out] Result Pointer to the result of conversion
48 @retval RETURN_SUCCESS Successful conversion
49 @retval RETURN_BUFFER_TOO_SMALL Overflow
50 @retval RETURN_INVALID_PARAMETER Result is NULL
59 if (sizeof (UINTN
) == sizeof (UINT32
)) {
60 return SafeInt32ToUint32 (Operand
, (UINT32
*)Result
);
62 return SafeInt32ToUint64 (Operand
, (UINT64
*) Result
);
66 UINT32 -> INTN conversion
68 Converts the value specified by Operand to a value specified by Result type
69 and stores the converted value into the caller allocated output buffer
70 specified by Result. The caller must pass in a Result buffer that is at
71 least as large as the Result type.
73 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
75 If the conversion results in an overflow or an underflow condition, then
76 Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
78 @param[in] Operand Operand to be converted to new type
79 @param[out] Result Pointer to the result of conversion
81 @retval RETURN_SUCCESS Successful conversion
82 @retval RETURN_BUFFER_TOO_SMALL Overflow
83 @retval RETURN_INVALID_PARAMETER Result is NULL
93 return RETURN_INVALID_PARAMETER
;
96 if (sizeof (UINTN
) == sizeof (UINT32
)) {
97 return SafeUint32ToInt32 (Operand
, (INT32
*)Result
);
100 return RETURN_SUCCESS
;
104 INTN -> INT32 conversion
106 Converts the value specified by Operand to a value specified by Result type
107 and stores the converted value into the caller allocated output buffer
108 specified by Result. The caller must pass in a Result buffer that is at
109 least as large as the Result type.
111 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
113 If the conversion results in an overflow or an underflow condition, then
114 Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
116 @param[in] Operand Operand to be converted to new type
117 @param[out] Result Pointer to the result of conversion
119 @retval RETURN_SUCCESS Successful conversion
120 @retval RETURN_BUFFER_TOO_SMALL Overflow
121 @retval RETURN_INVALID_PARAMETER Result is NULL
130 if (Result
== NULL
) {
131 return RETURN_INVALID_PARAMETER
;
134 if (sizeof (UINTN
) == sizeof (UINT32
)) {
135 *Result
= (INT32
)Operand
;
136 return RETURN_SUCCESS
;
138 return SafeInt64ToInt32 ((INT64
) Operand
, Result
);
142 INTN -> UINT32 conversion
144 Converts the value specified by Operand to a value specified by Result type
145 and stores the converted value into the caller allocated output buffer
146 specified by Result. The caller must pass in a Result buffer that is at
147 least as large as the Result type.
149 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
151 If the conversion results in an overflow or an underflow condition, then
152 Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
154 @param[in] Operand Operand to be converted to new type
155 @param[out] Result Pointer to the result of conversion
157 @retval RETURN_SUCCESS Successful conversion
158 @retval RETURN_BUFFER_TOO_SMALL Overflow
159 @retval RETURN_INVALID_PARAMETER Result is NULL
168 RETURN_STATUS Status
;
170 if (Result
== NULL
) {
171 return RETURN_INVALID_PARAMETER
;
174 if (sizeof (UINTN
) == sizeof (UINT32
)) {
176 *Result
= (UINT32
)Operand
;
177 Status
= RETURN_SUCCESS
;
179 *Result
= UINT32_ERROR
;
180 Status
= RETURN_BUFFER_TOO_SMALL
;
185 return SafeInt64ToUint32 ((INT64
)Operand
, Result
);
189 UINTN -> UINT32 conversion
191 Converts the value specified by Operand to a value specified by Result type
192 and stores the converted value into the caller allocated output buffer
193 specified by Result. The caller must pass in a Result buffer that is at
194 least as large as the Result type.
196 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
198 If the conversion results in an overflow or an underflow condition, then
199 Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
201 @param[in] Operand Operand to be converted to new type
202 @param[out] Result Pointer to the result of conversion
204 @retval RETURN_SUCCESS Successful conversion
205 @retval RETURN_BUFFER_TOO_SMALL Overflow
206 @retval RETURN_INVALID_PARAMETER Result is NULL
215 if (Result
== NULL
) {
216 return RETURN_INVALID_PARAMETER
;
219 if (sizeof (UINTN
) == sizeof (UINT32
)) {
220 *Result
= (UINT32
)Operand
;
221 return RETURN_SUCCESS
;
223 return SafeUint64ToUint32 ((UINT64
)Operand
, Result
);
227 UINTN -> INT64 conversion
229 Converts the value specified by Operand to a value specified by Result type
230 and stores the converted value into the caller allocated output buffer
231 specified by Result. The caller must pass in a Result buffer that is at
232 least as large as the Result type.
234 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
236 If the conversion results in an overflow or an underflow condition, then
237 Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
239 @param[in] Operand Operand to be converted to new type
240 @param[out] Result Pointer to the result of conversion
242 @retval RETURN_SUCCESS Successful conversion
243 @retval RETURN_BUFFER_TOO_SMALL Overflow
244 @retval RETURN_INVALID_PARAMETER Result is NULL
253 if (Result
== NULL
) {
254 return RETURN_INVALID_PARAMETER
;
257 if (sizeof (UINTN
) == sizeof (UINT32
)) {
258 *Result
= (INT64
)Operand
;
259 return RETURN_SUCCESS
;
261 return SafeUint64ToInt64 ((UINT64
)Operand
, Result
);
265 INT64 -> INTN conversion
267 Converts the value specified by Operand to a value specified by Result type
268 and stores the converted value into the caller allocated output buffer
269 specified by Result. The caller must pass in a Result buffer that is at
270 least as large as the Result type.
272 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
274 If the conversion results in an overflow or an underflow condition, then
275 Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
277 @param[in] Operand Operand to be converted to new type
278 @param[out] Result Pointer to the result of conversion
280 @retval RETURN_SUCCESS Successful conversion
281 @retval RETURN_BUFFER_TOO_SMALL Overflow
282 @retval RETURN_INVALID_PARAMETER Result is NULL
291 if (Result
== NULL
) {
292 return RETURN_INVALID_PARAMETER
;
295 if (sizeof (UINTN
) == sizeof (UINT32
)) {
296 return SafeInt64ToInt32 (Operand
, (INT32
*)Result
);
298 *Result
= (INTN
)Operand
;
299 return RETURN_SUCCESS
;
303 INT64 -> UINTN conversion
305 Converts the value specified by Operand to a value specified by Result type
306 and stores the converted value into the caller allocated output buffer
307 specified by Result. The caller must pass in a Result buffer that is at
308 least as large as the Result type.
310 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
312 If the conversion results in an overflow or an underflow condition, then
313 Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
315 @param[in] Operand Operand to be converted to new type
316 @param[out] Result Pointer to the result of conversion
318 @retval RETURN_SUCCESS Successful conversion
319 @retval RETURN_BUFFER_TOO_SMALL Overflow
320 @retval RETURN_INVALID_PARAMETER Result is NULL
329 if (sizeof (UINTN
) == sizeof (UINT32
)) {
330 return SafeInt64ToUint32 (Operand
, (UINT32
*)Result
);
332 return SafeInt64ToUint64 (Operand
, (UINT64
*)Result
);
336 UINT64 -> UINTN conversion
338 Converts the value specified by Operand to a value specified by Result type
339 and stores the converted value into the caller allocated output buffer
340 specified by Result. The caller must pass in a Result buffer that is at
341 least as large as the Result type.
343 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
345 If the conversion results in an overflow or an underflow condition, then
346 Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
348 @param[in] Operand Operand to be converted to new type
349 @param[out] Result Pointer to the result of conversion
351 @retval RETURN_SUCCESS Successful conversion
352 @retval RETURN_BUFFER_TOO_SMALL Overflow
353 @retval RETURN_INVALID_PARAMETER Result is NULL
362 if (Result
== NULL
) {
363 return RETURN_INVALID_PARAMETER
;
366 if (sizeof (UINTN
) == sizeof (UINT32
)) {
367 return SafeUint64ToUint32 ((UINT64
) Operand
, (UINT32
*)Result
);
370 return RETURN_SUCCESS
;
376 Performs the requested operation using the input parameters into a value
377 specified by Result type and stores the converted value into the caller
378 allocated output buffer specified by Result. The caller must pass in a
379 Result buffer that is at least as large as the Result type.
381 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
383 If the requested operation results in an overflow or an underflow condition,
384 then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
386 @param[in] Augend A number to which addend will be added
387 @param[in] Addend A number to be added to another
388 @param[out] Result Pointer to the result of addition
390 @retval RETURN_SUCCESS Successful addition
391 @retval RETURN_BUFFER_TOO_SMALL Overflow
392 @retval RETURN_INVALID_PARAMETER Result is NULL
402 RETURN_STATUS Status
;
404 if (Result
== NULL
) {
405 return RETURN_INVALID_PARAMETER
;
408 if (sizeof (UINTN
) == sizeof (UINT32
)) {
409 if ((UINT32
)(Augend
+ Addend
) >= Augend
) {
410 *Result
= (Augend
+ Addend
);
411 Status
= RETURN_SUCCESS
;
413 *Result
= UINTN_ERROR
;
414 Status
= RETURN_BUFFER_TOO_SMALL
;
419 return SafeUint64Add ((UINT64
)Augend
, (UINT64
)Addend
, (UINT64
*)Result
);
425 Performs the requested operation using the input parameters into a value
426 specified by Result type and stores the converted value into the caller
427 allocated output buffer specified by Result. The caller must pass in a
428 Result buffer that is at least as large as the Result type.
430 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
432 If the requested operation results in an overflow or an underflow condition,
433 then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
435 @param[in] Minuend A number from which another is to be subtracted.
436 @param[in] Subtrahend A number to be subtracted from another
437 @param[out] Result Pointer to the result of subtraction
439 @retval RETURN_SUCCESS Successful subtraction
440 @retval RETURN_BUFFER_TOO_SMALL Underflow
441 @retval RETURN_INVALID_PARAMETER Result is NULL
451 RETURN_STATUS Status
;
453 if (Result
== NULL
) {
454 return RETURN_INVALID_PARAMETER
;
457 if (sizeof (UINTN
) == sizeof (UINT32
)) {
458 if (Minuend
>= Subtrahend
) {
459 *Result
= (Minuend
- Subtrahend
);
460 Status
= RETURN_SUCCESS
;
462 *Result
= UINTN_ERROR
;
463 Status
= RETURN_BUFFER_TOO_SMALL
;
468 return SafeUint64Sub ((UINT64
)Minuend
, (UINT64
)Subtrahend
, (UINT64
*)Result
);
474 Performs the requested operation using the input parameters into a value
475 specified by Result type and stores the converted value into the caller
476 allocated output buffer specified by Result. The caller must pass in a
477 Result buffer that is at least as large as the Result type.
479 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
481 If the requested operation results in an overflow or an underflow condition,
482 then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
484 @param[in] Multiplicand A number that is to be multiplied by another
485 @param[in] Multiplier A number by which the multiplicand is to be multiplied
486 @param[out] Result Pointer to the result of multiplication
488 @retval RETURN_SUCCESS Successful multiplication
489 @retval RETURN_BUFFER_TOO_SMALL Overflow
490 @retval RETURN_INVALID_PARAMETER Result is NULL
495 IN UINTN Multiplicand
,
500 UINT64 IntermediateResult
;
502 if (sizeof (UINTN
) == sizeof (UINT32
)) {
503 IntermediateResult
= ((UINT64
) Multiplicand
) *((UINT64
) Multiplier
);
505 return SafeUint64ToUintn (IntermediateResult
, Result
);
507 return SafeUint64Mult ((UINT64
)Multiplicand
, (UINT64
)Multiplier
, (UINT64
*)Result
);
513 Performs the requested operation using the input parameters into a value
514 specified by Result type and stores the converted value into the caller
515 allocated output buffer specified by Result. The caller must pass in a
516 Result buffer that is at least as large as the Result type.
518 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
520 If the requested operation results in an overflow or an underflow condition,
521 then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
523 @param[in] Augend A number to which addend will be added
524 @param[in] Addend A number to be added to another
525 @param[out] Result Pointer to the result of addition
527 @retval RETURN_SUCCESS Successful addition
528 @retval RETURN_BUFFER_TOO_SMALL Overflow
529 @retval RETURN_INVALID_PARAMETER Result is NULL
539 if (sizeof (UINTN
) == sizeof (UINT32
)) {
540 return SafeInt64ToIntn (((INT64
)Augend
) + ((INT64
)Addend
), Result
);
542 return SafeInt64Add ((INT64
)Augend
, (INT64
)Addend
, (INT64
*)Result
);
548 Performs the requested operation using the input parameters into a value
549 specified by Result type and stores the converted value into the caller
550 allocated output buffer specified by Result. The caller must pass in a
551 Result buffer that is at least as large as the Result type.
553 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
555 If the requested operation results in an overflow or an underflow condition,
556 then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
558 @param[in] Minuend A number from which another is to be subtracted.
559 @param[in] Subtrahend A number to be subtracted from another
560 @param[out] Result Pointer to the result of subtraction
562 @retval RETURN_SUCCESS Successful subtraction
563 @retval RETURN_BUFFER_TOO_SMALL Underflow
564 @retval RETURN_INVALID_PARAMETER Result is NULL
574 if (sizeof (UINTN
) == sizeof (UINT32
)) {
575 return SafeInt64ToIntn (((INT64
)Minuend
) - ((INT64
)Subtrahend
), Result
);
577 return SafeInt64Sub ((INT64
)Minuend
, (INT64
)Subtrahend
, (INT64
*)Result
);
583 Performs the requested operation using the input parameters into a value
584 specified by Result type and stores the converted value into the caller
585 allocated output buffer specified by Result. The caller must pass in a
586 Result buffer that is at least as large as the Result type.
588 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
590 If the requested operation results in an overflow or an underflow condition,
591 then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
593 @param[in] Multiplicand A number that is to be multiplied by another
594 @param[in] Multiplier A number by which the multiplicand is to be multiplied
595 @param[out] Result Pointer to the result of multiplication
597 @retval RETURN_SUCCESS Successful multiplication
598 @retval RETURN_BUFFER_TOO_SMALL Overflow
599 @retval RETURN_INVALID_PARAMETER Result is NULL
604 IN INTN Multiplicand
,
609 if (sizeof (UINTN
) == sizeof (UINT32
)) {
610 return SafeInt64ToIntn (((INT64
)Multiplicand
) *((INT64
)Multiplier
), Result
);
612 return SafeInt64Mult ((INT64
)Multiplicand
, (INT64
)Multiplier
, (INT64
*)Result
);