From 2f7158397a81b6abd06892325b5b59ee67284420 Mon Sep 17 00:00:00 2001 From: Rob Davies Date: Thu, 2 Jul 2026 15:25:01 +0100 Subject: [PATCH] Speed up hts_parse_decimal() handling of oversized exponents The loop to apply exponent values could be made to run for a very long time (although not forever) if the exponent value in the number passed to the function was very large. As in both the +ve and -ve exponent cases this will eventually result in `n` becoming zero, it's possible to short-cut the rest of the loop as the final value will no longer change. (While the -ve case is obvious, the +ve one is a bit more complicated due to wrap-around. However, as each multiplication by 10 adds a factor of 2 (as 10 = 5 + 2), after at most 64 enough 2's will have accumulated in the product to make it divide exactly into 2^64 and the result will be zero.) Note that this does not try to add overflow detection, which would require more extensive changes and is left to future work. Signed-off-by: Rob Davies --- NEWS | 3 +++ hts.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index fbbc21aab..76019fe50 100644 --- a/NEWS +++ b/NEWS @@ -94,6 +94,9 @@ Bug fixes BGZF::errcode field after calling bgzf_close() as it may no longer be valid. (PR #2035, #2042) +* Speed up hts_parse_decimal() handling of oversized exponents + (PR #2045) + Documentation updates --------------------- diff --git a/hts.c b/hts.c index 571969cec..e8d9d91e6 100644 --- a/hts.c +++ b/hts.c @@ -3923,8 +3923,8 @@ long long hts_parse_decimal(const char *str, char **strend, int flags) } e -= decimals; - while (e > 0) n *= 10, e--; - while (e < 0) lost += n % 10, n /= 10, e++; + while (e > 0 && n) n *= 10, e--; + while (e < 0 && n) lost += n % 10, n /= 10, e++; if (lost > 0) { hts_log_warning("Discarding fractional part of %.*s", (int)(s - str), str);