How does __afl_persistent_loop actually work?
vivin opened this issue · 1 comments
vivin commented
I see that the macro is defined in afl-clang-fast.c
and I can see that it is basically an alias for __afl_persistent_loop
in afl-llvm-rt.o.c
. But I don't understand how the function would ever return 0
:
int __afl_persistent_loop(unsigned int max_cnt) {
static u8 first_pass = 1;
static u32 cycle_cnt;
if (first_pass) {
/* Make sure that every iteration of __AFL_LOOP() starts with a clean slate.
On subsequent calls, the parent will take care of that, but on the first
iteration, it's our job to erase any trace of whatever happened
before the loop. */
if (is_persistent) {
memset(__afl_area_ptr, 0, MAP_SIZE);
__afl_area_ptr[0] = 1;
__afl_prev_loc = 0;
}
cycle_cnt = max_cnt;
first_pass = 0;
return 1;
}
if (is_persistent) {
if (--cycle_cnt) {
raise(SIGSTOP);
__afl_area_ptr[0] = 1;
__afl_prev_loc = 0;
return 1;
} else {
/* When exiting __AFL_LOOP(), make sure that the subsequent code that
follows the loop is not traced. We do that by pivoting back to the
dummy output region. */
__afl_area_ptr = __afl_area_initial;
}
}
return 0;
}
I can see that in the second if
it will stop the process if it is able to decrement the cycle count, and so I get that this is where it basically signals that an iteration has ended. What I don't understand is how it would ever get to this part, because first_pass
is always set to 1
at the beginning of the function.
vivin commented
Well, I'm dumb 😆 I didn't notice that the variables are static
and because I don't regularly write C, I forgot that they persist outside the lifetime of the function. The code makes sense now.