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