From a80cb926d2135a0dd2cb4d85cb11696f5a36cbfd Mon Sep 17 00:00:00 2001 From: TapTap Date: Mon, 20 Jul 2026 21:25:31 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20correctness=20=E2=80=94=20bw=20throttle?= =?UTF-8?q?=20underflow,=20glob=20**,=20protocol=20version,=20valgrind?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/shared/protocol.c | 13 ++++++++++--- src/shared/utils.c | 11 +++++++---- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/shared/protocol.c b/src/shared/protocol.c index 8cb65c9..7f197ee 100644 --- a/src/shared/protocol.c +++ b/src/shared/protocol.c @@ -36,10 +36,17 @@ static void bw_throttle(size_t bytes_written) { clock_gettime(CLOCK_MONOTONIC, &now); /* Use unsigned long long for elapsed_ns to avoid overflow in multiplication. - * time_t differences fit comfortably in 64-bit for any practical runtime. */ + * time_t differences fit comfortably in 64-bit for any practical runtime. + * Handle nanosecond carry/borrow to avoid unsigned wraparound when + * now.tv_nsec < bw_last_refill.tv_nsec. */ + long long sec_diff = (long long)(now.tv_sec - bw_last_refill.tv_sec); + long long nsec_diff = (long long)(now.tv_nsec - bw_last_refill.tv_nsec); + if (nsec_diff < 0) { + sec_diff--; + nsec_diff += 1000000000LL; + } unsigned long long elapsed_ns = - (unsigned long long)(now.tv_sec - bw_last_refill.tv_sec) * 1000000000ULL + - (unsigned long long)(now.tv_nsec - bw_last_refill.tv_nsec); + (unsigned long long)sec_diff * 1000000000ULL + (unsigned long long)nsec_diff; bw_last_refill = now; long long tokens_to_add = (long long)((double)io_bwlimit * (double)elapsed_ns / 1000000000.0); diff --git a/src/shared/utils.c b/src/shared/utils.c index 05c8b60..77b8a9f 100644 --- a/src/shared/utils.c +++ b/src/shared/utils.c @@ -92,13 +92,16 @@ bool glob_match(const char* pattern, const char* str) { str++; } else { if (*pattern != *str) { - /* If pattern has a '/' followed by '**', allow zero path components */ + /* If pattern has a '/' followed by '**', allow zero path components. + * Only skip slash-double-star if the remainder is empty or starts with '/'; + * otherwise fall through to normal character matching. */ if (*pattern == '/' && *(pattern + 1) == '*' && *(pattern + 2) == '*') { - /* Skip over slash-double-star and try to match rest against current str */ const char* rest = pattern + 3; + if (*rest == '\0') + return glob_match(rest, str); if (*rest == '/') - rest++; - return glob_match(rest, str); + return glob_match(rest + 1, str); + /* slash-double-star X where X does not start with '/' — fall through */ } return false; }