]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/BaseSafeIntLib/SafeIntLibEbc.c
MdePkg/BaseLib: Add bit field population calculating methods
[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 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.
15
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.
26
27 **/
28
29 #include <Base.h>
30 #include <Library/SafeIntLib.h>
31
32 /**
33 INT32 -> UINTN conversion
34
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.
39
40 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
41
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.
44
45 @param[in] Operand Operand to be converted to new type
46 @param[out] Result Pointer to the result of conversion
47
48 @retval RETURN_SUCCESS Successful conversion
49 @retval RETURN_BUFFER_TOO_SMALL Overflow
50 @retval RETURN_INVALID_PARAMETER Result is NULL
51 **/
52 RETURN_STATUS
53 EFIAPI
54 SafeInt32ToUintn (
55 IN INT32 Operand,
56 OUT UINTN *Result
57 )
58 {
59 if (sizeof (UINTN) == sizeof (UINT32)) {
60 return SafeInt32ToUint32 (Operand, (UINT32 *)Result);
61 }
62 return SafeInt32ToUint64 (Operand, (UINT64 *) Result);
63 }
64
65 /**
66 UINT32 -> INTN conversion
67
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.
72
73 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
74
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.
77
78 @param[in] Operand Operand to be converted to new type
79 @param[out] Result Pointer to the result of conversion
80
81 @retval RETURN_SUCCESS Successful conversion
82 @retval RETURN_BUFFER_TOO_SMALL Overflow
83 @retval RETURN_INVALID_PARAMETER Result is NULL
84 **/
85 RETURN_STATUS
86 EFIAPI
87 SafeUint32ToIntn (
88 IN UINT32 Operand,
89 OUT INTN *Result
90 )
91 {
92 if (Result == NULL) {
93 return RETURN_INVALID_PARAMETER;
94 }
95
96 if (sizeof (UINTN) == sizeof (UINT32)) {
97 return SafeUint32ToInt32 (Operand, (INT32 *)Result);
98 }
99 *Result = Operand;
100 return RETURN_SUCCESS;
101 }
102
103 /**
104 INTN -> INT32 conversion
105
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.
110
111 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
112
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.
115
116 @param[in] Operand Operand to be converted to new type
117 @param[out] Result Pointer to the result of conversion
118
119 @retval RETURN_SUCCESS Successful conversion
120 @retval RETURN_BUFFER_TOO_SMALL Overflow
121 @retval RETURN_INVALID_PARAMETER Result is NULL
122 **/
123 RETURN_STATUS
124 EFIAPI
125 SafeIntnToInt32 (
126 IN INTN Operand,
127 OUT INT32 *Result
128 )
129 {
130 if (Result == NULL) {
131 return RETURN_INVALID_PARAMETER;
132 }
133
134 if (sizeof (UINTN) == sizeof (UINT32)) {
135 *Result = (INT32)Operand;
136 return RETURN_SUCCESS;
137 }
138 return SafeInt64ToInt32 ((INT64) Operand, Result);
139 }
140
141 /**
142 INTN -> UINT32 conversion
143
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.
148
149 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
150
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.
153
154 @param[in] Operand Operand to be converted to new type
155 @param[out] Result Pointer to the result of conversion
156
157 @retval RETURN_SUCCESS Successful conversion
158 @retval RETURN_BUFFER_TOO_SMALL Overflow
159 @retval RETURN_INVALID_PARAMETER Result is NULL
160 **/
161 RETURN_STATUS
162 EFIAPI
163 SafeIntnToUint32 (
164 IN INTN Operand,
165 OUT UINT32 *Result
166 )
167 {
168 RETURN_STATUS Status;
169
170 if (Result == NULL) {
171 return RETURN_INVALID_PARAMETER;
172 }
173
174 if (sizeof (UINTN) == sizeof (UINT32)) {
175 if (Operand >= 0) {
176 *Result = (UINT32)Operand;
177 Status = RETURN_SUCCESS;
178 } else {
179 *Result = UINT32_ERROR;
180 Status = RETURN_BUFFER_TOO_SMALL;
181 }
182
183 return Status;
184 }
185 return SafeInt64ToUint32 ((INT64)Operand, Result);
186 }
187
188 /**
189 UINTN -> UINT32 conversion
190
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.
195
196 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
197
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.
200
201 @param[in] Operand Operand to be converted to new type
202 @param[out] Result Pointer to the result of conversion
203
204 @retval RETURN_SUCCESS Successful conversion
205 @retval RETURN_BUFFER_TOO_SMALL Overflow
206 @retval RETURN_INVALID_PARAMETER Result is NULL
207 **/
208 RETURN_STATUS
209 EFIAPI
210 SafeUintnToUint32 (
211 IN UINTN Operand,
212 OUT UINT32 *Result
213 )
214 {
215 if (Result == NULL) {
216 return RETURN_INVALID_PARAMETER;
217 }
218
219 if (sizeof (UINTN) == sizeof (UINT32)) {
220 *Result = (UINT32)Operand;
221 return RETURN_SUCCESS;
222 }
223 return SafeUint64ToUint32 ((UINT64)Operand, Result);
224 }
225
226 /**
227 UINTN -> INT64 conversion
228
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.
233
234 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
235
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.
238
239 @param[in] Operand Operand to be converted to new type
240 @param[out] Result Pointer to the result of conversion
241
242 @retval RETURN_SUCCESS Successful conversion
243 @retval RETURN_BUFFER_TOO_SMALL Overflow
244 @retval RETURN_INVALID_PARAMETER Result is NULL
245 **/
246 RETURN_STATUS
247 EFIAPI
248 SafeUintnToInt64 (
249 IN UINTN Operand,
250 OUT INT64 *Result
251 )
252 {
253 if (Result == NULL) {
254 return RETURN_INVALID_PARAMETER;
255 }
256
257 if (sizeof (UINTN) == sizeof (UINT32)) {
258 *Result = (INT64)Operand;
259 return RETURN_SUCCESS;
260 }
261 return SafeUint64ToInt64 ((UINT64)Operand, Result);
262 }
263
264 /**
265 INT64 -> INTN conversion
266
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.
271
272 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
273
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.
276
277 @param[in] Operand Operand to be converted to new type
278 @param[out] Result Pointer to the result of conversion
279
280 @retval RETURN_SUCCESS Successful conversion
281 @retval RETURN_BUFFER_TOO_SMALL Overflow
282 @retval RETURN_INVALID_PARAMETER Result is NULL
283 **/
284 RETURN_STATUS
285 EFIAPI
286 SafeInt64ToIntn (
287 IN INT64 Operand,
288 OUT INTN *Result
289 )
290 {
291 if (Result == NULL) {
292 return RETURN_INVALID_PARAMETER;
293 }
294
295 if (sizeof (UINTN) == sizeof (UINT32)) {
296 return SafeInt64ToInt32 (Operand, (INT32 *)Result);
297 }
298 *Result = (INTN)Operand;
299 return RETURN_SUCCESS;
300 }
301
302 /**
303 INT64 -> UINTN conversion
304
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.
309
310 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
311
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.
314
315 @param[in] Operand Operand to be converted to new type
316 @param[out] Result Pointer to the result of conversion
317
318 @retval RETURN_SUCCESS Successful conversion
319 @retval RETURN_BUFFER_TOO_SMALL Overflow
320 @retval RETURN_INVALID_PARAMETER Result is NULL
321 **/
322 RETURN_STATUS
323 EFIAPI
324 SafeInt64ToUintn (
325 IN INT64 Operand,
326 OUT UINTN *Result
327 )
328 {
329 if (sizeof (UINTN) == sizeof (UINT32)) {
330 return SafeInt64ToUint32 (Operand, (UINT32 *)Result);
331 }
332 return SafeInt64ToUint64 (Operand, (UINT64 *)Result);
333 }
334
335 /**
336 UINT64 -> UINTN conversion
337
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.
342
343 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
344
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.
347
348 @param[in] Operand Operand to be converted to new type
349 @param[out] Result Pointer to the result of conversion
350
351 @retval RETURN_SUCCESS Successful conversion
352 @retval RETURN_BUFFER_TOO_SMALL Overflow
353 @retval RETURN_INVALID_PARAMETER Result is NULL
354 **/
355 RETURN_STATUS
356 EFIAPI
357 SafeUint64ToUintn (
358 IN UINT64 Operand,
359 OUT UINTN *Result
360 )
361 {
362 if (Result == NULL) {
363 return RETURN_INVALID_PARAMETER;
364 }
365
366 if (sizeof (UINTN) == sizeof (UINT32)) {
367 return SafeUint64ToUint32 ((UINT64) Operand, (UINT32 *)Result);
368 }
369 *Result = Operand;
370 return RETURN_SUCCESS;
371 }
372
373 /**
374 UINTN addition
375
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.
380
381 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
382
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.
385
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
389
390 @retval RETURN_SUCCESS Successful addition
391 @retval RETURN_BUFFER_TOO_SMALL Overflow
392 @retval RETURN_INVALID_PARAMETER Result is NULL
393 **/
394 RETURN_STATUS
395 EFIAPI
396 SafeUintnAdd (
397 IN UINTN Augend,
398 IN UINTN Addend,
399 OUT UINTN *Result
400 )
401 {
402 RETURN_STATUS Status;
403
404 if (Result == NULL) {
405 return RETURN_INVALID_PARAMETER;
406 }
407
408 if (sizeof (UINTN) == sizeof (UINT32)) {
409 if ((UINT32)(Augend + Addend) >= Augend) {
410 *Result = (Augend + Addend);
411 Status = RETURN_SUCCESS;
412 } else {
413 *Result = UINTN_ERROR;
414 Status = RETURN_BUFFER_TOO_SMALL;
415 }
416
417 return Status;
418 }
419 return SafeUint64Add ((UINT64)Augend, (UINT64)Addend, (UINT64 *)Result);
420 }
421
422 /**
423 UINTN subtraction
424
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.
429
430 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
431
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.
434
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
438
439 @retval RETURN_SUCCESS Successful subtraction
440 @retval RETURN_BUFFER_TOO_SMALL Underflow
441 @retval RETURN_INVALID_PARAMETER Result is NULL
442 **/
443 RETURN_STATUS
444 EFIAPI
445 SafeUintnSub (
446 IN UINTN Minuend,
447 IN UINTN Subtrahend,
448 OUT UINTN *Result
449 )
450 {
451 RETURN_STATUS Status;
452
453 if (Result == NULL) {
454 return RETURN_INVALID_PARAMETER;
455 }
456
457 if (sizeof (UINTN) == sizeof (UINT32)) {
458 if (Minuend >= Subtrahend) {
459 *Result = (Minuend - Subtrahend);
460 Status = RETURN_SUCCESS;
461 } else {
462 *Result = UINTN_ERROR;
463 Status = RETURN_BUFFER_TOO_SMALL;
464 }
465
466 return Status;
467 }
468 return SafeUint64Sub ((UINT64)Minuend, (UINT64)Subtrahend, (UINT64 *)Result);
469 }
470
471 /**
472 UINTN multiplication
473
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.
478
479 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
480
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.
483
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
487
488 @retval RETURN_SUCCESS Successful multiplication
489 @retval RETURN_BUFFER_TOO_SMALL Overflow
490 @retval RETURN_INVALID_PARAMETER Result is NULL
491 **/
492 RETURN_STATUS
493 EFIAPI
494 SafeUintnMult (
495 IN UINTN Multiplicand,
496 IN UINTN Multiplier,
497 OUT UINTN *Result
498 )
499 {
500 UINT64 IntermediateResult;
501
502 if (sizeof (UINTN) == sizeof (UINT32)) {
503 IntermediateResult = ((UINT64) Multiplicand) *((UINT64) Multiplier);
504
505 return SafeUint64ToUintn (IntermediateResult, Result);
506 }
507 return SafeUint64Mult ((UINT64)Multiplicand, (UINT64)Multiplier, (UINT64 *)Result);
508 }
509
510 /**
511 INTN Addition
512
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.
517
518 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
519
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.
522
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
526
527 @retval RETURN_SUCCESS Successful addition
528 @retval RETURN_BUFFER_TOO_SMALL Overflow
529 @retval RETURN_INVALID_PARAMETER Result is NULL
530 **/
531 RETURN_STATUS
532 EFIAPI
533 SafeIntnAdd (
534 IN INTN Augend,
535 IN INTN Addend,
536 OUT INTN *Result
537 )
538 {
539 if (sizeof (UINTN) == sizeof (UINT32)) {
540 return SafeInt64ToIntn (((INT64)Augend) + ((INT64)Addend), Result);
541 }
542 return SafeInt64Add ((INT64)Augend, (INT64)Addend, (INT64 *)Result);
543 }
544
545 /**
546 INTN Subtraction
547
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.
552
553 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
554
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.
557
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
561
562 @retval RETURN_SUCCESS Successful subtraction
563 @retval RETURN_BUFFER_TOO_SMALL Underflow
564 @retval RETURN_INVALID_PARAMETER Result is NULL
565 **/
566 RETURN_STATUS
567 EFIAPI
568 SafeIntnSub (
569 IN INTN Minuend,
570 IN INTN Subtrahend,
571 OUT INTN *Result
572 )
573 {
574 if (sizeof (UINTN) == sizeof (UINT32)) {
575 return SafeInt64ToIntn (((INT64)Minuend) - ((INT64)Subtrahend), Result);
576 }
577 return SafeInt64Sub ((INT64)Minuend, (INT64)Subtrahend, (INT64 *)Result);
578 }
579
580 /**
581 INTN multiplication
582
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.
587
588 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
589
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.
592
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
596
597 @retval RETURN_SUCCESS Successful multiplication
598 @retval RETURN_BUFFER_TOO_SMALL Overflow
599 @retval RETURN_INVALID_PARAMETER Result is NULL
600 **/
601 RETURN_STATUS
602 EFIAPI
603 SafeIntnMult (
604 IN INTN Multiplicand,
605 IN INTN Multiplier,
606 OUT INTN *Result
607 )
608 {
609 if (sizeof (UINTN) == sizeof (UINT32)) {
610 return SafeInt64ToIntn (((INT64)Multiplicand) *((INT64)Multiplier), Result);
611 }
612 return SafeInt64Mult ((INT64)Multiplicand, (INT64)Multiplier, (INT64 *)Result);
613 }
614