* promote the compared types properly to address the signed/unsigned
comparison warnings. this also fixes the potential problems of
slicing a compared type down to a "smaller" type before the
comparison.
* check for the width of resulting type and shift bits caused by SI
prefix to avoid the -Wshift-count-overflow warnings. this again
is a potential issue, as shifting n bits of an integer of m bits
width, where n >= m, leads to undefined behaviour.
* add a test for the 2nd fixed issue.
Signed-off-by: Kefu Chai <kchai@redhat.com>
*err = "strict_sistrtoll: value should not be negative";
return 0;
}
- if (ll < (long long)std::numeric_limits<T>::min() >> m) {
+ if (static_cast<unsigned>(m) >= sizeof(T) * CHAR_BIT) {
+ *err = ("strict_sistrtoll: the SI prefix is too large for the designated "
+ "type");
+ return 0;
+ }
+ using promoted_t = typename std::common_type<decltype(ll), T>::type;
+ if (static_cast<promoted_t>(ll) <
+ static_cast<promoted_t>(std::numeric_limits<T>::min()) >> m) {
*err = "strict_sistrtoll: value seems to be too small";
return 0;
}
- if (ll > std::numeric_limits<T>::max() >> m) {
+ if (static_cast<promoted_t>(ll) >
+ static_cast<promoted_t>(std::numeric_limits<T>::max()) >> m) {
*err = "strict_sistrtoll: value seems to be too large";
return 0;
-
}
return (ll << m);
}
test_strict_sistrtoll_err("1024E"); // overflows after adding the suffix
}
+// since strict_sistrtoll is an alias of strict_si_cast<uint64_t>(), quite a few
+// of cases are covered by existing test cases of strict_sistrtoll already.
+TEST(StrictSICast, Error) {
+ {
+ std::string err;
+ // the SI prefix is way too large for `int`.
+ (void)strict_si_cast<int>("2E", &err);
+ ASSERT_NE(err, "");
+ }
+ {
+ std::string err;
+ (void)strict_si_cast<int>("-2E", &err);
+ ASSERT_NE(err, "");
+ }
+ {
+ std::string err;
+ (void)strict_si_cast<int>("1T", &err);
+ ASSERT_NE(err, "");
+ }
+}
+
/*
* Local Variables:
* compile-command: "cd .. ; make unittest_strtol && ./unittest_strtol"