]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/BaseSafeIntLib/SafeIntLib32.c
MdePkg/BaseSafeIntLib: Add SafeIntLib class and instance
[mirror_edk2.git] / MdePkg / Library / BaseSafeIntLib / SafeIntLib32.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 return SafeInt32ToUint32 (Operand, (UINT32 *)Result);
60 }
61
62 /**
63 UINT32 -> INTN conversion
64
65 Converts the value specified by Operand to a value specified by Result type
66 and stores the converted value into the caller allocated output buffer
67 specified by Result. The caller must pass in a Result buffer that is at
68 least as large as the Result type.
69
70 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
71
72 If the conversion results in an overflow or an underflow condition, then
73 Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
74
75 @param[in] Operand Operand to be converted to new type
76 @param[out] Result Pointer to the result of conversion
77
78 @retval RETURN_SUCCESS Successful conversion
79 @retval RETURN_BUFFER_TOO_SMALL Overflow
80 @retval RETURN_INVALID_PARAMETER Result is NULL
81 **/
82 RETURN_STATUS
83 EFIAPI
84 SafeUint32ToIntn (
85 IN UINT32 Operand,
86 OUT INTN *Result
87 )
88 {
89 return SafeUint32ToInt32 (Operand, (INT32 *)Result);
90 }
91
92 /**
93 INTN -> INT32 conversion
94
95 Converts the value specified by Operand to a value specified by Result type
96 and stores the converted value into the caller allocated output buffer
97 specified by Result. The caller must pass in a Result buffer that is at
98 least as large as the Result type.
99
100 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
101
102 If the conversion results in an overflow or an underflow condition, then
103 Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
104
105 @param[in] Operand Operand to be converted to new type
106 @param[out] Result Pointer to the result of conversion
107
108 @retval RETURN_SUCCESS Successful conversion
109 @retval RETURN_BUFFER_TOO_SMALL Overflow
110 @retval RETURN_INVALID_PARAMETER Result is NULL
111 **/
112 RETURN_STATUS
113 EFIAPI
114 SafeIntnToInt32 (
115 IN INTN Operand,
116 OUT INT32 *Result
117 )
118 {
119 if (Result == NULL) {
120 return RETURN_INVALID_PARAMETER;
121 }
122
123 *Result = (INT32)Operand;
124 return RETURN_SUCCESS;
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 (Operand >= 0) {
161 *Result = (UINT32)Operand;
162 Status = RETURN_SUCCESS;
163 } else {
164 *Result = UINT32_ERROR;
165 Status = RETURN_BUFFER_TOO_SMALL;
166 }
167
168 return Status;
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 *Result = (UINT32)Operand;
203 return RETURN_SUCCESS;
204 }
205
206 /**
207 UINTN -> INT64 conversion
208
209 Converts the value specified by Operand to a value specified by Result type
210 and stores the converted value into the caller allocated output buffer
211 specified by Result. The caller must pass in a Result buffer that is at
212 least as large as the Result type.
213
214 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
215
216 If the conversion results in an overflow or an underflow condition, then
217 Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
218
219 @param[in] Operand Operand to be converted to new type
220 @param[out] Result Pointer to the result of conversion
221
222 @retval RETURN_SUCCESS Successful conversion
223 @retval RETURN_BUFFER_TOO_SMALL Overflow
224 @retval RETURN_INVALID_PARAMETER Result is NULL
225 **/
226 RETURN_STATUS
227 EFIAPI
228 SafeUintnToInt64 (
229 IN UINTN Operand,
230 OUT INT64 *Result
231 )
232 {
233 if (Result == NULL) {
234 return RETURN_INVALID_PARAMETER;
235 }
236
237 *Result = (INT64)Operand;
238 return RETURN_SUCCESS;
239 }
240
241 /**
242 INT64 -> INTN conversion
243
244 Converts the value specified by Operand to a value specified by Result type
245 and stores the converted value into the caller allocated output buffer
246 specified by Result. The caller must pass in a Result buffer that is at
247 least as large as the Result type.
248
249 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
250
251 If the conversion results in an overflow or an underflow condition, then
252 Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
253
254 @param[in] Operand Operand to be converted to new type
255 @param[out] Result Pointer to the result of conversion
256
257 @retval RETURN_SUCCESS Successful conversion
258 @retval RETURN_BUFFER_TOO_SMALL Overflow
259 @retval RETURN_INVALID_PARAMETER Result is NULL
260 **/
261 RETURN_STATUS
262 EFIAPI
263 SafeInt64ToIntn (
264 IN INT64 Operand,
265 OUT INTN *Result
266 )
267 {
268 return SafeInt64ToInt32 (Operand, (INT32 *)Result);
269 }
270
271 /**
272 INT64 -> UINTN conversion
273
274 Converts the value specified by Operand to a value specified by Result type
275 and stores the converted value into the caller allocated output buffer
276 specified by Result. The caller must pass in a Result buffer that is at
277 least as large as the Result type.
278
279 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
280
281 If the conversion results in an overflow or an underflow condition, then
282 Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
283
284 @param[in] Operand Operand to be converted to new type
285 @param[out] Result Pointer to the result of conversion
286
287 @retval RETURN_SUCCESS Successful conversion
288 @retval RETURN_BUFFER_TOO_SMALL Overflow
289 @retval RETURN_INVALID_PARAMETER Result is NULL
290 **/
291 RETURN_STATUS
292 EFIAPI
293 SafeInt64ToUintn (
294 IN INT64 Operand,
295 OUT UINTN *Result
296 )
297 {
298 return SafeInt64ToUint32 (Operand, (UINT32 *)Result);
299 }
300
301 /**
302 UINT64 -> UINTN conversion
303
304 Converts the value specified by Operand to a value specified by Result type
305 and stores the converted value into the caller allocated output buffer
306 specified by Result. The caller must pass in a Result buffer that is at
307 least as large as the Result type.
308
309 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
310
311 If the conversion results in an overflow or an underflow condition, then
312 Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
313
314 @param[in] Operand Operand to be converted to new type
315 @param[out] Result Pointer to the result of conversion
316
317 @retval RETURN_SUCCESS Successful conversion
318 @retval RETURN_BUFFER_TOO_SMALL Overflow
319 @retval RETURN_INVALID_PARAMETER Result is NULL
320 **/
321 RETURN_STATUS
322 EFIAPI
323 SafeUint64ToUintn (
324 IN UINT64 Operand,
325 OUT UINTN *Result
326 )
327 {
328 return SafeUint64ToUint32 ((UINT64) Operand, (UINT32 *)Result);
329 }
330
331 /**
332 UINTN addition
333
334 Performs the requested operation using the input parameters into a value
335 specified by Result type and stores the converted value into the caller
336 allocated output buffer specified by Result. The caller must pass in a
337 Result buffer that is at least as large as the Result type.
338
339 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
340
341 If the requested operation results in an overflow or an underflow condition,
342 then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
343
344 @param[in] Augend A number to which addend will be added
345 @param[in] Addend A number to be added to another
346 @param[out] Result Pointer to the result of addition
347
348 @retval RETURN_SUCCESS Successful addition
349 @retval RETURN_BUFFER_TOO_SMALL Overflow
350 @retval RETURN_INVALID_PARAMETER Result is NULL
351 **/
352 RETURN_STATUS
353 EFIAPI
354 SafeUintnAdd (
355 IN UINTN Augend,
356 IN UINTN Addend,
357 OUT UINTN *Result
358 )
359 {
360 RETURN_STATUS Status;
361
362 if (Result == NULL) {
363 return RETURN_INVALID_PARAMETER;
364 }
365
366 if ((Augend + Addend) >= Augend) {
367 *Result = (Augend + Addend);
368 Status = RETURN_SUCCESS;
369 } else {
370 *Result = UINTN_ERROR;
371 Status = RETURN_BUFFER_TOO_SMALL;
372 }
373
374 return Status;
375 }
376
377 /**
378 UINTN subtraction
379
380 Performs the requested operation using the input parameters into a value
381 specified by Result type and stores the converted value into the caller
382 allocated output buffer specified by Result. The caller must pass in a
383 Result buffer that is at least as large as the Result type.
384
385 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
386
387 If the requested operation results in an overflow or an underflow condition,
388 then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
389
390 @param[in] Minuend A number from which another is to be subtracted.
391 @param[in] Subtrahend A number to be subtracted from another
392 @param[out] Result Pointer to the result of subtraction
393
394 @retval RETURN_SUCCESS Successful subtraction
395 @retval RETURN_BUFFER_TOO_SMALL Underflow
396 @retval RETURN_INVALID_PARAMETER Result is NULL
397 **/
398 RETURN_STATUS
399 EFIAPI
400 SafeUintnSub (
401 IN UINTN Minuend,
402 IN UINTN Subtrahend,
403 OUT UINTN *Result
404 )
405 {
406 RETURN_STATUS Status;
407
408 if (Result == NULL) {
409 return RETURN_INVALID_PARAMETER;
410 }
411
412 if (Minuend >= Subtrahend) {
413 *Result = (Minuend - Subtrahend);
414 Status = RETURN_SUCCESS;
415 } else {
416 *Result = UINTN_ERROR;
417 Status = RETURN_BUFFER_TOO_SMALL;
418 }
419
420 return Status;
421 }
422
423 /**
424 UINTN multiplication
425
426 Performs the requested operation using the input parameters into a value
427 specified by Result type and stores the converted value into the caller
428 allocated output buffer specified by Result. The caller must pass in a
429 Result buffer that is at least as large as the Result type.
430
431 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
432
433 If the requested operation results in an overflow or an underflow condition,
434 then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
435
436 @param[in] Multiplicand A number that is to be multiplied by another
437 @param[in] Multiplier A number by which the multiplicand is to be multiplied
438 @param[out] Result Pointer to the result of multiplication
439
440 @retval RETURN_SUCCESS Successful multiplication
441 @retval RETURN_BUFFER_TOO_SMALL Overflow
442 @retval RETURN_INVALID_PARAMETER Result is NULL
443 **/
444 RETURN_STATUS
445 EFIAPI
446 SafeUintnMult (
447 IN UINTN Multiplicand,
448 IN UINTN Multiplier,
449 OUT UINTN *Result
450 )
451 {
452 UINT64 IntermediateResult;
453
454 IntermediateResult = ((UINT64) Multiplicand) *((UINT64) Multiplier);
455
456 return SafeUint64ToUintn (IntermediateResult, Result);
457 }
458
459 /**
460 INTN Addition
461
462 Performs the requested operation using the input parameters into a value
463 specified by Result type and stores the converted value into the caller
464 allocated output buffer specified by Result. The caller must pass in a
465 Result buffer that is at least as large as the Result type.
466
467 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
468
469 If the requested operation results in an overflow or an underflow condition,
470 then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
471
472 @param[in] Augend A number to which addend will be added
473 @param[in] Addend A number to be added to another
474 @param[out] Result Pointer to the result of addition
475
476 @retval RETURN_SUCCESS Successful addition
477 @retval RETURN_BUFFER_TOO_SMALL Overflow
478 @retval RETURN_INVALID_PARAMETER Result is NULL
479 **/
480 RETURN_STATUS
481 EFIAPI
482 SafeIntnAdd (
483 IN INTN Augend,
484 IN INTN Addend,
485 OUT INTN *Result
486 )
487 {
488 return SafeInt64ToIntn (((INT64)Augend) + ((INT64)Addend), Result);
489 }
490
491 /**
492 INTN Subtraction
493
494 Performs the requested operation using the input parameters into a value
495 specified by Result type and stores the converted value into the caller
496 allocated output buffer specified by Result. The caller must pass in a
497 Result buffer that is at least as large as the Result type.
498
499 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
500
501 If the requested operation results in an overflow or an underflow condition,
502 then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
503
504 @param[in] Minuend A number from which another is to be subtracted.
505 @param[in] Subtrahend A number to be subtracted from another
506 @param[out] Result Pointer to the result of subtraction
507
508 @retval RETURN_SUCCESS Successful subtraction
509 @retval RETURN_BUFFER_TOO_SMALL Underflow
510 @retval RETURN_INVALID_PARAMETER Result is NULL
511 **/
512 RETURN_STATUS
513 EFIAPI
514 SafeIntnSub (
515 IN INTN Minuend,
516 IN INTN Subtrahend,
517 OUT INTN *Result
518 )
519 {
520 return SafeInt64ToIntn (((INT64)Minuend) - ((INT64)Subtrahend), Result);
521 }
522
523 /**
524 INTN multiplication
525
526 Performs the requested operation using the input parameters into a value
527 specified by Result type and stores the converted value into the caller
528 allocated output buffer specified by Result. The caller must pass in a
529 Result buffer that is at least as large as the Result type.
530
531 If Result is NULL, RETURN_INVALID_PARAMETER is returned.
532
533 If the requested operation results in an overflow or an underflow condition,
534 then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.
535
536 @param[in] Multiplicand A number that is to be multiplied by another
537 @param[in] Multiplier A number by which the multiplicand is to be multiplied
538 @param[out] Result Pointer to the result of multiplication
539
540 @retval RETURN_SUCCESS Successful multiplication
541 @retval RETURN_BUFFER_TOO_SMALL Overflow
542 @retval RETURN_INVALID_PARAMETER Result is NULL
543 **/
544 RETURN_STATUS
545 EFIAPI
546 SafeIntnMult (
547 IN INTN Multiplicand,
548 IN INTN Multiplier,
549 OUT INTN *Result
550 )
551 {
552 return SafeInt64ToIntn (((INT64)Multiplicand) *((INT64)Multiplier), Result);
553 }
554