@@ -89,6 +89,7 @@ u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */
89
89
s32 dev_null_fd = -1 ; /* FD to /dev/null */
90
90
91
91
u8 crash_mode , /* Crash-centric mode? */
92
+ hang_mode , /* Minimize as long as it hangs */
92
93
exit_crash , /* Treat non-zero exit as crash? */
93
94
edges_only , /* Ignore hit counts? */
94
95
exact_mode , /* Require path match for crashes? */
@@ -98,6 +99,7 @@ static volatile u8 stop_soon; /* Ctrl-C pressed? */
98
99
99
100
static u8 qemu_mode ;
100
101
102
+
101
103
/*
102
104
* forkserver section
103
105
*/
@@ -427,6 +429,8 @@ static u8 run_target(char** argv, u8* mem, u32 len, u8 first_run) {
427
429
428
430
u32 cksum ;
429
431
432
+ child_timed_out = 0 ;
433
+
430
434
memset (trace_bits , 0 , MAP_SIZE );
431
435
MEM_BARRIER ();
432
436
@@ -484,8 +488,13 @@ static u8 run_target(char** argv, u8* mem, u32 len, u8 first_run) {
484
488
if (* (u32 * )trace_bits == EXEC_FAIL_SIG )
485
489
FATAL ("Unable to execute '%s'" , argv [0 ]);
486
490
487
- classify_counts (trace_bits );
488
- apply_mask ((u32 * )trace_bits , (u32 * )mask_bitmap );
491
+ if (!hang_mode ) {
492
+
493
+ classify_counts (trace_bits );
494
+ apply_mask ((u32 * )trace_bits , (u32 * )mask_bitmap );
495
+
496
+ }
497
+
489
498
total_execs ++ ;
490
499
491
500
if (stop_soon ) {
@@ -496,15 +505,35 @@ static u8 run_target(char** argv, u8* mem, u32 len, u8 first_run) {
496
505
497
506
}
498
507
499
- /* Always discard inputs that time out. */
508
+ /* Always discard inputs that time out, unless we are in hang mode */
509
+
510
+ if (hang_mode ) {
511
+
512
+ if (child_timed_out ) return 1 ;
513
+
514
+ if (WIFSIGNALED (status ) ||
515
+ (WIFEXITED (status ) && WEXITSTATUS (status ) == MSAN_ERROR ) ||
516
+ (WIFEXITED (status ) && WEXITSTATUS (status ) && exit_crash )) {
517
+
518
+ missed_crashes ++ ;
519
+
520
+ } else {
521
+
522
+ missed_hangs ++ ;
523
+
524
+ }
525
+
526
+ return 0 ;
527
+
528
+ }
500
529
501
530
if (child_timed_out ) {
502
531
503
532
missed_hangs ++ ;
504
533
return 0 ;
505
534
506
535
}
507
-
536
+
508
537
/* Handle crashing inputs depending on current mode. */
509
538
510
539
if (WIFSIGNALED (status ) ||
@@ -791,6 +820,19 @@ static void minimize(char** argv) {
791
820
792
821
finalize_all :
793
822
823
+ if (hang_mode ) {
824
+
825
+ SAYF ("\n" cGRA " File size reduced by : " cRST
826
+ "%0.02f%% (to %u byte%s)\n" cGRA " Characters simplified : " cRST
827
+ "%0.02f%%\n" cGRA " Number of execs done : " cRST "%u\n" cGRA
828
+ " Fruitless execs : " cRST "termination=%u crash=%u\n\n" ,
829
+ 100 - ((double )in_len ) * 100 / orig_len , in_len , in_len == 1 ? "" : "s" ,
830
+ ((double )(alpha_d_total )) * 100 / (in_len ? in_len : 1 ), total_execs ,
831
+ missed_paths , missed_crashes );
832
+ return ;
833
+
834
+ }
835
+
794
836
SAYF ("\n" cGRA " File size reduced by : " cRST
795
837
"%0.02f%% (to %u byte%s)\n" cGRA " Characters simplified : " cRST
796
838
"%0.02f%%\n" cGRA " Number of execs done : " cRST "%u\n" cGRA
@@ -799,7 +841,7 @@ static void minimize(char** argv) {
799
841
((double )(alpha_d_total )) * 100 / (in_len ? in_len : 1 ), total_execs ,
800
842
missed_paths , missed_crashes , missed_hangs ? cLRD : "" , missed_hangs );
801
843
802
- if (total_execs > 50 && missed_hangs * 10 > total_execs )
844
+ if (total_execs > 50 && missed_hangs * 10 > total_execs && ! hang_mode )
803
845
WARNF (cLRD "Frequent timeouts - results may be skewed." cRST );
804
846
805
847
}
@@ -978,6 +1020,7 @@ static void usage(u8* argv0) {
978
1020
979
1021
" -e - solve for edge coverage only, ignore hit counts\n"
980
1022
" -x - treat non-zero exit codes as crashes\n\n"
1023
+ " -H - minimize a hang (hang mode)\n"
981
1024
982
1025
"For additional tips, please consult %s/README.md.\n\n"
983
1026
@@ -1077,7 +1120,7 @@ int main(int argc, char** argv, char** envp) {
1077
1120
1078
1121
SAYF (cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n" );
1079
1122
1080
- while ((opt = getopt (argc , argv , "+i:o:f:m:t:B:xeQUWh " )) > 0 )
1123
+ while ((opt = getopt (argc , argv , "+i:o:f:m:t:B:xeQUWHh " )) > 0 )
1081
1124
1082
1125
switch (opt ) {
1083
1126
@@ -1103,6 +1146,7 @@ int main(int argc, char** argv, char** envp) {
1103
1146
case 'e' :
1104
1147
1105
1148
if (edges_only ) FATAL ("Multiple -e options not supported" );
1149
+ if (hang_mode ) FATAL ("Edges only and hang mode are mutually exclusive." );
1106
1150
edges_only = 1 ;
1107
1151
break ;
1108
1152
@@ -1188,6 +1232,15 @@ int main(int argc, char** argv, char** envp) {
1188
1232
1189
1233
break ;
1190
1234
1235
+ case 'H' : /* Hang Mode */
1236
+
1237
+ /* Minimizes a testcase to the minimum that still times out */
1238
+
1239
+ if (hang_mode ) FATAL ("Multipe -H options not supported" );
1240
+ if (edges_only ) FATAL ("Edges only and hang mode are mutually exclusive." );
1241
+ hang_mode = 1 ;
1242
+ break ;
1243
+
1191
1244
case 'B' : /* load bitmap */
1192
1245
1193
1246
/* This is a secret undocumented option! It is speculated to be useful
@@ -1242,6 +1295,13 @@ int main(int argc, char** argv, char** envp) {
1242
1295
1243
1296
exact_mode = !!get_afl_env ("AFL_TMIN_EXACT" );
1244
1297
1298
+ if (hang_mode && exact_mode ) {
1299
+
1300
+ SAYF ("AFL_TMIN_EXACT won't work for loops in hang mode, ignoring." );
1301
+ exact_mode = 0 ;
1302
+
1303
+ }
1304
+
1245
1305
SAYF ("\n" );
1246
1306
1247
1307
read_initial_file ();
@@ -1253,10 +1313,18 @@ int main(int argc, char** argv, char** envp) {
1253
1313
1254
1314
run_target (use_argv , in_data , in_len , 1 );
1255
1315
1256
- if (child_timed_out )
1257
- FATAL ("Target binary times out (adjusting -t may help)." );
1316
+ if (hang_mode && !child_timed_out )
1317
+ FATAL ("Target binary did not time out but hang minimization mode "
1318
+ "(-H) was set (-t %u)." , exec_tmout );
1319
+
1320
+ if (child_timed_out && !hang_mode )
1321
+ FATAL ("Target binary times out (adjusting -t may help). Use -H to minimize a hang." );
1322
+
1323
+ if (hang_mode ) {
1324
+
1325
+ OKF ("Program hangs as expected, minimizing in " cCYA "hang" cRST " mode." );
1258
1326
1259
- if (!crash_mode ) {
1327
+ } else if (!crash_mode ) {
1260
1328
1261
1329
OKF ("Program terminates normally, minimizing in " cCYA "instrumented" cRST
1262
1330
" mode." );
0 commit comments