diff --git a/adb/bugreport.cpp b/adb/bugreport.cpp index c348dd541..24be529a1 100644 --- a/adb/bugreport.cpp +++ b/adb/bugreport.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include "sysdeps.h" @@ -143,9 +144,11 @@ class BugreportStandardStreamsCallback : public StandardStreamsCallbackInterface // size_t idx1 = line.rfind(BUGZ_PROGRESS_PREFIX) + strlen(BUGZ_PROGRESS_PREFIX); size_t idx2 = line.rfind(BUGZ_PROGRESS_SEPARATOR); - int progress = std::stoi(line.substr(idx1, (idx2 - idx1))); - int total = std::stoi(line.substr(idx2 + 1)); - br_->UpdateProgress(line_message_, progress, total); + int progress, total; + if (android::base::ParseInt(line.substr(idx1, (idx2 - idx1)), &progress) && + android::base::ParseInt(line.substr(idx2 + 1), &total)) { + br_->UpdateProgress(line_message_, progress, total); + } } else { invalid_lines_.push_back(line); } diff --git a/base/include/android-base/parseint.h b/base/include/android-base/parseint.h index 7415409c0..2c8570ead 100644 --- a/base/include/android-base/parseint.h +++ b/base/include/android-base/parseint.h @@ -21,13 +21,15 @@ #include #include +#include namespace android { namespace base { // Parses the unsigned decimal integer in the string 's' and sets 'out' to // that value. Optionally allows the caller to define a 'max' beyond which -// otherwise valid values will be rejected. Returns boolean success. +// otherwise valid values will be rejected. Returns boolean success; 'out' +// is untouched if parsing fails. template bool ParseUint(const char* s, T* out, T max = std::numeric_limits::max()) { @@ -45,10 +47,17 @@ bool ParseUint(const char* s, T* out, return true; } +// TODO: string_view +template +bool ParseUint(const std::string& s, T* out, + T max = std::numeric_limits::max()) { + return ParseUint(s.c_str(), out, max); +} + // Parses the signed decimal integer in the string 's' and sets 'out' to // that value. Optionally allows the caller to define a 'min' and 'max // beyond which otherwise valid values will be rejected. Returns boolean -// success. +// success; 'out' is untouched if parsing fails. template bool ParseInt(const char* s, T* out, T min = std::numeric_limits::min(), @@ -67,6 +76,14 @@ bool ParseInt(const char* s, T* out, return true; } +// TODO: string_view +template +bool ParseInt(const std::string& s, T* out, + T min = std::numeric_limits::min(), + T max = std::numeric_limits::max()) { + return ParseInt(s.c_str(), out, min, max); +} + } // namespace base } // namespace android diff --git a/base/parseint_test.cpp b/base/parseint_test.cpp index 6a3ba316d..483b1d3be 100644 --- a/base/parseint_test.cpp +++ b/base/parseint_test.cpp @@ -19,7 +19,7 @@ #include TEST(parseint, signed_smoke) { - int i; + int i = 0; ASSERT_FALSE(android::base::ParseInt("x", &i)); ASSERT_FALSE(android::base::ParseInt("123x", &i)); @@ -28,7 +28,7 @@ TEST(parseint, signed_smoke) { ASSERT_TRUE(android::base::ParseInt("-123", &i)); ASSERT_EQ(-123, i); - short s; + short s = 0; ASSERT_TRUE(android::base::ParseInt("1234", &s)); ASSERT_EQ(1234, s); @@ -39,7 +39,7 @@ TEST(parseint, signed_smoke) { } TEST(parseint, unsigned_smoke) { - unsigned int i; + unsigned int i = 0u; ASSERT_FALSE(android::base::ParseUint("x", &i)); ASSERT_FALSE(android::base::ParseUint("123x", &i)); @@ -47,7 +47,7 @@ TEST(parseint, unsigned_smoke) { ASSERT_EQ(123u, i); ASSERT_FALSE(android::base::ParseUint("-123", &i)); - unsigned short s; + unsigned short s = 0u; ASSERT_TRUE(android::base::ParseUint("1234", &s)); ASSERT_EQ(1234u, s); @@ -58,21 +58,41 @@ TEST(parseint, unsigned_smoke) { } TEST(parseint, no_implicit_octal) { - int i; + int i = 0; ASSERT_TRUE(android::base::ParseInt("0123", &i)); ASSERT_EQ(123, i); - unsigned int u; + unsigned int u = 0u; ASSERT_TRUE(android::base::ParseUint("0123", &u)); ASSERT_EQ(123u, u); } TEST(parseint, explicit_hex) { - int i; + int i = 0; ASSERT_TRUE(android::base::ParseInt("0x123", &i)); ASSERT_EQ(0x123, i); - unsigned int u; + unsigned int u = 0u; ASSERT_TRUE(android::base::ParseUint("0x123", &u)); ASSERT_EQ(0x123u, u); } + +TEST(parseint, string) { + int i = 0; + ASSERT_TRUE(android::base::ParseInt(std::string("123"), &i)); + ASSERT_EQ(123, i); + + unsigned int u = 0u; + ASSERT_TRUE(android::base::ParseUint(std::string("123"), &u)); + ASSERT_EQ(123u, u); +} + +TEST(parseint, untouched_on_failure) { + int i = 123; + ASSERT_FALSE(android::base::ParseInt("456x", &i)); + ASSERT_EQ(123, i); + + unsigned int u = 123u; + ASSERT_FALSE(android::base::ParseInt("456x", &u)); + ASSERT_EQ(123u, u); +} diff --git a/base/properties.cpp b/base/properties.cpp index fab300557..37daf9a10 100644 --- a/base/properties.cpp +++ b/base/properties.cpp @@ -52,7 +52,7 @@ template T GetIntProperty(const std::string& key, T default_value, T min, T max) { T result; std::string value = GetProperty(key, ""); - if (!value.empty() && android::base::ParseInt(value.c_str(), &result, min, max)) return result; + if (!value.empty() && android::base::ParseInt(value, &result, min, max)) return result; return default_value; } @@ -60,7 +60,7 @@ template T GetUintProperty(const std::string& key, T default_value, T max) { T result; std::string value = GetProperty(key, ""); - if (!value.empty() && android::base::ParseUint(value.c_str(), &result, max)) return result; + if (!value.empty() && android::base::ParseUint(value, &result, max)) return result; return default_value; } diff --git a/bootstat/boot_event_record_store.cpp b/bootstat/boot_event_record_store.cpp index 346eadae6..78be9445a 100644 --- a/bootstat/boot_event_record_store.cpp +++ b/bootstat/boot_event_record_store.cpp @@ -59,7 +59,7 @@ bool ParseRecordEventTime(const std::string& path, int32_t* uptime) { // Ignore existing bootstat records (which do not contain file content). if (!content.empty()) { int32_t value; - if (android::base::ParseInt(content.c_str(), &value)) { + if (android::base::ParseInt(content, &value)) { bootstat::LogHistogram("bootstat_mtime_matches_content", value == *uptime); } } diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp index 0ab4c98d4..e5ddab3d0 100644 --- a/bootstat/bootstat.cpp +++ b/bootstat/bootstat.cpp @@ -60,7 +60,7 @@ void RecordBootEventFromCommandLine( BootEventRecordStore boot_event_store; if (!value_str.empty()) { int32_t value = 0; - if (android::base::ParseInt(value_str.c_str(), &value)) { + if (android::base::ParseInt(value_str, &value)) { boot_event_store.AddBootEventWithValue(event, value); } } else { @@ -193,7 +193,7 @@ std::string CalculateBootCompletePrefix() { std::string build_date_str = GetProperty("ro.build.date.utc"); int32_t build_date; - if (!android::base::ParseInt(build_date_str.c_str(), &build_date)) { + if (!android::base::ParseInt(build_date_str, &build_date)) { return std::string(); } diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index d6b631f12..4cd423af6 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -755,7 +755,7 @@ static int64_t get_target_sparse_limit(Transport* transport) { max_download_size = android::base::Trim(max_download_size); uint64_t limit; - if (!android::base::ParseUint(max_download_size.c_str(), &limit)) { + if (!android::base::ParseUint(max_download_size, &limit)) { fprintf(stderr, "couldn't parse max-download-size '%s'\n", max_download_size.c_str()); return 0; } @@ -903,7 +903,7 @@ static int get_slot_count(Transport* transport) { if (!fb_getvar(transport, "slot-count", &var)) { if (supports_AB_obsolete(transport)) return 2; // Legacy support } - if (!android::base::ParseInt(var.c_str(), &count)) return 0; + if (!android::base::ParseInt(var, &count)) return 0; return count; } @@ -1362,7 +1362,7 @@ static void fb_perform_format(Transport* transport, } int64_t size; - if (!android::base::ParseInt(partition_size.c_str(), &size)) { + if (!android::base::ParseInt(partition_size, &size)) { fprintf(stderr, "Couldn't parse partition size '%s'.\n", partition_size.c_str()); return; } diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp index f81e7d9bf..0c90a5456 100644 --- a/healthd/BatteryMonitor.cpp +++ b/healthd/BatteryMonitor.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -182,7 +183,7 @@ int BatteryMonitor::getIntField(const String8& path) { int value = 0; if (readFromFile(path, &buf) > 0) - value = std::stoi(buf.c_str(), NULL, 0); + android::base::ParseInt(buf, &value); return value; } diff --git a/init/builtins.cpp b/init/builtins.cpp index f4ba01822..da4b84ea2 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -304,7 +304,7 @@ static int do_mkdir(const std::vector& args) { /* mkdir [mode] [owner] [group] */ if (args.size() >= 3) { - mode = std::stoul(args[2], 0, 8); + mode = std::strtoul(args[2].c_str(), 0, 8); } ret = make_dir(args[1].c_str(), mode); @@ -637,10 +637,13 @@ static int do_setprop(const std::vector& args) { static int do_setrlimit(const std::vector& args) { struct rlimit limit; int resource; - resource = std::stoi(args[1]); - limit.rlim_cur = std::stoi(args[2]); - limit.rlim_max = std::stoi(args[3]); - return setrlimit(resource, &limit); + if (android::base::ParseInt(args[1], &resource) && + android::base::ParseUint(args[2], &limit.rlim_cur) && + android::base::ParseUint(args[3], &limit.rlim_max)) { + return setrlimit(resource, &limit); + } + LOG(WARNING) << "ignoring setrlimit " << args[1] << " " << args[2] << " " << args[3]; + return -1; } static int do_start(const std::vector& args) { @@ -709,7 +712,7 @@ static int do_powerctl(const std::vector& args) { std::string timeout = property_get("ro.build.shutdown_timeout"); unsigned int delay = 0; - if (android::base::ParseUint(timeout.c_str(), &delay) && delay > 0) { + if (android::base::ParseUint(timeout, &delay) && delay > 0) { Timer t; // Ask all services to terminate. ServiceManager::GetInstance().ForEachService( @@ -764,13 +767,11 @@ static int do_rmdir(const std::vector& args) { } static int do_sysclktz(const std::vector& args) { - struct timezone tz; - - memset(&tz, 0, sizeof(tz)); - tz.tz_minuteswest = std::stoi(args[1]); - if (settimeofday(NULL, &tz)) - return -1; - return 0; + struct timezone tz = {}; + if (android::base::ParseInt(args[1], &tz.tz_minuteswest) && settimeofday(NULL, &tz) != -1) { + return 0; + } + return -1; } static int do_verity_load_state(const std::vector& args) { @@ -914,7 +915,8 @@ static int do_restorecon_recursive(const std::vector& args) { static int do_loglevel(const std::vector& args) { // TODO: support names instead/as well? - int log_level = std::stoi(args[1]); + int log_level = -1; + android::base::ParseInt(args[1], &log_level); android::base::LogSeverity severity; switch (log_level) { case 7: severity = android::base::DEBUG; break; @@ -947,9 +949,12 @@ static int do_wait(const std::vector& args) { if (args.size() == 2) { return wait_for_file(args[1].c_str(), COMMAND_RETRY_TIMEOUT); } else if (args.size() == 3) { - return wait_for_file(args[1].c_str(), std::stoi(args[2])); - } else - return -1; + int timeout; + if (android::base::ParseInt(args[2], &timeout)) { + return wait_for_file(args[1].c_str(), timeout); + } + } + return -1; } /* diff --git a/init/service.cpp b/init/service.cpp index 503d84f42..22fb01342 100644 --- a/init/service.cpp +++ b/init/service.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -46,6 +47,7 @@ #include "property_service.h" #include "util.h" +using android::base::ParseInt; using android::base::StringPrintf; using android::base::WriteStringToFile; @@ -351,22 +353,19 @@ bool Service::ParseGroup(const std::vector& args, std::string* err) } bool Service::ParsePriority(const std::vector& args, std::string* err) { - priority_ = std::stoi(args[1]); - - if (priority_ < ANDROID_PRIORITY_HIGHEST || priority_ > ANDROID_PRIORITY_LOWEST) { - priority_ = 0; + priority_ = 0; + if (!ParseInt(args[1], &priority_, + static_cast(ANDROID_PRIORITY_LOWEST), + static_cast(ANDROID_PRIORITY_HIGHEST))) { *err = StringPrintf("process priority value must be range %d - %d", ANDROID_PRIORITY_HIGHEST, ANDROID_PRIORITY_LOWEST); return false; } - return true; } bool Service::ParseIoprio(const std::vector& args, std::string* err) { - ioprio_pri_ = std::stoul(args[2], 0, 8); - - if (ioprio_pri_ < 0 || ioprio_pri_ > 7) { + if (!ParseInt(args[2], &ioprio_pri_, 0, 7)) { *err = "priority value must be range 0 - 7"; return false; } @@ -387,7 +386,12 @@ bool Service::ParseIoprio(const std::vector& args, std::string* err bool Service::ParseKeycodes(const std::vector& args, std::string* err) { for (std::size_t i = 1; i < args.size(); i++) { - keycodes_.emplace_back(std::stoi(args[i])); + int code; + if (ParseInt(args[i], &code)) { + keycodes_.emplace_back(code); + } else { + LOG(WARNING) << "ignoring invalid keycode: " << args[i]; + } } return true; } @@ -420,17 +424,13 @@ bool Service::ParseNamespace(const std::vector& args, std::string* } bool Service::ParseOomScoreAdjust(const std::vector& args, std::string* err) { - oom_score_adjust_ = std::stol(args[1], 0, 10); - - if (oom_score_adjust_ < -1000 || oom_score_adjust_ > 1000) { + if (!ParseInt(args[1], &oom_score_adjust_, -1000, 1000)) { *err = "oom_score_adjust value must be in range -1000 - +1000"; return false; } - return true; } - bool Service::ParseSeclabel(const std::vector& args, std::string* err) { seclabel_ = args[1]; return true; @@ -448,7 +448,7 @@ bool Service::ParseSocket(const std::vector& args, std::string* err return false; } - int perm = std::stoul(args[3], 0, 8); + int perm = std::strtoul(args[3].c_str(), 0, 8); uid_t uid = args.size() > 4 ? decode_uid(args[4].c_str()) : 0; gid_t gid = args.size() > 5 ? decode_uid(args[5].c_str()) : 0; std::string socketcon = args.size() > 6 ? args[6] : "";