OLD | NEW |
1 /* | 1 /* |
2 american fuzzy lop - test case minimizer | 2 american fuzzy lop - test case minimizer |
3 ---------------------------------------- | 3 ---------------------------------------- |
4 | 4 |
5 Written and maintained by Michal Zalewski <lcamtuf@google.com> | 5 Written and maintained by Michal Zalewski <lcamtuf@google.com> |
6 | 6 |
7 Copyright 2015, 2016 Google Inc. All rights reserved. | 7 Copyright 2015, 2016 Google Inc. All rights reserved. |
8 | 8 |
9 Licensed under the Apache License, Version 2.0 (the "License"); | 9 Licensed under the Apache License, Version 2.0 (the "License"); |
10 you may not use this file except in compliance with the License. | 10 you may not use this file except in compliance with the License. |
(...skipping 28 matching lines...) Expand all Loading... |
39 | 39 |
40 #include <sys/wait.h> | 40 #include <sys/wait.h> |
41 #include <sys/time.h> | 41 #include <sys/time.h> |
42 #include <sys/shm.h> | 42 #include <sys/shm.h> |
43 #include <sys/stat.h> | 43 #include <sys/stat.h> |
44 #include <sys/types.h> | 44 #include <sys/types.h> |
45 #include <sys/resource.h> | 45 #include <sys/resource.h> |
46 | 46 |
47 static s32 child_pid; /* PID of the tested program */ | 47 static s32 child_pid; /* PID of the tested program */ |
48 | 48 |
49 static u8* trace_bits; /* SHM with instrumentation bitmap */ | 49 static u8 *trace_bits, /* SHM with instrumentation bitmap */ |
| 50 *mask_bitmap; /* Mask for trace bits (-B) */ |
50 | 51 |
51 static u8 *in_file, /* Minimizer input test case */ | 52 static u8 *in_file, /* Minimizer input test case */ |
52 *out_file, /* Minimizer output file */ | 53 *out_file, /* Minimizer output file */ |
53 *prog_in, /* Targeted program input file */ | 54 *prog_in, /* Targeted program input file */ |
54 *target_path, /* Path to target binary */ | 55 *target_path, /* Path to target binary */ |
55 *doc_path; /* Path to docs */ | 56 *doc_path; /* Path to docs */ |
56 | 57 |
57 static u8* in_data; /* Input data for trimming */ | 58 static u8* in_data; /* Input data for trimming */ |
58 | 59 |
59 static u32 in_len, /* Input data length */ | 60 static u32 in_len, /* Input data length */ |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 while (i--) { | 112 while (i--) { |
112 *mem = count_class_lookup[*mem]; | 113 *mem = count_class_lookup[*mem]; |
113 mem++; | 114 mem++; |
114 } | 115 } |
115 | 116 |
116 } | 117 } |
117 | 118 |
118 } | 119 } |
119 | 120 |
120 | 121 |
| 122 /* Apply mask to classified bitmap (if set). */ |
| 123 |
| 124 static void apply_mask(u32* mem, u32* mask) { |
| 125 |
| 126 u32 i = (MAP_SIZE >> 2); |
| 127 |
| 128 if (!mask) return; |
| 129 |
| 130 while (i--) { |
| 131 |
| 132 *mem &= ~*mask; |
| 133 mem++; |
| 134 mask++; |
| 135 |
| 136 } |
| 137 |
| 138 } |
| 139 |
| 140 |
121 /* See if any bytes are set in the bitmap. */ | 141 /* See if any bytes are set in the bitmap. */ |
122 | 142 |
123 static inline u8 anything_set(void) { | 143 static inline u8 anything_set(void) { |
124 | 144 |
125 u32* ptr = (u32*)trace_bits; | 145 u32* ptr = (u32*)trace_bits; |
126 u32 i = (MAP_SIZE >> 2); | 146 u32 i = (MAP_SIZE >> 2); |
127 | 147 |
128 while (i--) if (*(ptr++)) return 1; | 148 while (i--) if (*(ptr++)) return 1; |
129 | 149 |
130 return 0; | 150 return 0; |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 setitimer(ITIMER_REAL, &it, NULL); | 327 setitimer(ITIMER_REAL, &it, NULL); |
308 | 328 |
309 MEM_BARRIER(); | 329 MEM_BARRIER(); |
310 | 330 |
311 /* Clean up bitmap, analyze exit condition, etc. */ | 331 /* Clean up bitmap, analyze exit condition, etc. */ |
312 | 332 |
313 if (*(u32*)trace_bits == EXEC_FAIL_SIG) | 333 if (*(u32*)trace_bits == EXEC_FAIL_SIG) |
314 FATAL("Unable to execute '%s'", argv[0]); | 334 FATAL("Unable to execute '%s'", argv[0]); |
315 | 335 |
316 classify_counts(trace_bits); | 336 classify_counts(trace_bits); |
| 337 apply_mask((u32*)trace_bits, (u32*)mask_bitmap); |
317 total_execs++; | 338 total_execs++; |
318 | 339 |
319 if (stop_soon) { | 340 if (stop_soon) { |
320 SAYF(cRST cLRD "\n+++ Minimization aborted by user +++\n" cRST); | 341 SAYF(cRST cLRD "\n+++ Minimization aborted by user +++\n" cRST); |
321 exit(1); | 342 exit(1); |
322 } | 343 } |
323 | 344 |
324 /* Always discard inputs that time out. */ | 345 /* Always discard inputs that time out. */ |
325 | 346 |
326 if (child_timed_out) { | 347 if (child_timed_out) { |
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
912 target_path = new_argv[0] = BIN_PATH "/afl-qemu-trace"; | 933 target_path = new_argv[0] = BIN_PATH "/afl-qemu-trace"; |
913 return new_argv; | 934 return new_argv; |
914 | 935 |
915 } | 936 } |
916 | 937 |
917 FATAL("Unable to find 'afl-qemu-trace'."); | 938 FATAL("Unable to find 'afl-qemu-trace'."); |
918 | 939 |
919 } | 940 } |
920 | 941 |
921 | 942 |
| 943 /* Read mask bitmap from file. This is for the -B option. */ |
| 944 |
| 945 static void read_bitmap(u8* fname) { |
| 946 |
| 947 s32 fd = open(fname, O_RDONLY); |
| 948 |
| 949 if (fd < 0) PFATAL("Unable to open '%s'", fname); |
| 950 |
| 951 ck_read(fd, mask_bitmap, MAP_SIZE, fname); |
| 952 |
| 953 close(fd); |
| 954 |
| 955 } |
| 956 |
| 957 |
| 958 |
922 /* Main entry point */ | 959 /* Main entry point */ |
923 | 960 |
924 int main(int argc, char** argv) { | 961 int main(int argc, char** argv) { |
925 | 962 |
926 s32 opt; | 963 s32 opt; |
927 u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0; | 964 u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0; |
928 char** use_argv; | 965 char** use_argv; |
929 | 966 |
930 doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; | 967 doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; |
931 | 968 |
932 SAYF(cCYA "afl-tmin " cBRI VERSION cRST " by <lcamtuf@google.com>\n"); | 969 SAYF(cCYA "afl-tmin " cBRI VERSION cRST " by <lcamtuf@google.com>\n"); |
933 | 970 |
934 while ((opt = getopt(argc,argv,"+i:o:f:m:t:xeQ")) > 0) | 971 while ((opt = getopt(argc,argv,"+i:o:f:m:t:B:xeQ")) > 0) |
935 | 972 |
936 switch (opt) { | 973 switch (opt) { |
937 | 974 |
938 case 'i': | 975 case 'i': |
939 | 976 |
940 if (in_file) FATAL("Multiple -i options not supported"); | 977 if (in_file) FATAL("Multiple -i options not supported"); |
941 in_file = optarg; | 978 in_file = optarg; |
942 break; | 979 break; |
943 | 980 |
944 case 'o': | 981 case 'o': |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1016 break; | 1053 break; |
1017 | 1054 |
1018 case 'Q': | 1055 case 'Q': |
1019 | 1056 |
1020 if (qemu_mode) FATAL("Multiple -Q options not supported"); | 1057 if (qemu_mode) FATAL("Multiple -Q options not supported"); |
1021 if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU; | 1058 if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU; |
1022 | 1059 |
1023 qemu_mode = 1; | 1060 qemu_mode = 1; |
1024 break; | 1061 break; |
1025 | 1062 |
| 1063 case 'B': /* load bitmap */ |
| 1064 |
| 1065 /* This is a secret undocumented option! It is speculated to be useful |
| 1066 if you have a baseline "boring" input file and another "interesting" |
| 1067 file you want to minimize. |
| 1068 |
| 1069 You can dump a binary bitmap for the boring file using |
| 1070 afl-showmap -b, and then load it into afl-tmin via -B. The minimizer |
| 1071 will then minimize to preserve only the edges that are unique to |
| 1072 the interesting input file, but ignoring everything from the |
| 1073 original map. |
| 1074 |
| 1075 The option may be extended and made more official if it proves |
| 1076 to be useful. */ |
| 1077 |
| 1078 if (mask_bitmap) FATAL("Multiple -B options not supported"); |
| 1079 mask_bitmap = ck_alloc(MAP_SIZE); |
| 1080 read_bitmap(optarg); |
| 1081 break; |
| 1082 |
1026 default: | 1083 default: |
1027 | 1084 |
1028 usage(argv[0]); | 1085 usage(argv[0]); |
1029 | 1086 |
1030 } | 1087 } |
1031 | 1088 |
1032 if (optind == argc || !in_file || !out_file) usage(argv[0]); | 1089 if (optind == argc || !in_file || !out_file) usage(argv[0]); |
1033 | 1090 |
1034 setup_shm(); | 1091 setup_shm(); |
1035 setup_signal_handlers(); | 1092 setup_signal_handlers(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1075 ACTF("Writing output to '%s'...", out_file); | 1132 ACTF("Writing output to '%s'...", out_file); |
1076 | 1133 |
1077 close(write_to_file(out_file, in_data, in_len)); | 1134 close(write_to_file(out_file, in_data, in_len)); |
1078 | 1135 |
1079 OKF("We're done here. Have a nice day!\n"); | 1136 OKF("We're done here. Have a nice day!\n"); |
1080 | 1137 |
1081 exit(0); | 1138 exit(0); |
1082 | 1139 |
1083 } | 1140 } |
1084 | 1141 |
OLD | NEW |