From c4fb0f7603ed5fa8382eef5609f50426eba475b8 Mon Sep 17 00:00:00 2001 From: Azat Khuzhin Date: Tue, 20 Feb 2024 08:58:04 +0100 Subject: [PATCH] Fix divide-by-zero in ev_token_bucket_get_tick_ Found by oss-fuzz, after coverage had been improved in https://github.com/google/oss-fuzz/pull/11257 --- bufferevent_ratelim.c | 11 +++++++++-- test/regress_bufferevent.c | 13 +++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/bufferevent_ratelim.c b/bufferevent_ratelim.c index 1fed9d15..d4624615 100644 --- a/bufferevent_ratelim.c +++ b/bufferevent_ratelim.c @@ -146,11 +146,19 @@ ev_token_bucket_cfg_new(size_t read_rate, size_t read_burst, { struct ev_token_bucket_cfg *r; struct timeval g; + unsigned msec_per_tick; + if (! tick_len) { g.tv_sec = 1; g.tv_usec = 0; tick_len = &g; } + + msec_per_tick = (tick_len->tv_sec * 1000) + + (tick_len->tv_usec & COMMON_TIMEOUT_MICROSECONDS_MASK)/1000; + if (!msec_per_tick) + return NULL; + if (read_rate > read_burst || write_rate > write_burst || read_rate < 1 || write_rate < 1) return NULL; @@ -167,8 +175,7 @@ ev_token_bucket_cfg_new(size_t read_rate, size_t read_burst, r->read_maximum = read_burst; r->write_maximum = write_burst; memcpy(&r->tick_timeout, tick_len, sizeof(struct timeval)); - r->msec_per_tick = (tick_len->tv_sec * 1000) + - (tick_len->tv_usec & COMMON_TIMEOUT_MICROSECONDS_MASK)/1000; + r->msec_per_tick = msec_per_tick; return r; } diff --git a/test/regress_bufferevent.c b/test/regress_bufferevent.c index 493ab6bd..f069f4b8 100644 --- a/test/regress_bufferevent.c +++ b/test/regress_bufferevent.c @@ -203,6 +203,17 @@ static void test_bufferevent_pair_flush_normal(void) { test_bufferevent_impl(1, static void test_bufferevent_pair_flush_flush(void) { test_bufferevent_impl(1, BEV_FLUSH); } static void test_bufferevent_pair_flush_finished(void) { test_bufferevent_impl(1, BEV_FINISHED); } +static void test_bufferevent_ratelimit_fuzz(void) +{ + struct timeval cfg_tick = {0, 0}; + struct ev_token_bucket_cfg *cfg = ev_token_bucket_cfg_new(1, 1, 1, 1, &cfg_tick); + tt_ptr_op(cfg, ==, NULL); + test_ok = 1; + +end: + ; +} + #if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED) /** * Trace lock/unlock/alloc/free for locks. @@ -1463,6 +1474,8 @@ struct testcase_t bufferevent_testcases[] = { test_bufferevent_read_failed, TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE, &basic_setup, NULL }, + LEGACY(bufferevent_ratelimit_fuzz, TT_ISOLATED), + END_OF_TESTCASES, };