From 275453672767dad79057b1a30677ea8ba439c182 Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Wed, 25 Feb 2026 23:46:53 -0600 Subject: [PATCH] Fix integer overflow in size suffix parsing Use __builtin_mul_overflow to detect overflow when applying size suffixes (K, M, G, T) in str::from for int64_t and uint64_t. Previously, large values with suffixes could silently wrap around. --- src/from_string.cpp | 52 +++++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/src/from_string.cpp b/src/from_string.cpp index d8287e1f..bdb1e606 100644 --- a/src/from_string.cpp +++ b/src/from_string.cpp @@ -69,10 +69,14 @@ str::from(const std::string_view val_, int str::from(const std::string_view val_, - int64_t *rv_) + int64_t *rv_) { int64_t tmp; const int base = 10; + constexpr int64_t K = 1024LL; + constexpr int64_t M = K * 1024LL; + constexpr int64_t G = M * 1024LL; + constexpr int64_t T = G * 1024LL; auto [ptr,ec] = std::from_chars(val_.begin(), val_.end(), @@ -81,50 +85,60 @@ str::from(const std::string_view val_, if(ec != std::errc{}) return -EINVAL; - *rv_ = tmp; if(ptr == val_.end()) - return 0; + { + *rv_ = tmp; + return 0; + } switch(*ptr) { case 'b': case 'B': - *rv_ *= 1ULL; break; case 'k': case 'K': - *rv_ *= 1024ULL; + if(__builtin_mul_overflow(tmp,K,&tmp)) + return -EOVERFLOW; break; case 'm': case 'M': - *rv_ *= (1024ULL * 1024ULL); + if(__builtin_mul_overflow(tmp,M,&tmp)) + return -EOVERFLOW; break; case 'g': case 'G': - *rv_ *= (1024ULL * 1024ULL * 1024ULL); + if(__builtin_mul_overflow(tmp,G,&tmp)) + return -EOVERFLOW; break; case 't': case 'T': - *rv_ *= (1024ULL * 1024ULL * 1024ULL * 1024ULL); + if(__builtin_mul_overflow(tmp,T,&tmp)) + return -EOVERFLOW; break; default: return -EINVAL; } + *rv_ = tmp; return 0; } int str::from(const std::string_view val_, - uint64_t *rv_) + uint64_t *rv_) { uint64_t tmp; const int base = 10; + constexpr uint64_t K = 1024ULL; + constexpr uint64_t M = K * 1024ULL; + constexpr uint64_t G = M * 1024ULL; + constexpr uint64_t T = G * 1024ULL; auto [ptr,ec] = std::from_chars(val_.begin(), val_.end(), @@ -133,41 +147,47 @@ str::from(const std::string_view val_, if(ec != std::errc{}) return -EINVAL; - *rv_ = tmp; if(ptr == val_.end()) - return 0; + { + *rv_ = tmp; + return 0; + } switch(*ptr) { case 'b': case 'B': - *rv_ *= 1ULL; break; case 'k': case 'K': - *rv_ *= 1024ULL; + if(__builtin_mul_overflow(tmp,K,&tmp)) + return -EOVERFLOW; break; case 'm': case 'M': - *rv_ *= (1024ULL * 1024ULL); + if(__builtin_mul_overflow(tmp,M,&tmp)) + return -EOVERFLOW; break; case 'g': case 'G': - *rv_ *= (1024ULL * 1024ULL * 1024ULL); + if(__builtin_mul_overflow(tmp,G,&tmp)) + return -EOVERFLOW; break; case 't': case 'T': - *rv_ *= (1024ULL * 1024ULL * 1024ULL * 1024ULL); + if(__builtin_mul_overflow(tmp,T,&tmp)) + return -EOVERFLOW; break; default: return -EINVAL; } + *rv_ = tmp; return 0; }