]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BaseSafeIntLib/SafeIntLib32.c
MdePkg/BaseSafeIntLib: Fix VS2015 IA32 NOOPT build failure
[mirror_edk2.git] / MdePkg / Library / BaseSafeIntLib / SafeIntLib32.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
8 Redistribution and use in source and binary forms, with or without\r
9 modification, are permitted provided that the following conditions are met:\r
10 1. Redistributions of source code must retain the above copyright notice,\r
11 this list of conditions and the following disclaimer.\r
12 2. Redistributions in binary form must reproduce the above copyright notice,\r
13 this list of conditions and the following disclaimer in the documentation\r
14 and/or other materials provided with the distribution.\r
15\r
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
19 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\r
20 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\r
21 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
23 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
24 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\r
25 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
26\r
27**/\r
28\r
29#include <Base.h>\r
30#include <Library/SafeIntLib.h>\r
dc9b2a57 31#include <Library/BaseLib.h>\r
d7a09cb8
SB
32\r
33/**\r
34 INT32 -> UINTN conversion\r
35\r
36 Converts the value specified by Operand to a value specified by Result type\r
37 and stores the converted value into the caller allocated output buffer\r
38 specified by Result. The caller must pass in a Result buffer that is at\r
39 least as large as the Result type.\r
40\r
41 If Result is NULL, RETURN_INVALID_PARAMETER is returned.\r
42\r
43 If the conversion results in an overflow or an underflow condition, then\r
44 Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.\r
45\r
46 @param[in] Operand Operand to be converted to new type\r
47 @param[out] Result Pointer to the result of conversion\r
48\r
49 @retval RETURN_SUCCESS Successful conversion\r
50 @retval RETURN_BUFFER_TOO_SMALL Overflow\r
51 @retval RETURN_INVALID_PARAMETER Result is NULL\r
52**/\r
53RETURN_STATUS\r
54EFIAPI\r
55SafeInt32ToUintn (\r
56 IN INT32 Operand,\r
57 OUT UINTN *Result\r
58 )\r
59{\r
60 return SafeInt32ToUint32 (Operand, (UINT32 *)Result);\r
61}\r
62\r
63/**\r
64 UINT32 -> INTN conversion\r
65\r
66 Converts the value specified by Operand to a value specified by Result type\r
67 and stores the converted value into the caller allocated output buffer\r
68 specified by Result. The caller must pass in a Result buffer that is at\r
69 least as large as the Result type.\r
70\r
71 If Result is NULL, RETURN_INVALID_PARAMETER is returned.\r
72\r
73 If the conversion results in an overflow or an underflow condition, then\r
74 Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.\r
75\r
76 @param[in] Operand Operand to be converted to new type\r
77 @param[out] Result Pointer to the result of conversion\r
78\r
79 @retval RETURN_SUCCESS Successful conversion\r
80 @retval RETURN_BUFFER_TOO_SMALL Overflow\r
81 @retval RETURN_INVALID_PARAMETER Result is NULL\r
82**/\r
83RETURN_STATUS\r
84EFIAPI\r
85SafeUint32ToIntn (\r
86 IN UINT32 Operand,\r
87 OUT INTN *Result\r
88 )\r
89{\r
90 return SafeUint32ToInt32 (Operand, (INT32 *)Result);\r
91}\r
92\r
93/**\r
94 INTN -> INT32 conversion\r
95\r
96 Converts the value specified by Operand to a value specified by Result type\r
97 and stores the converted value into the caller allocated output buffer\r
98 specified by Result. The caller must pass in a Result buffer that is at\r
99 least as large as the Result type.\r
100\r
101 If Result is NULL, RETURN_INVALID_PARAMETER is returned.\r
102\r
103 If the conversion results in an overflow or an underflow condition, then\r
104 Result is set to INT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.\r
105\r
106 @param[in] Operand Operand to be converted to new type\r
107 @param[out] Result Pointer to the result of conversion\r
108\r
109 @retval RETURN_SUCCESS Successful conversion\r
110 @retval RETURN_BUFFER_TOO_SMALL Overflow\r
111 @retval RETURN_INVALID_PARAMETER Result is NULL\r
112**/\r
113RETURN_STATUS\r
114EFIAPI\r
115SafeIntnToInt32 (\r
116 IN INTN Operand,\r
117 OUT INT32 *Result\r
118 )\r
119{\r
120 if (Result == NULL) {\r
121 return RETURN_INVALID_PARAMETER;\r
122 }\r
123\r
124 *Result = (INT32)Operand;\r
125 return RETURN_SUCCESS;\r
126}\r
127\r
128/**\r
129 INTN -> UINT32 conversion\r
130\r
131 Converts the value specified by Operand to a value specified by Result type\r
132 and stores the converted value into the caller allocated output buffer\r
133 specified by Result. The caller must pass in a Result buffer that is at\r
134 least as large as the Result type.\r
135\r
136 If Result is NULL, RETURN_INVALID_PARAMETER is returned.\r
137\r
138 If the conversion results in an overflow or an underflow condition, then\r
139 Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.\r
140\r
141 @param[in] Operand Operand to be converted to new type\r
142 @param[out] Result Pointer to the result of conversion\r
143\r
144 @retval RETURN_SUCCESS Successful conversion\r
145 @retval RETURN_BUFFER_TOO_SMALL Overflow\r
146 @retval RETURN_INVALID_PARAMETER Result is NULL\r
147**/\r
148RETURN_STATUS\r
149EFIAPI\r
150SafeIntnToUint32 (\r
151 IN INTN Operand,\r
152 OUT UINT32 *Result\r
153 )\r
154{\r
155 RETURN_STATUS Status;\r
156\r
157 if (Result == NULL) {\r
158 return RETURN_INVALID_PARAMETER;\r
159 }\r
160\r
161 if (Operand >= 0) {\r
162 *Result = (UINT32)Operand;\r
163 Status = RETURN_SUCCESS;\r
164 } else {\r
165 *Result = UINT32_ERROR;\r
166 Status = RETURN_BUFFER_TOO_SMALL;\r
167 }\r
168\r
169 return Status;\r
170}\r
171\r
172/**\r
173 UINTN -> UINT32 conversion\r
174\r
175 Converts the value specified by Operand to a value specified by Result type\r
176 and stores the converted value into the caller allocated output buffer\r
177 specified by Result. The caller must pass in a Result buffer that is at\r
178 least as large as the Result type.\r
179\r
180 If Result is NULL, RETURN_INVALID_PARAMETER is returned.\r
181\r
182 If the conversion results in an overflow or an underflow condition, then\r
183 Result is set to UINT32_ERROR and RETURN_BUFFER_TOO_SMALL is returned.\r
184\r
185 @param[in] Operand Operand to be converted to new type\r
186 @param[out] Result Pointer to the result of conversion\r
187\r
188 @retval RETURN_SUCCESS Successful conversion\r
189 @retval RETURN_BUFFER_TOO_SMALL Overflow\r
190 @retval RETURN_INVALID_PARAMETER Result is NULL\r
191**/\r
192RETURN_STATUS\r
193EFIAPI\r
194SafeUintnToUint32 (\r
195 IN UINTN Operand,\r
196 OUT UINT32 *Result\r
197 )\r
198{\r
199 if (Result == NULL) {\r
200 return RETURN_INVALID_PARAMETER;\r
201 }\r
202\r
203 *Result = (UINT32)Operand;\r
204 return RETURN_SUCCESS;\r
205}\r
206\r
207/**\r
208 UINTN -> INT64 conversion\r
209\r
210 Converts the value specified by Operand to a value specified by Result type\r
211 and stores the converted value into the caller allocated output buffer\r
212 specified by Result. The caller must pass in a Result buffer that is at\r
213 least as large as the Result type.\r
214\r
215 If Result is NULL, RETURN_INVALID_PARAMETER is returned.\r
216\r
217 If the conversion results in an overflow or an underflow condition, then\r
218 Result is set to INT64_ERROR and RETURN_BUFFER_TOO_SMALL is returned.\r
219\r
220 @param[in] Operand Operand to be converted to new type\r
221 @param[out] Result Pointer to the result of conversion\r
222\r
223 @retval RETURN_SUCCESS Successful conversion\r
224 @retval RETURN_BUFFER_TOO_SMALL Overflow\r
225 @retval RETURN_INVALID_PARAMETER Result is NULL\r
226**/\r
227RETURN_STATUS\r
228EFIAPI\r
229SafeUintnToInt64 (\r
230 IN UINTN Operand,\r
231 OUT INT64 *Result\r
232 )\r
233{\r
234 if (Result == NULL) {\r
235 return RETURN_INVALID_PARAMETER;\r
236 }\r
237\r
238 *Result = (INT64)Operand;\r
239 return RETURN_SUCCESS;\r
240}\r
241\r
242/**\r
243 INT64 -> INTN conversion\r
244\r
245 Converts the value specified by Operand to a value specified by Result type\r
246 and stores the converted value into the caller allocated output buffer\r
247 specified by Result. The caller must pass in a Result buffer that is at\r
248 least as large as the Result type.\r
249\r
250 If Result is NULL, RETURN_INVALID_PARAMETER is returned.\r
251\r
252 If the conversion results in an overflow or an underflow condition, then\r
253 Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.\r
254\r
255 @param[in] Operand Operand to be converted to new type\r
256 @param[out] Result Pointer to the result of conversion\r
257\r
258 @retval RETURN_SUCCESS Successful conversion\r
259 @retval RETURN_BUFFER_TOO_SMALL Overflow\r
260 @retval RETURN_INVALID_PARAMETER Result is NULL\r
261**/\r
262RETURN_STATUS\r
263EFIAPI\r
264SafeInt64ToIntn (\r
265 IN INT64 Operand,\r
266 OUT INTN *Result\r
267 )\r
268{\r
269 return SafeInt64ToInt32 (Operand, (INT32 *)Result);\r
270}\r
271\r
272/**\r
273 INT64 -> UINTN conversion\r
274\r
275 Converts the value specified by Operand to a value specified by Result type\r
276 and stores the converted value into the caller allocated output buffer\r
277 specified by Result. The caller must pass in a Result buffer that is at\r
278 least as large as the Result type.\r
279\r
280 If Result is NULL, RETURN_INVALID_PARAMETER is returned.\r
281\r
282 If the conversion results in an overflow or an underflow condition, then\r
283 Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.\r
284\r
285 @param[in] Operand Operand to be converted to new type\r
286 @param[out] Result Pointer to the result of conversion\r
287\r
288 @retval RETURN_SUCCESS Successful conversion\r
289 @retval RETURN_BUFFER_TOO_SMALL Overflow\r
290 @retval RETURN_INVALID_PARAMETER Result is NULL\r
291**/\r
292RETURN_STATUS\r
293EFIAPI\r
294SafeInt64ToUintn (\r
295 IN INT64 Operand,\r
296 OUT UINTN *Result\r
297 )\r
298{\r
299 return SafeInt64ToUint32 (Operand, (UINT32 *)Result);\r
300}\r
301\r
302/**\r
303 UINT64 -> UINTN conversion\r
304\r
305 Converts the value specified by Operand to a value specified by Result type\r
306 and stores the converted value into the caller allocated output buffer\r
307 specified by Result. The caller must pass in a Result buffer that is at\r
308 least as large as the Result type.\r
309\r
310 If Result is NULL, RETURN_INVALID_PARAMETER is returned.\r
311\r
312 If the conversion results in an overflow or an underflow condition, then\r
313 Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.\r
314\r
315 @param[in] Operand Operand to be converted to new type\r
316 @param[out] Result Pointer to the result of conversion\r
317\r
318 @retval RETURN_SUCCESS Successful conversion\r
319 @retval RETURN_BUFFER_TOO_SMALL Overflow\r
320 @retval RETURN_INVALID_PARAMETER Result is NULL\r
321**/\r
322RETURN_STATUS\r
323EFIAPI\r
324SafeUint64ToUintn (\r
325 IN UINT64 Operand,\r
326 OUT UINTN *Result\r
327 )\r
328{\r
329 return SafeUint64ToUint32 ((UINT64) Operand, (UINT32 *)Result);\r
330}\r
331\r
332/**\r
333 UINTN addition\r
334\r
335 Performs the requested operation using the input parameters into a value\r
336 specified by Result type and stores the converted value into the caller\r
337 allocated output buffer specified by Result. The caller must pass in a\r
338 Result buffer that is at least as large as the Result type.\r
339\r
340 If Result is NULL, RETURN_INVALID_PARAMETER is returned.\r
341\r
342 If the requested operation results in an overflow or an underflow condition,\r
343 then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.\r
344\r
345 @param[in] Augend A number to which addend will be added\r
346 @param[in] Addend A number to be added to another\r
347 @param[out] Result Pointer to the result of addition\r
348\r
349 @retval RETURN_SUCCESS Successful addition\r
350 @retval RETURN_BUFFER_TOO_SMALL Overflow\r
351 @retval RETURN_INVALID_PARAMETER Result is NULL\r
352**/\r
353RETURN_STATUS\r
354EFIAPI\r
355SafeUintnAdd (\r
356 IN UINTN Augend,\r
357 IN UINTN Addend,\r
358 OUT UINTN *Result\r
359 )\r
360{\r
361 RETURN_STATUS Status;\r
362\r
363 if (Result == NULL) {\r
364 return RETURN_INVALID_PARAMETER;\r
365 }\r
366\r
367 if ((Augend + Addend) >= Augend) {\r
368 *Result = (Augend + Addend);\r
369 Status = RETURN_SUCCESS;\r
370 } else {\r
371 *Result = UINTN_ERROR;\r
372 Status = RETURN_BUFFER_TOO_SMALL;\r
373 }\r
374\r
375 return Status;\r
376}\r
377\r
378/**\r
379 UINTN subtraction\r
380\r
381 Performs the requested operation using the input parameters into a value\r
382 specified by Result type and stores the converted value into the caller\r
383 allocated output buffer specified by Result. The caller must pass in a\r
384 Result buffer that is at least as large as the Result type.\r
385\r
386 If Result is NULL, RETURN_INVALID_PARAMETER is returned.\r
387\r
388 If the requested operation results in an overflow or an underflow condition,\r
389 then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.\r
390\r
391 @param[in] Minuend A number from which another is to be subtracted.\r
392 @param[in] Subtrahend A number to be subtracted from another\r
393 @param[out] Result Pointer to the result of subtraction\r
394\r
395 @retval RETURN_SUCCESS Successful subtraction\r
396 @retval RETURN_BUFFER_TOO_SMALL Underflow\r
397 @retval RETURN_INVALID_PARAMETER Result is NULL\r
398**/\r
399RETURN_STATUS\r
400EFIAPI\r
401SafeUintnSub (\r
402 IN UINTN Minuend,\r
403 IN UINTN Subtrahend,\r
404 OUT UINTN *Result\r
405 )\r
406{\r
407 RETURN_STATUS Status;\r
408\r
409 if (Result == NULL) {\r
410 return RETURN_INVALID_PARAMETER;\r
411 }\r
412\r
413 if (Minuend >= Subtrahend) {\r
414 *Result = (Minuend - Subtrahend);\r
415 Status = RETURN_SUCCESS;\r
416 } else {\r
417 *Result = UINTN_ERROR;\r
418 Status = RETURN_BUFFER_TOO_SMALL;\r
419 }\r
420\r
421 return Status;\r
422}\r
423\r
424/**\r
425 UINTN multiplication\r
426\r
427 Performs the requested operation using the input parameters into a value\r
428 specified by Result type and stores the converted value into the caller\r
429 allocated output buffer specified by Result. The caller must pass in a\r
430 Result buffer that is at least as large as the Result type.\r
431\r
432 If Result is NULL, RETURN_INVALID_PARAMETER is returned.\r
433\r
434 If the requested operation results in an overflow or an underflow condition,\r
435 then Result is set to UINTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.\r
436\r
437 @param[in] Multiplicand A number that is to be multiplied by another\r
438 @param[in] Multiplier A number by which the multiplicand is to be multiplied\r
439 @param[out] Result Pointer to the result of multiplication\r
440\r
441 @retval RETURN_SUCCESS Successful multiplication\r
442 @retval RETURN_BUFFER_TOO_SMALL Overflow\r
443 @retval RETURN_INVALID_PARAMETER Result is NULL\r
444**/\r
445RETURN_STATUS\r
446EFIAPI\r
447SafeUintnMult (\r
448 IN UINTN Multiplicand,\r
449 IN UINTN Multiplier,\r
450 OUT UINTN *Result\r
451 )\r
452{\r
453 UINT64 IntermediateResult;\r
454\r
455 IntermediateResult = ((UINT64) Multiplicand) *((UINT64) Multiplier);\r
456\r
457 return SafeUint64ToUintn (IntermediateResult, Result);\r
458}\r
459\r
460/**\r
461 INTN Addition\r
462\r
463 Performs the requested operation using the input parameters into a value\r
464 specified by Result type and stores the converted value into the caller\r
465 allocated output buffer specified by Result. The caller must pass in a\r
466 Result buffer that is at least as large as the Result type.\r
467\r
468 If Result is NULL, RETURN_INVALID_PARAMETER is returned.\r
469\r
470 If the requested operation results in an overflow or an underflow condition,\r
471 then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.\r
472\r
473 @param[in] Augend A number to which addend will be added\r
474 @param[in] Addend A number to be added to another\r
475 @param[out] Result Pointer to the result of addition\r
476\r
477 @retval RETURN_SUCCESS Successful addition\r
478 @retval RETURN_BUFFER_TOO_SMALL Overflow\r
479 @retval RETURN_INVALID_PARAMETER Result is NULL\r
480**/\r
481RETURN_STATUS\r
482EFIAPI\r
483SafeIntnAdd (\r
484 IN INTN Augend,\r
485 IN INTN Addend,\r
486 OUT INTN *Result\r
487 )\r
488{\r
489 return SafeInt64ToIntn (((INT64)Augend) + ((INT64)Addend), Result);\r
490}\r
491\r
492/**\r
493 INTN Subtraction\r
494\r
495 Performs the requested operation using the input parameters into a value\r
496 specified by Result type and stores the converted value into the caller\r
497 allocated output buffer specified by Result. The caller must pass in a\r
498 Result buffer that is at least as large as the Result type.\r
499\r
500 If Result is NULL, RETURN_INVALID_PARAMETER is returned.\r
501\r
502 If the requested operation results in an overflow or an underflow condition,\r
503 then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.\r
504\r
505 @param[in] Minuend A number from which another is to be subtracted.\r
506 @param[in] Subtrahend A number to be subtracted from another\r
507 @param[out] Result Pointer to the result of subtraction\r
508\r
509 @retval RETURN_SUCCESS Successful subtraction\r
510 @retval RETURN_BUFFER_TOO_SMALL Underflow\r
511 @retval RETURN_INVALID_PARAMETER Result is NULL\r
512**/\r
513RETURN_STATUS\r
514EFIAPI\r
515SafeIntnSub (\r
516 IN INTN Minuend,\r
517 IN INTN Subtrahend,\r
518 OUT INTN *Result\r
519 )\r
520{\r
521 return SafeInt64ToIntn (((INT64)Minuend) - ((INT64)Subtrahend), Result);\r
522}\r
523\r
524/**\r
525 INTN multiplication\r
526\r
527 Performs the requested operation using the input parameters into a value\r
528 specified by Result type and stores the converted value into the caller\r
529 allocated output buffer specified by Result. The caller must pass in a\r
530 Result buffer that is at least as large as the Result type.\r
531\r
532 If Result is NULL, RETURN_INVALID_PARAMETER is returned.\r
533\r
534 If the requested operation results in an overflow or an underflow condition,\r
535 then Result is set to INTN_ERROR and RETURN_BUFFER_TOO_SMALL is returned.\r
536\r
537 @param[in] Multiplicand A number that is to be multiplied by another\r
538 @param[in] Multiplier A number by which the multiplicand is to be multiplied\r
539 @param[out] Result Pointer to the result of multiplication\r
540\r
541 @retval RETURN_SUCCESS Successful multiplication\r
542 @retval RETURN_BUFFER_TOO_SMALL Overflow\r
543 @retval RETURN_INVALID_PARAMETER Result is NULL\r
544**/\r
545RETURN_STATUS\r
546EFIAPI\r
547SafeIntnMult (\r
548 IN INTN Multiplicand,\r
549 IN INTN Multiplier,\r
550 OUT INTN *Result\r
551 )\r
552{\r
dc9b2a57 553 return SafeInt64ToIntn (MultS64x64 (Multiplicand, Multiplier), Result);\r
d7a09cb8
SB
554}\r
555\r