mirror of
https://github.com/trapexit/mergerfs.git
synced 2026-10-26 19:01:56 -04:00
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.
This commit is contained in:
parent
a0cff637e1
commit
2754536727
1 changed files with 36 additions and 16 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue