diff options
author | Dominik Maier <domenukk@gmail.com> | 2020-05-30 11:02:34 +0200 |
---|---|---|
committer | Dominik Maier <domenukk@gmail.com> | 2020-05-30 11:02:34 +0200 |
commit | 38e5c32a55086d36c8b9ee38e4b20c15517fc4b2 (patch) | |
tree | 30f7eebc1a1725b31904c3cec9fd7c5d459ff27f /src/afl-common.c | |
parent | 0c50945303e12cbe46cfb98578bbe129305018c4 (diff) | |
download | afl++-38e5c32a55086d36c8b9ee38e4b20c15517fc4b2.tar.gz |
corrected read_timed for values > 4
Diffstat (limited to 'src/afl-common.c')
-rw-r--r-- | src/afl-common.c | 82 |
1 files changed, 57 insertions, 25 deletions
diff --git a/src/afl-common.c b/src/afl-common.c index d428c9c5..793041b2 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -39,6 +39,7 @@ #include <limits.h> #include <sys/types.h> #include <sys/stat.h> +#include <sys/ioctl.h> #include <unistd.h> #include <fcntl.h> @@ -869,51 +870,82 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) { } -/* Wrapper for select() and read(), reading len bytes. - Assumes that all bytes are available on read! +/* sets a FD to non-blocking mode (used for read_timed) */ +void set_nonblocking(int fd) { + + int ret = 0; + int opt = 1; + ret = ioctl(fd, FIONBIO, &opt); + if (ret == -1) { PFATAL("Could not enable non-blocking mode on fd %d", fd); } + +} + + +/* Wrapper for select() and read(), reading exactly len bytes. + Should be called on non-blocking fds. Returns the time passed to read. If the wait times out, returns timeout_ms + 1; - Returns 0 if an error occurred (fd closed, signal, ...); */ + Returns 0 if an error occurred (fd closed, signal, ...); + */ u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms, volatile u8 *stop_soon_p) { + struct timeval timeout; fd_set readfds; FD_ZERO(&readfds); FD_SET(fd, &readfds); - struct timeval timeout; - timeout.tv_sec = (timeout_ms / 1000); - timeout.tv_usec = (timeout_ms % 1000) * 1000; -#if !defined(__linux__) - u64 read_start = get_cur_time_us(); -#endif + size_t read_total = 0; + ssize_t len_read = 0; - /* set exceptfds as well to return when a child exited/closed the pipe. */ - int sret = select(fd + 1, &readfds, NULL, NULL, &timeout); + #if defined(__linux__) + timeout.tv_sec = (timeout_ms / 1000); + timeout.tv_usec = (timeout_ms % 1000) * 1000; + #else + u64 time_start = get_cur_time_us(); + #endif - if (!sret) { + while (read_total < len) { - return timeout_ms + 1; + #if !defined(__linux__) + u64 time_current = get_cur_time_us(); + u64 timeout_current = timeout_ms - (time_current - time_start); + timeout.tv_sec = (timeout_current / 1000); + timeout.tv_usec = (timeout_current % 1000) * 1000; + #endif - } else if (sret < 0) { + /* set exceptfds as well to return when a child exited/closed the pipe. */ + int sret = select(fd + 1, &readfds, NULL, NULL, &timeout); - return 0; + if (!sret) { - } + // printf("Timeout in sret."); + return timeout_ms + 1; + + } else if (sret < 0) { + + /* Retry select for all signals other than than ctrl+c */ + if (errno == EINTR && !*stop_soon_p) { continue; } + return 0; + + } + + len_read = read(fd, ((u8 *)buf) + read_total, len - read_total); + if (len_read <= 0) { return 0; } + read_total += len_read; - ssize_t len_read = read(fd, ((u8 *)buf), len); - if (len_read < len) { return 0; } + } -#if defined(__linux__) - u32 exec_ms = + #if defined(__linux__) + s32 exec_ms = MIN(timeout_ms, ((u64)timeout_ms - (timeout.tv_sec * 1000 + timeout.tv_usec / 1000))); -#else - u32 exec_ms = get_cur_time_us() - read_start; -#endif + #else + u32 exec_ms = get_cur_time_us() - time_start; + #endif - // ensure to report 1 ms has passed (0 is an error) - return exec_ms > 0 ? exec_ms : 1; + return exec_ms > 0 ? exec_ms + : 1; // at least 1 milli must have passed (0 is an error) } |