1 /*
2  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6 
7 /*
8  * Simple fault injection test.
9  */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <errno.h>
13 
14 #include "native_client/src/include/portability.h"
15 
16 #include "native_client/src/shared/platform/nacl_log.h"
17 #include "native_client/src/trusted/fault_injection/fault_injection.h"
18 
FunctionThatMightFail(size_t ix)19 int FunctionThatMightFail(size_t ix) {
20   return (int) ix+1;
21 }
22 
23 enum ErrorCode {
24   PASS,
25   FAIL,
26   RETAKE_PREVIOUS_GRADE,
27   GOTO_JAIL_DO_NOT_PASS_GO,
28 };
29 
SomeFunction(size_t ix)30 enum ErrorCode SomeFunction(size_t ix) {
31   switch (ix & 0x3) {
32     case 0:
33       return PASS;
34     case 1:
35       return FAIL;
36   }
37   return RETAKE_PREVIOUS_GRADE;
38 }
39 
fake_write(size_t ix)40 ssize_t fake_write(size_t ix) {
41   return (ssize_t) ix;
42 }
43 
fake_fstat(size_t ix)44 int fake_fstat(size_t ix) {
45   return (int) ix;
46 }
47 
main(int ac,char ** av)48 int main(int ac, char **av) {
49   int                   opt;
50   size_t                ix;
51   size_t                limit = 10u;
52   char                  *buffer;
53   enum ErrorCode        err;
54   static enum ErrorCode expected[4] = {
55     PASS, FAIL, RETAKE_PREVIOUS_GRADE, RETAKE_PREVIOUS_GRADE
56   };
57   ssize_t               write_result;
58 
59   NaClLogModuleInit();
60 
61   while (-1 != (opt = getopt(ac, av, "l:v"))) {
62     switch (opt) {
63       case 'v':
64         NaClLogIncrVerbosity();
65         break;
66       case 'l':
67         limit = strtoul(optarg, (char **) NULL, 0);
68         break;
69       default:
70         fprintf(stderr,
71                 "Usage: nacl_fi_test [-v]\n");
72         return 1;
73     }
74   }
75   NaClFaultInjectionModuleInit();
76 
77   for (ix = 0; ix < limit; ++ix) {
78     printf("%d\n", NACL_FI("test", FunctionThatMightFail(ix), -1));
79     buffer = NACL_FI("alloc", malloc(ix+1), NULL);
80     if (NULL == buffer) {
81       printf("allocation for %"NACL_PRIdS" bytes failed\n", ix+1);
82     } else {
83       free(buffer);
84       buffer = NULL;
85     }
86     err = NACL_FI_VAL("ret", enum ErrorCode, SomeFunction(ix));
87     if (err != expected[ix & 0x3]) {
88       printf("Unexpected return %d, expected %d\n",
89              err, expected[ix & 0x3]);
90     }
91     if (-1 == NACL_FI_SYSCALL("fstat", fake_fstat(ix))) {
92       printf("fstat failed, errno %d\n", errno);
93     }
94     if (-1 == (write_result =
95                NACL_FI_TYPED_SYSCALL("write", ssize_t, fake_write(ix)))) {
96       printf("write failed, errno %d\n", errno);
97     } else if (write_result != (ssize_t) ix) {
98       printf("unexpected write count %"NACL_PRIdS", expected %"NACL_PRIuS"\n",
99              write_result, ix);
100     }
101   }
102   return 0;
103 }
104