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