switch (opt->type) {
case OPT_INT: {
std::string err;
- int f = strict_sistrtoll(val, &err);
+ int f = strict_si_cast<int>(val, &err);
if (!err.empty())
return -EINVAL;
*(int*)opt->conf_ptr(this) = f;
}
case OPT_LONGLONG: {
std::string err;
- long long f = strict_sistrtoll(val, &err);
+ long long f = strict_si_cast<long long>(val, &err);
if (!err.empty())
return -EINVAL;
*(long long*)opt->conf_ptr(this) = f;
return 0;
case OPT_U32: {
std::string err;
- int f = strict_sistrtoll(val, &err);
+ int f = strict_si_cast<int>(val, &err);
if (!err.empty())
return -EINVAL;
*(uint32_t*)opt->conf_ptr(this) = f;
}
case OPT_U64: {
std::string err;
- long long f = strict_sistrtoll(val, &err);
+ uint64_t f = strict_si_cast<uint64_t>(val, &err);
if (!err.empty())
return -EINVAL;
*(uint64_t*)opt->conf_ptr(this) = f;
*
*/
+#include "strtol.h"
+
#include <errno.h>
#include <limits.h>
#include <sstream>
#include <stdlib.h>
-#include <string>
-extern "C" {
-#include <stdint.h>
-}
using std::ostringstream;
uint64_t strict_sistrtoll(const char *str, std::string *err)
{
std::string s(str);
- if (s.size() == 0) {
- ostringstream oss;
- oss << "strict_sistrtoll: value not specified";
- *err = oss.str();
+ if (s.empty()) {
+ *err = "strict_sistrtoll: value not specified";
return 0;
}
const char &u = s.at(s.size()-1); //str[std::strlen(str)-1];
s = std::string(str, s.size()-1);
v = s.c_str();
- uint64_t r = strict_strtoll(v, 10, err);
+ long long r_ll = strict_strtoll(v, 10, err);
+
+ if (r_ll < 0) {
+ *err = "strict_sistrtoll: value should not be negative";
+ return 0;
+ }
+
+ uint64_t r = r_ll;
if (err->empty() && m > 0) {
- r = (r << m);
+ if (r > (std::numeric_limits<uint64_t>::max() >> m)) {
+ *err = "strict_sistrtoll: value seems to be too large";
+ return 0;
+ }
+ r <<= m;
}
return r;
}
+
+template <>
+uint64_t strict_si_cast(const char *str, std::string *err) {
+ return strict_sistrtoll(str, err);
+}
#define CEPH_COMMON_STRTOL_H
#include <string>
+#include <limits>
extern "C" {
#include <stdint.h>
}
uint64_t strict_sistrtoll(const char *str, std::string *err);
+template <typename Target>
+Target strict_si_cast(const char *str, std::string *err) {
+ uint64_t ret = strict_sistrtoll(str, err);
+ if (!err->empty())
+ return ret;
+ if (ret > (uint64_t)std::numeric_limits<Target>::max()) {
+ err->append("The option value '");
+ err->append(str);
+ err->append("' seems to be too large");
+ return 0;
+ }
+ return ret;
+}
+
+template <>
+uint64_t strict_si_cast(const char *str, std::string *err);
+
#endif
#include <string>
#include <string.h>
+#include <boost/lexical_cast.hpp>
+
+
using std::string;
TEST(DaemonConfig, SimpleSet) {
"false"));
ASSERT_EQ(ret, 0);
}
+
+TEST(DaemonConfig, InvalidIntegers) {
+ {
+ int ret = g_ceph_context->_conf->set_val("num_client", "-1");
+ ASSERT_EQ(ret, -EINVAL);
+ }
+ {
+ int ret = g_ceph_context->_conf->set_val("num_client", "-1K");
+ ASSERT_EQ(ret, -EINVAL);
+ }
+ {
+ long long bad_value = (long long)std::numeric_limits<int>::max() + 1;
+ string str = boost::lexical_cast<string>(bad_value);
+ int ret = g_ceph_context->_conf->set_val("num_client", str);
+ ASSERT_EQ(ret, -EINVAL);
+ }
+ {
+ // 4G must be greater than INT_MAX
+ ASSERT_GT(4LL * 1024 * 1024 * 1024, (long long)std::numeric_limits<int>::max());
+ int ret = g_ceph_context->_conf->set_val("num_client", "4G");
+ ASSERT_EQ(ret, -EINVAL);
+ }
+}
+
/*
* Local Variables:
* compile-command: "cd .. ; make unittest_daemon_config && ./unittest_daemon_config"
for (std::map<char,int>::iterator p = units.begin();
p != units.end(); ++p) {
- test_strict_sistrtoll_units("1024", p->first, p->second);
+ // the upper bound of uint64_t is 2^64 = 4E
+ test_strict_sistrtoll_units("4", p->first, p->second);
test_strict_sistrtoll_units("1", p->first, p->second);
test_strict_sistrtoll_units("0", p->first, p->second);
}
test_strict_sistrtoll_err("BM");
test_strict_sistrtoll_err("B0wef");
test_strict_sistrtoll_err("0m");
+ test_strict_sistrtoll_err("-1"); // it returns uint64_t
+ test_strict_sistrtoll_err("-1K");
+ // the upper bound of uint64_t is 2^64 = 4E, so 1024E overflows
+ test_strict_sistrtoll_err("1024E"); // overflows after adding the suffix
}
+
+/*
+ * Local Variables:
+ * compile-command: "cd .. ; make unittest_strtol && ./unittest_strtol"
+ * End:
+ */