1 /** @file
2   x64-specific functions for unit-testing INTN and UINTN functions in
3   SafeIntLib.
4 
5   Copyright (c) Microsoft Corporation.<BR>
6   Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
7   SPDX-License-Identifier: BSD-2-Clause-Patent
8 
9 **/
10 
11 #include "TestBaseSafeIntLib.h"
12 
13 UNIT_TEST_STATUS
14 EFIAPI
TestSafeInt32ToUintn(IN UNIT_TEST_CONTEXT Context)15 TestSafeInt32ToUintn (
16   IN UNIT_TEST_CONTEXT           Context
17   )
18 {
19   EFI_STATUS  Status;
20   INT32       Operand;
21   UINTN       Result;
22 
23   //
24   // If Operand is non-negative, then it's a cast
25   //
26   Operand = 0x5bababab;
27   Result = 0;
28   Status = SafeInt32ToUintn(Operand, &Result);
29   UT_ASSERT_NOT_EFI_ERROR(Status);
30   UT_ASSERT_EQUAL(0x5bababab, Result);
31 
32   //
33   // Otherwise should result in an error status
34   //
35   Operand = (-1537977259);
36   Status = SafeInt32ToUintn(Operand, &Result);
37   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
38 
39   return UNIT_TEST_PASSED;
40 }
41 
42 UNIT_TEST_STATUS
43 EFIAPI
TestSafeUint32ToIntn(IN UNIT_TEST_CONTEXT Context)44 TestSafeUint32ToIntn (
45   IN UNIT_TEST_CONTEXT           Context
46   )
47 {
48   EFI_STATUS  Status;
49   UINT32      Operand;
50   INTN        Result;
51 
52   //
53   // For x64, INTN is same as INT64 which is a superset of INT32
54   // This is just a cast then, and it'll never fail
55   //
56 
57   //
58   // If Operand is non-negative, then it's a cast
59   //
60   Operand = 0xabababab;
61   Result = 0;
62   Status = SafeUint32ToIntn(Operand, &Result);
63   UT_ASSERT_NOT_EFI_ERROR(Status);
64   UT_ASSERT_EQUAL(0xabababab, Result);
65 
66   return UNIT_TEST_PASSED;
67 }
68 
69 UNIT_TEST_STATUS
70 EFIAPI
TestSafeIntnToInt32(IN UNIT_TEST_CONTEXT Context)71 TestSafeIntnToInt32 (
72   IN UNIT_TEST_CONTEXT           Context
73   )
74 {
75   EFI_STATUS  Status;
76   INTN        Operand;
77   INT32       Result;
78 
79   //
80   // If Operand is between MIN_INT32 and  MAX_INT32 inclusive, then it's a cast
81   //
82   Operand = 0x5bababab;
83   Result = 0;
84   Status = SafeIntnToInt32(Operand, &Result);
85   UT_ASSERT_NOT_EFI_ERROR(Status);
86   UT_ASSERT_EQUAL(0x5bababab, Result);
87 
88   Operand = (-1537977259);
89   Status = SafeIntnToInt32(Operand, &Result);
90   UT_ASSERT_NOT_EFI_ERROR(Status);
91   UT_ASSERT_EQUAL((-1537977259), Result);
92 
93   //
94   // Otherwise should result in an error status
95   //
96   Operand = (0x5babababefefefef);
97   Status = SafeIntnToInt32(Operand, &Result);
98   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
99 
100   Operand =  (-6605562033422200815);
101   Status = SafeIntnToInt32(Operand, &Result);
102   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
103 
104   return UNIT_TEST_PASSED;
105 }
106 
107 UNIT_TEST_STATUS
108 EFIAPI
TestSafeIntnToUint32(IN UNIT_TEST_CONTEXT Context)109 TestSafeIntnToUint32 (
110   IN UNIT_TEST_CONTEXT           Context
111   )
112 {
113   EFI_STATUS  Status;
114   INTN        Operand;
115   UINT32      Result;
116 
117   //
118   // If Operand is between 0 and  MAX_UINT32 inclusive, then it's a cast
119   //
120   Operand = 0xabababab;
121   Result = 0;
122   Status = SafeIntnToUint32(Operand, &Result);
123   UT_ASSERT_NOT_EFI_ERROR(Status);
124   UT_ASSERT_EQUAL(0xabababab, Result);
125 
126   //
127   // Otherwise should result in an error status
128   //
129   Operand = (0x5babababefefefef);
130   Status = SafeIntnToUint32(Operand, &Result);
131   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
132 
133   Operand =  (-6605562033422200815);
134   Status = SafeIntnToUint32(Operand, &Result);
135   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
136 
137   return UNIT_TEST_PASSED;
138 }
139 
140 UNIT_TEST_STATUS
141 EFIAPI
TestSafeUintnToUint32(IN UNIT_TEST_CONTEXT Context)142 TestSafeUintnToUint32 (
143   IN UNIT_TEST_CONTEXT           Context
144   )
145 {
146   EFI_STATUS  Status;
147   UINTN       Operand;
148   UINT32      Result;
149 
150   //
151   // If Operand is <= MAX_UINT32, then it's a cast
152   //
153   Operand = 0xabababab;
154   Result = 0;
155   Status = SafeUintnToUint32(Operand, &Result);
156   UT_ASSERT_NOT_EFI_ERROR(Status);
157   UT_ASSERT_EQUAL(0xabababab, Result);
158 
159   //
160   // Otherwise should result in an error status
161   //
162   Operand = (0xababababefefefef);
163   Status = SafeUintnToUint32(Operand, &Result);
164   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
165 
166   return UNIT_TEST_PASSED;
167 }
168 
169 UNIT_TEST_STATUS
170 EFIAPI
TestSafeUintnToIntn(IN UNIT_TEST_CONTEXT Context)171 TestSafeUintnToIntn (
172   IN UNIT_TEST_CONTEXT           Context
173   )
174 {
175   EFI_STATUS  Status;
176   UINTN       Operand;
177   INTN        Result;
178 
179   //
180   // If Operand is <= MAX_INTN (0x7fff_ffff_ffff_ffff), then it's a cast
181   //
182   Operand = 0x5babababefefefef;
183   Result = 0;
184   Status = SafeUintnToIntn(Operand, &Result);
185   UT_ASSERT_NOT_EFI_ERROR(Status);
186   UT_ASSERT_EQUAL(0x5babababefefefef, Result);
187 
188   //
189   // Otherwise should result in an error status
190   //
191   Operand = (0xababababefefefef);
192   Status = SafeUintnToIntn(Operand, &Result);
193   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
194 
195   return UNIT_TEST_PASSED;
196 }
197 
198 UNIT_TEST_STATUS
199 EFIAPI
TestSafeUintnToInt64(IN UNIT_TEST_CONTEXT Context)200 TestSafeUintnToInt64 (
201   IN UNIT_TEST_CONTEXT           Context
202   )
203 {
204   EFI_STATUS  Status;
205   UINTN       Operand;
206   INT64       Result;
207 
208   //
209   // If Operand is <= MAX_INT64, then it's a cast
210   //
211   Operand = 0x5babababefefefef;
212   Result = 0;
213   Status = SafeUintnToInt64(Operand, &Result);
214   UT_ASSERT_NOT_EFI_ERROR(Status);
215   UT_ASSERT_EQUAL(0x5babababefefefef, Result);
216 
217   //
218   // Otherwise should result in an error status
219   //
220   Operand = (0xababababefefefef);
221   Status = SafeUintnToInt64(Operand, &Result);
222   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
223 
224   return UNIT_TEST_PASSED;
225 }
226 
227 UNIT_TEST_STATUS
228 EFIAPI
TestSafeInt64ToIntn(IN UNIT_TEST_CONTEXT Context)229 TestSafeInt64ToIntn (
230   IN UNIT_TEST_CONTEXT           Context
231   )
232 {
233   EFI_STATUS  Status;
234   INT64       Operand;
235   INTN        Result;
236 
237   //
238   // INTN is same as INT64 in x64, so this is just a cast
239   //
240   Operand = 0x5babababefefefef;
241   Result = 0;
242   Status = SafeInt64ToIntn(Operand, &Result);
243   UT_ASSERT_NOT_EFI_ERROR(Status);
244   UT_ASSERT_EQUAL(0x5babababefefefef, Result);
245 
246   return UNIT_TEST_PASSED;
247 }
248 
249 UNIT_TEST_STATUS
250 EFIAPI
TestSafeInt64ToUintn(IN UNIT_TEST_CONTEXT Context)251 TestSafeInt64ToUintn (
252   IN UNIT_TEST_CONTEXT           Context
253   )
254 {
255   EFI_STATUS  Status;
256   INT64       Operand;
257   UINTN       Result;
258 
259   //
260   // If Operand is non-negative, then it's a cast
261   //
262   Operand = 0x5babababefefefef;
263   Result = 0;
264   Status = SafeInt64ToUintn(Operand, &Result);
265   UT_ASSERT_NOT_EFI_ERROR(Status);
266   UT_ASSERT_EQUAL(0x5babababefefefef, Result);
267 
268   //
269   // Otherwise should result in an error status
270   //
271   Operand =  (-6605562033422200815);
272   Status = SafeInt64ToUintn(Operand, &Result);
273   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
274 
275   return UNIT_TEST_PASSED;
276 }
277 
278 UNIT_TEST_STATUS
279 EFIAPI
TestSafeUint64ToIntn(IN UNIT_TEST_CONTEXT Context)280 TestSafeUint64ToIntn (
281   IN UNIT_TEST_CONTEXT           Context
282   )
283 {
284   EFI_STATUS  Status;
285   UINT64      Operand;
286   INTN        Result;
287 
288   //
289   // If Operand is <= MAX_INTN (0x7fff_ffff_ffff_ffff), then it's a cast
290   //
291   Operand = 0x5babababefefefef;
292   Result = 0;
293   Status = SafeUint64ToIntn(Operand, &Result);
294   UT_ASSERT_NOT_EFI_ERROR(Status);
295   UT_ASSERT_EQUAL(0x5babababefefefef, Result);
296 
297   //
298   // Otherwise should result in an error status
299   //
300   Operand = (0xababababefefefef);
301   Status = SafeUint64ToIntn(Operand, &Result);
302   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
303 
304   return UNIT_TEST_PASSED;
305 }
306 
307 UNIT_TEST_STATUS
308 EFIAPI
TestSafeUint64ToUintn(IN UNIT_TEST_CONTEXT Context)309 TestSafeUint64ToUintn (
310   IN UNIT_TEST_CONTEXT           Context
311   )
312 {
313   EFI_STATUS  Status;
314   UINT64      Operand;
315   UINTN       Result;
316 
317   //
318   // UINTN is same as UINT64 in x64, so this is just a cast
319   //
320   Operand = 0xababababefefefef;
321   Result = 0;
322   Status = SafeUint64ToUintn(Operand, &Result);
323   UT_ASSERT_NOT_EFI_ERROR(Status);
324   UT_ASSERT_EQUAL(0xababababefefefef, Result);
325 
326   return UNIT_TEST_PASSED;
327 }
328 
329 UNIT_TEST_STATUS
330 EFIAPI
TestSafeUintnAdd(IN UNIT_TEST_CONTEXT Context)331 TestSafeUintnAdd (
332   IN UNIT_TEST_CONTEXT           Context
333   )
334 {
335   EFI_STATUS  Status;
336   UINTN       Augend;
337   UINTN       Addend;
338   UINTN       Result;
339 
340   //
341   // If the result of addition doesn't overflow MAX_UINTN, then it's addition
342   //
343   Augend = 0x3a3a3a3a12121212;
344   Addend = 0x3a3a3a3a12121212;
345   Result = 0;
346   Status = SafeUintnAdd(Augend, Addend, &Result);
347   UT_ASSERT_NOT_EFI_ERROR(Status);
348   UT_ASSERT_EQUAL(0x7474747424242424, Result);
349 
350   //
351   // Otherwise should result in an error status
352   //
353   Augend = 0xababababefefefef;
354   Addend = 0xbcbcbcbcdededede;
355   Status = SafeUintnAdd(Augend, Addend, &Result);
356   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
357 
358   return UNIT_TEST_PASSED;
359 }
360 
361 UNIT_TEST_STATUS
362 EFIAPI
TestSafeIntnAdd(IN UNIT_TEST_CONTEXT Context)363 TestSafeIntnAdd (
364   IN UNIT_TEST_CONTEXT           Context
365   )
366 {
367   EFI_STATUS  Status;
368   INTN        Augend;
369   INTN        Addend;
370   INTN        Result;
371 
372   //
373   // If the result of addition doesn't overflow MAX_INTN
374   // and doesn't underflow MIN_INTN, then it's addition
375   //
376   Augend = 0x3a3a3a3a3a3a3a3a;
377   Addend = 0x3a3a3a3a3a3a3a3a;
378   Result = 0;
379   Status = SafeIntnAdd(Augend, Addend, &Result);
380   UT_ASSERT_NOT_EFI_ERROR(Status);
381   UT_ASSERT_EQUAL(0x7474747474747474, Result);
382 
383   Augend = (-4195730024608447034);
384   Addend = (-4195730024608447034);
385   Status = SafeIntnAdd(Augend, Addend, &Result);
386   UT_ASSERT_NOT_EFI_ERROR(Status);
387   UT_ASSERT_EQUAL((-8391460049216894068), Result);
388 
389   //
390   // Otherwise should result in an error status
391   //
392   Augend = 0x5a5a5a5a5a5a5a5a;
393   Addend = 0x5a5a5a5a5a5a5a5a;
394   Status = SafeIntnAdd(Augend, Addend, &Result);
395   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
396 
397   Augend = (-6510615555426900570);
398   Addend = (-6510615555426900570);
399   Status = SafeIntnAdd(Augend, Addend, &Result);
400   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
401 
402   return UNIT_TEST_PASSED;
403 }
404 
405 UNIT_TEST_STATUS
406 EFIAPI
TestSafeUintnSub(IN UNIT_TEST_CONTEXT Context)407 TestSafeUintnSub (
408   IN UNIT_TEST_CONTEXT           Context
409   )
410 {
411   EFI_STATUS  Status;
412   UINTN       Minuend;
413   UINTN       Subtrahend;
414   UINTN       Result;
415 
416   //
417   // If Minuend >= Subtrahend, then it's subtraction
418   //
419   Minuend = 0x5a5a5a5a5a5a5a5a;
420   Subtrahend = 0x3b3b3b3b3b3b3b3b;
421   Result = 0;
422   Status = SafeUintnSub(Minuend, Subtrahend, &Result);
423   UT_ASSERT_NOT_EFI_ERROR(Status);
424   UT_ASSERT_EQUAL(0x1f1f1f1f1f1f1f1f, Result);
425 
426   //
427   // Otherwise should result in an error status
428   //
429   Minuend = 0x5a5a5a5a5a5a5a5a;
430   Subtrahend = 0x6d6d6d6d6d6d6d6d;
431   Status = SafeUintnSub(Minuend, Subtrahend, &Result);
432   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
433 
434   return UNIT_TEST_PASSED;
435 }
436 
437 UNIT_TEST_STATUS
438 EFIAPI
TestSafeIntnSub(IN UNIT_TEST_CONTEXT Context)439 TestSafeIntnSub (
440   IN UNIT_TEST_CONTEXT           Context
441   )
442 {
443   EFI_STATUS  Status;
444   INTN        Minuend;
445   INTN        Subtrahend;
446   INTN        Result;
447 
448   //
449   // If the result of subtractions doesn't overflow MAX_INTN or
450   // underflow MIN_INTN, then it's subtraction
451   //
452   Minuend = 0x5a5a5a5a5a5a5a5a;
453   Subtrahend = 0x3a3a3a3a3a3a3a3a;
454   Result = 0;
455   Status = SafeIntnSub(Minuend, Subtrahend, &Result);
456   UT_ASSERT_NOT_EFI_ERROR(Status);
457   UT_ASSERT_EQUAL(0x2020202020202020, Result);
458 
459   Minuend = 0x3a3a3a3a3a3a3a3a;
460   Subtrahend = 0x5a5a5a5a5a5a5a5a;
461   Status = SafeIntnSub(Minuend, Subtrahend, &Result);
462   UT_ASSERT_NOT_EFI_ERROR(Status);
463   UT_ASSERT_EQUAL((-2314885530818453536), Result);
464 
465   //
466   // Otherwise should result in an error status
467   //
468   Minuend = (-8825501086245354106);
469   Subtrahend = 8825501086245354106;
470   Status = SafeIntnSub(Minuend, Subtrahend, &Result);
471   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
472 
473   Minuend = (8825501086245354106);
474   Subtrahend = (-8825501086245354106);
475   Status = SafeIntnSub(Minuend, Subtrahend, &Result);
476   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
477 
478   return UNIT_TEST_PASSED;
479 }
480 
481 UNIT_TEST_STATUS
482 EFIAPI
TestSafeUintnMult(IN UNIT_TEST_CONTEXT Context)483 TestSafeUintnMult (
484   IN UNIT_TEST_CONTEXT           Context
485   )
486 {
487   EFI_STATUS  Status;
488   UINTN       Multiplicand;
489   UINTN       Multiplier;
490   UINTN       Result;
491 
492   //
493   // If the result of multiplication doesn't overflow MAX_UINTN, it will succeed
494   //
495   Multiplicand = 0x123456789a;
496   Multiplier = 0x1234567;
497   Result = 0;
498   Status = SafeUintnMult(Multiplicand, Multiplier, &Result);
499   UT_ASSERT_NOT_EFI_ERROR(Status);
500   UT_ASSERT_EQUAL(0x14b66db9745a07f6, Result);
501 
502   //
503   // Otherwise should result in an error status
504   //
505   Multiplicand = 0x123456789a;
506   Multiplier = 0x12345678;
507   Status = SafeUintnMult(Multiplicand, Multiplier, &Result);
508   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
509 
510   return UNIT_TEST_PASSED;
511 }
512 
513 UNIT_TEST_STATUS
514 EFIAPI
TestSafeIntnMult(IN UNIT_TEST_CONTEXT Context)515 TestSafeIntnMult (
516   IN UNIT_TEST_CONTEXT           Context
517   )
518 {
519   EFI_STATUS  Status;
520   INTN        Multiplicand;
521   INTN        Multiplier;
522   INTN        Result;
523 
524   //
525   // If the result of multiplication doesn't overflow MAX_INTN and doesn't
526   // underflow MIN_UINTN, it will succeed
527   //
528   Multiplicand = 0x123456789;
529   Multiplier = 0x6789abcd;
530   Result = 0;
531   Status = SafeIntnMult(Multiplicand, Multiplier, &Result);
532   UT_ASSERT_NOT_EFI_ERROR(Status);
533   UT_ASSERT_EQUAL(0x75cd9045220d6bb5, Result);
534 
535   //
536   // Otherwise should result in an error status
537   //
538   Multiplicand = 0x123456789;
539   Multiplier = 0xa789abcd;
540   Status = SafeIntnMult(Multiplicand, Multiplier, &Result);
541   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
542 
543   return UNIT_TEST_PASSED;
544 }
545