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