diff --git a/include/command_reporter.h b/include/command_reporter.h index d548eef490abbd454668fa3097f0179afca85a66..89420231a50cd59dd4eb90ffe92db2396e5ca93c 100644 --- a/include/command_reporter.h +++ b/include/command_reporter.h @@ -51,7 +51,8 @@ namespace OHOS::Developtools::HiPerf { GEN_ITEM(SUBCOMMAND_OPTIONS_ERROR), /* 29 */ \ GEN_ITEM(CHECK_OUT_PUT_ERROR), /* 30 */ \ GEN_ITEM(WRONG_CONTROL_CMD), /* 31 */ \ - GEN_ITEM(CHECK_DEBUG_APP_FAIL) /* 32 */ + GEN_ITEM(CHECK_DEBUG_APP_FAIL), /* 32 */ \ + GEN_ITEM(SET_HM_FAIL) /* 33 */ #define FOR_ERROR_ENUM(x) x diff --git a/include/hiperf_hilog.h b/include/hiperf_hilog.h index 6ef4f60eaadbf0ba0783c2c8b25fa7682f22c12a..4d0d9d68524beb01f5a38562d7bb1e02df047833 100644 --- a/include/hiperf_hilog.h +++ b/include/hiperf_hilog.h @@ -126,14 +126,14 @@ static inline std::string StringFormat(const char* fmt, ...) do { \ if (!(expr)) { \ if (log == 1) { \ - std::string str = StringFormat(fmt, ##__VA_ARGS__); \ - HLOGE("%s", str.c_str()); \ + std::string logStr = StringFormat(fmt, ##__VA_ARGS__); \ + HLOGE("%s", logStr.c_str()); \ } else if (log == LOG_TYPE_PRINTF) { \ printf("%s", StringFormat(fmt, ##__VA_ARGS__).c_str()); \ } else if (log == LOG_TYPE_WITH_HILOG) { \ - std::string str = StringFormat(fmt, ##__VA_ARGS__); \ - HLOGE("%s", str.c_str()); \ - HIPERF_HILOGE(MODULE_DEFAULT, "%{public}s", str.c_str()); \ + std::string logStr = StringFormat(fmt, ##__VA_ARGS__); \ + HLOGE("%s", logStr.c_str()); \ + HIPERF_HILOGE(MODULE_DEFAULT, "%{public}s", logStr.c_str()); \ } \ return retval; \ } \ diff --git a/include/subcommand_dump.h b/include/subcommand_dump.h index b5e0d03b6b89d5ab0ab8f52266a0a0bd984afc01..8f5b9627b5c6493b28b766eed87dde1155c816b0 100644 --- a/include/subcommand_dump.h +++ b/include/subcommand_dump.h @@ -122,7 +122,7 @@ private: bool CheckOutputFile(); VirtualRuntime vr_; - void SetHM(); + bool SetHM(); }; } // namespace HiPerf } // namespace Developtools diff --git a/include/subcommand_report.h b/include/subcommand_report.h index 5edfcdee84221d34300450a6d5a2a2bc217fa71b..214f7791363fda15e297dbb2f7f415e274220fc9 100644 --- a/include/subcommand_report.h +++ b/include/subcommand_report.h @@ -180,7 +180,7 @@ private: std::unique_ptr protobufOutputFileWriter_ = nullptr; void UpdateReportInfo(); #endif - void SetHM(); + bool SetHM(); }; } // namespace HiPerf } // namespace Developtools diff --git a/include/utilities.h b/include/utilities.h index 3191e2885778b830b26e61288d26cf89eb874647..a08f301a466d05d624e1da1c939aebcac3706564 100644 --- a/include/utilities.h +++ b/include/utilities.h @@ -342,6 +342,10 @@ bool IsNumeric(const std::string& str); bool IscontainDigits(const std::string& str); bool IsStringToIntSuccess(const std::string &str, int &num); bool StringToUint64(const std::string &str, uint64_t &val); +bool StringToUnsignedLong(const std::string &str, unsigned long &val); +bool StringToUnsignedLongLong(const std::string &str, unsigned long long &val); +bool StringToLong(const std::string &str, long &val); +bool StringToLongLong(const std::string &str, long long &val); bool IsDirectoryExists(const std::string& fileName); bool CreateDirectory(const std::string& path, const mode_t mode); bool IsValidOutPath(const std::string& path); @@ -382,7 +386,15 @@ void CollectPidsByAppname(std::set &pids, const Container& appPackage) } std::string fileName {basePath + subDir + cmdline}; if (IsSameCommand(ReadFileToString(fileName), appPackage)) { - pids.emplace(std::stoul(subDir, nullptr)); + unsigned long tempPid = 0; + char *endPtr = nullptr; + errno = 0; + tempPid = std::strtoul(subDir.c_str(), &endPtr, 10); // 10 : decimal scale + if (endPtr == subDir.c_str() || *endPtr != '\0' || errno != 0) { + HLOGE("[CollectPidsByAppname] Invalid subDir: %s", subDir.c_str()); + return; + } + pids.emplace(static_cast(tempPid)); } } } diff --git a/interfaces/kits/js/napi/BUILD.gn b/interfaces/kits/js/napi/BUILD.gn index be41d05476fff210ee5f0735fdf64805d3c78a5a..92a03fd54167f62fe74c27d5d4f75fc3e9ff3c9f 100644 --- a/interfaces/kits/js/napi/BUILD.gn +++ b/interfaces/kits/js/napi/BUILD.gn @@ -29,6 +29,7 @@ ohos_shared_library("hiperf_client_napi") { deps = [ "${innerkits_path}/native/hiperf_client:hiperf_client" ] external_deps = [ + "c_utils:utils", "hilog:libhilog", "napi:ace_napi", ] diff --git a/interfaces/kits/js/napi/hiperf_client_napi.cpp b/interfaces/kits/js/napi/hiperf_client_napi.cpp index 5248c51ce7334019fe8a865ff4a27c0496aef067..5be25aedb2adf3ddf8ad62b4f41161d0812c9423 100644 --- a/interfaces/kits/js/napi/hiperf_client_napi.cpp +++ b/interfaces/kits/js/napi/hiperf_client_napi.cpp @@ -20,6 +20,7 @@ #include "hiperf_client.h" #include "napi/native_api.h" #include "napi/native_node_api.h" +#include "utilities.h" namespace OHOS { namespace Developtools { @@ -44,17 +45,17 @@ static std::vector StringSplit(const std::string& text, char delimi return tokens; } -static bool IsNumeric(const std::string& str) +static bool IsStringToIntSuccess(const std::string &str, int &val) { - std::istringstream iss(str); - int number; - char trailingCharacter; - if (!(iss >> number)) { - return false; - } - if (iss >> trailingCharacter) { + char *endPtr = nullptr; + errno = 0; + long num = 0; + num = std::strtol(str.c_str(), &endPtr, 10); // 10 : decimal scale + if (endPtr == str.c_str() || *endPtr != '\0' || errno != 0 || num > INT_MAX || num < INT_MIN) { + HLOGE("get int failed, str: %s", str.c_str()); return false; } + val = static_cast(num); return true; } @@ -64,8 +65,9 @@ static std::vector StringSplitToInt(const std::string& text, char delimiter std::string token; std::istringstream tokenStream(text); while (std::getline(tokenStream, token, delimiter)) { - if (IsNumeric(token)) { - tokens.push_back(std::stoi(token)); + int num = 0; + if (IsStringToIntSuccess(token, num)) { + tokens.push_back(num); } } return tokens; diff --git a/src/perf_event_record.cpp b/src/perf_event_record.cpp index 232796ce2cd27369dba15292b5167c87d35e974d..9b725a853288b05823533004eaa604bda4cf902f 100644 --- a/src/perf_event_record.cpp +++ b/src/perf_event_record.cpp @@ -295,7 +295,7 @@ PerfRecordMmap::PerfRecordMmap(bool inKernel, u32 pid, u32 tid, u64 addr, u64 le data_.addr = addr; data_.len = len; data_.pgoff = pgoff; - if (strncpy_s(data_.filename, KILO, filename.c_str(), filename.size()) != 0) { + if (strncpy_s(data_.filename, KILO, filename.c_str(), filename.size()) != EOK) { HLOGE("strncpy_s failed"); } @@ -356,7 +356,7 @@ PerfRecordMmap2::PerfRecordMmap2(const bool inKernel, const u32 pid, const u32 t data_.ino_generation = 0; data_.prot = prot; data_.flags = flags; - if (strncpy_s(data_.filename, KILO, filename.c_str(), filename.size()) != 0) { + if (strncpy_s(data_.filename, KILO, filename.c_str(), filename.size()) != EOK) { HLOGE("strncpy_s failed"); } @@ -379,7 +379,7 @@ PerfRecordMmap2::PerfRecordMmap2(const bool inKernel, const u32 pid, const u32 t // r--p 00000000 103:3e 12307 /data/storage/el1/bundle/entry.hap // why prot get from this is 7. rwxp DfxMap::PermsToProts(item->perms, data_.prot, data_.flags); - if (strncpy_s(data_.filename, KILO, item->name.c_str(), item->name.size()) != 0) { + if (strncpy_s(data_.filename, KILO, item->name.c_str(), item->name.size()) != EOK) { HLOGE("strncpy_s failed"); } @@ -465,7 +465,7 @@ PerfRecordComm::PerfRecordComm(const bool inKernel, const u32 pid, const u32 tid PerfEventRecord::Init(PERF_RECORD_COMM, inKernel); data_.pid = pid; data_.tid = tid; - if (strncpy_s(data_.comm, KILO, comm.c_str(), comm.size()) != 0) { + if (strncpy_s(data_.comm, KILO, comm.c_str(), comm.size()) != EOK) { HLOGE("strncpy_s failed !!!"); } diff --git a/src/perf_events.cpp b/src/perf_events.cpp index 5f47bd5edbf35868388f723aa3d95c07b4a4ac49..bc99255f5ec77a2719a67f35ff6f3141b2c54bcf 100644 --- a/src/perf_events.cpp +++ b/src/perf_events.cpp @@ -376,7 +376,10 @@ bool PerfEvents::AddEvent(const std::string &eventString, const bool followGroup } if (StringStartsWith(eventName, "0x") && eventName.length() <= MAX_HEX_EVENT_NAME_LENGTH && IsHexDigits(eventName)) { - return AddEvent(PERF_TYPE_RAW, std::stoull(eventName, nullptr, NUMBER_FORMAT_HEX_BASE), + unsigned long long config = 0; + CHECK_TRUE(StringToUnsignedLongLong(eventName, config), false, + LOG_TYPE_WITH_HILOG, "[AddEvent] eventName %s has invalid characters", eventName.c_str()); + return AddEvent(PERF_TYPE_RAW, static_cast(config), excludeUser, excludeKernel, followGroup); } else { auto [find, typeId, configId] = GetStaticConfigId(eventName); diff --git a/src/subcommand_dump.cpp b/src/subcommand_dump.cpp index c2e6cc932dfc619dbfba4023c70f0682185552c3..07fdaee839229fa74db5b4bb4447807e77810718 100644 --- a/src/subcommand_dump.cpp +++ b/src/subcommand_dump.cpp @@ -199,7 +199,7 @@ HiperfError SubCommandDump::OnSubCommand(std::vector& args) if (dumpAll_ || dumpData_) { // before load data section - SetHM(); + CHECK_TRUE(SetHM(), HiperfError::SET_HM_FAIL, LOG_TYPE_WITH_HILOG, "[LoadPerfData] SetHM failed"); DumpDataPortion(indent_); DumpSpeReport(); } @@ -602,7 +602,7 @@ bool SubCommandDump::RegisterSubCommandDump() return SubCommand::RegisterSubCommand("dump", SubCommandDump::GetInstance); } -void SubCommandDump::SetHM() +bool SubCommandDump::SetHM() { std::string os = reader_->GetFeatureString(FEATURE::OSRELEASE); isHM_ = os.find(HMKERNEL) != std::string::npos; @@ -612,10 +612,14 @@ void SubCommandDump::SetHM() pid_t devhost = -1; std::string str = reader_->GetFeatureString(FEATURE::HIPERF_HM_DEVHOST); if (IsNumeric(str)) { - devhost = std::stoll(str); + long val = 0; // 10 : decimal scale + CHECK_TRUE(StringToLong(str, val), false, + LOG_TYPE_WITH_HILOG, "[SetHM] str %s has invalid characters", str.c_str()); + devhost = static_cast(val); } vr_.SetDevhostPid(devhost); } + return true; } void SubCommandDump::DumpSpeReport() diff --git a/src/subcommand_record.cpp b/src/subcommand_record.cpp index f2421814141959b488d524be9004be4e6ebb0dd2..aed10127e684912fcb0a339fd539b23da396e773 100644 --- a/src/subcommand_record.cpp +++ b/src/subcommand_record.cpp @@ -809,10 +809,12 @@ pid_t SubCommandRecord::GetPidFromAppPackage(const pid_t oldPid, const uint64_t } std::string fileName {basePath + subDir + cmdline}; if (IsSameCommand(ReadFileToString(fileName), appPackage_)) { - res = static_cast(std::stoul(subDir, nullptr)); - HLOGD("[GetAppPackagePid]: get appPid for %s is %d", appPackage_.c_str(), res); - HIPERF_HILOGD(MODULE_DEFAULT, "[GetAppPackagePid] get appPid %{public}d for app", - res); + unsigned long tempPid = 0; + CHECK_TRUE(StringToUnsignedLong(subDir, tempPid), -1, + LOG_TYPE_WITH_HILOG, "[GetPidFromAppPackage] Invalid subDir: %s", subDir.c_str()); + res = static_cast(tempPid); + HLOGD("[GetPidFromAppPackage]: get appPid %d", res); + HIPERF_HILOGD(MODULE_DEFAULT, "[GetPidFromAppPackage] get appPid %{public}d", res); return res; } } @@ -2396,7 +2398,12 @@ void SubCommandRecord::SetHM() if (!IsDigits(subDir)) { continue; } - pid_t pid = std::stoll(subDir); + long val = 0; + if (!StringToLong(subDir, val)) { + HLOGE("[SetHM] Invalid subDir: %s", subDir.c_str()); + break; + } + pid_t pid = static_cast(val); std::string cmdline = GetProcessName(pid); for (const auto& service : SENSITIVE_SERVICE) { if (cmdline == "/bin/" + service) { diff --git a/src/subcommand_report.cpp b/src/subcommand_report.cpp index 4f29e253227c1370e02c7484804919d6421ebce4..3162fe73e3e449f9d6f178c86e8f54be541226a9 100644 --- a/src/subcommand_report.cpp +++ b/src/subcommand_report.cpp @@ -480,7 +480,7 @@ bool SubCommandReport::LoadPerfData() ProcessUniStackTableData(); HLOGD("process record"); // before load data section - SetHM(); + CHECK_TRUE(SetHM(), false, LOG_TYPE_WITH_HILOG, "[LoadPerfData] SetHM failed"); recordFileReader_->ReadDataSection( [this] (PerfEventRecord& record) -> bool { return this->RecordCallBack(record); @@ -627,7 +627,7 @@ bool SubCommandReport::RegisterSubCommandReport() return SubCommand::RegisterSubCommand("report", SubCommandReport::GetInstance); } -void SubCommandReport::SetHM() +bool SubCommandReport::SetHM() { std::string os = recordFileReader_->GetFeatureString(FEATURE::OSRELEASE); isHM_ = os.find(HMKERNEL) != std::string::npos; @@ -637,10 +637,14 @@ void SubCommandReport::SetHM() pid_t devhost = -1; std::string str = recordFileReader_->GetFeatureString(FEATURE::HIPERF_HM_DEVHOST); if (str != EMPTY_STRING && IsNumeric(str)) { - devhost = std::stoll(str); + long long val = 0; + CHECK_TRUE(StringToLongLong(str, val), false, + LOG_TYPE_WITH_HILOG, "[SetHM] str %s has invalid characters", str.c_str()); + devhost = static_cast(val); } GetReport().virtualRuntime_.SetDevhostPid(devhost); } + return true; } SubCommand& SubCommandReport::GetInstance() diff --git a/src/utilities.cpp b/src/utilities.cpp index 9de04fff0d58821141a89c37582c9807f967216f..43ebbc9f9845432d8a365fe4dc7bdb17f141c8bd 100644 --- a/src/utilities.cpp +++ b/src/utilities.cpp @@ -62,9 +62,10 @@ std::string CanonicalizeSpecPath(const char* src) return ""; } #else - if (access(src, F_OK) == 0) { + struct stat st; + if (stat(src, &st) == 0) { if (strstr(src, "/proc/") == src && strstr(src, "/data/storage") != nullptr) { // for sandbox - if (strncpy_s(resolvedPath, sizeof(resolvedPath), src, strlen(src)) == -1) { + if (strncpy_s(resolvedPath, sizeof(resolvedPath), src, strlen(src)) != EOK) { HLOGE("Error: strncpy_s %s failed", src); return ""; } @@ -362,6 +363,10 @@ bool IscontainDigits(const std::string& str) bool IsStringToIntSuccess(const std::string &str, int &val) { + if (str.empty()) { + HIPERF_HILOGE(MODULE_DEFAULT, "string to int failed: empty not allowed"); + return false; + } char *endPtr = nullptr; errno = 0; long num = 0; @@ -376,6 +381,14 @@ bool IsStringToIntSuccess(const std::string &str, int &val) bool StringToUint64(const std::string &str, uint64_t &val) { + if (str.empty()) { + HIPERF_HILOGE(MODULE_DEFAULT, "string to uint64_t failed: empty not allowed"); + return false; + } + if (str[0] == '-') { + HIPERF_HILOGE(MODULE_DEFAULT, "string to uint64_t failed: negative value not allowed"); + return false; + } char *endPtr = nullptr; errno = 0; uint64_t num = std::strtoull(str.c_str(), &endPtr, 10); // 10 : decimal scale @@ -387,6 +400,82 @@ bool StringToUint64(const std::string &str, uint64_t &val) return true; } +bool StringToUnsignedLong(const std::string &str, unsigned long &val) +{ + if (str.empty()) { + HIPERF_HILOGE(MODULE_DEFAULT, "string to unsigned long failed: empty not allowed"); + return false; + } + if (str[0] == '-') { + HIPERF_HILOGE(MODULE_DEFAULT, "string to unsigned long failed: negative value not allowed"); + return false; + } + char *endPtr = nullptr; + errno = 0; + unsigned long num = std::strtoul(str.c_str(), &endPtr, 10); // 10 : decimal scale + if (endPtr == str.c_str() || *endPtr != '\0' || errno != 0) { + HIPERF_HILOGE(MODULE_DEFAULT, "string to unsigned long failed"); + return false; + } + val = num; + return true; +} + +bool StringToUnsignedLongLong(const std::string &str, unsigned long long &val) +{ + if (str.empty()) { + HIPERF_HILOGE(MODULE_DEFAULT, "string to unsigned long long failed: empty not allowed"); + return false; + } + if (str[0] == '-') { + HIPERF_HILOGE(MODULE_DEFAULT, "string to unsigned unsigned long long failed: negative value not allowed"); + return false; + } + char *endPtr = nullptr; + errno = 0; + unsigned long long num = std::strtoull(str.c_str(), &endPtr, 10); // 10 : decimal scale + if (endPtr == str.c_str() || *endPtr != '\0' || errno != 0) { + HIPERF_HILOGE(MODULE_DEFAULT, "string to unsigned long long failed"); + return false; + } + val = num; + return true; +} + +bool StringToLong(const std::string &str, long &val) +{ + if (str.empty()) { + HIPERF_HILOGE(MODULE_DEFAULT, "string to long failed: empty not allowed"); + return false; + } + char *endPtr = nullptr; + errno = 0; + long num = std::strtol(str.c_str(), &endPtr, 10); // 10 : decimal scale + if (endPtr == str.c_str() || *endPtr != '\0' || errno != 0) { + HIPERF_HILOGE(MODULE_DEFAULT, "string to long failed"); + return false; + } + val = num; + return true; +} + +bool StringToLongLong(const std::string &str, long long &val) +{ + if (str.empty()) { + HIPERF_HILOGE(MODULE_DEFAULT, "string to long long failed: empty not allowed"); + return false; + } + char *endPtr = nullptr; + errno = 0; + long long num = std::strtoll(str.c_str(), &endPtr, 10); // 10 : decimal scale + if (endPtr == str.c_str() || *endPtr != '\0' || errno != 0) { + HIPERF_HILOGE(MODULE_DEFAULT, "string to long long failed"); + return false; + } + val = num; + return true; +} + bool ReadIntFromProcFile(const std::string &path, int &value) { std::string s = ReadFileToString(path); @@ -693,8 +782,11 @@ pid_t GetAppPackagePid(const std::string &appPackage, const pid_t oldPid, const } std::string fileName {basePath + subDir + cmdline}; if (IsSameCommand(ReadFileToString(fileName), appPackage)) { - res = std::stoul(subDir, nullptr); - HLOGD("[GetAppPackagePid]: get appid for %s is %d", appPackage.c_str(), res); + unsigned long tempPid = 0; + CHECK_TRUE(StringToUnsignedLong(subDir, tempPid), -1, + LOG_TYPE_WITH_HILOG, "[GetAppPackagePid] Invalid subDir: %s", subDir.c_str()); + res = static_cast(tempPid); + HLOGD("[GetAppPackagePid]: get appid %d", res); return res; } } @@ -712,7 +804,7 @@ bool CheckAppIsRunning(std::vector &selectPids, const std::string &appPac printf("app %s not running\n", appPackage.c_str()); return false; } - HLOGD("[CheckAppIsRunning] get appPid %d for app %s\n", appPid, appPackage.c_str()); + HLOGD("[CheckAppIsRunning] get appPid %d", appPid); selectPids.push_back(appPid); } return true; @@ -819,7 +911,10 @@ bool LittleMemory() std::string line; while (getline(file, line)) { if (line.find("MemTotal:") != std::string::npos) { - int memSize = stoi(line.substr(line.find(":") + 1)); + int memSize = 0; + if (!IsStringToIntSuccess(line.substr(line.find(":") + 1), memSize)) { + return false; + } CHECK_TRUE(memSize >= (LITTLE_MEMORY_SIZE * MULTIPLE_SIZE * MULTIPLE_SIZE), true, 0, ""); } } diff --git a/src/virtual_runtime.cpp b/src/virtual_runtime.cpp index e5e1718cf1cd3a16f2bc61133d84790bf34a07b3..00f482da7ad3f96b144f05bd2396f5c6ed135a50 100644 --- a/src/virtual_runtime.cpp +++ b/src/virtual_runtime.cpp @@ -1411,7 +1411,7 @@ void VirtualRuntime::FixHMBundleMmap(char *filename, const int pid, u16 &headerS if (memset_s(filename, KILO, '\0', KILO) != EOK) { HLOGD("memset_s failed in FixHMBundleMmap."); } - if (strncpy_s(filename, KILO, newFilename.c_str(), newFilename.size()) != 0) { + if (strncpy_s(filename, KILO, newFilename.c_str(), newFilename.size()) != EOK) { HLOGD("strncpy_s recordMmap2 failed!"); } headerSize += newFilename.size() - oldSize; diff --git a/src/virtual_thread.cpp b/src/virtual_thread.cpp index ef65da8822c576d1f00684796de43776d18cea75..97273170eece52eef48e87c073eb407dbe8c19d0 100644 --- a/src/virtual_thread.cpp +++ b/src/virtual_thread.cpp @@ -298,8 +298,18 @@ void VirtualThread::ParseServiceMap(const std::string &filename) if (addrRanges.size() < mmapAddrRangeToken) { continue; } - begin = std::stoull(addrRanges[0], nullptr, NUMBER_FORMAT_HEX_BASE); - end = std::stoull(addrRanges[1], nullptr, NUMBER_FORMAT_HEX_BASE); + unsigned long long beginVal = 0; + unsigned long long endVal = 0; + if (!StringToUnsignedLongLong(addrRanges[0], beginVal)) { + HLOGE("addrRanges[0] convert to beginVal failed, addrRanges[0]: %s", addrRanges[0].c_str()); + continue; + } + if (!StringToUnsignedLongLong(addrRanges[1], endVal)) { + HLOGE("addrRanges[1] convert to beginVal failed, addrRanges[0]: %s", addrRanges[1].c_str()); + continue; + } + begin = static_cast(beginVal); + end = static_cast(endVal); break; } } diff --git a/test/unittest/common/native/utilities_test.cpp b/test/unittest/common/native/utilities_test.cpp index 613e2d11f3ee6d3cdf48c1966f09e562d28ae4a7..2d1ec66ff2572af758c64c2fe8230f3a8a78b253 100644 --- a/test/unittest/common/native/utilities_test.cpp +++ b/test/unittest/common/native/utilities_test.cpp @@ -1018,6 +1018,284 @@ HWTEST_F(UtilitiesTest, IsDebugableApp, TestSize.Level1) { EXPECT_FALSE(IsDebugableApp("hiperf_test_demo")); } + +/** + * @tc.name: IsStringToIntSuccess + * @tc.desc: Test IsStringToIntSuccess fun + * @tc.type: FUNC + */ +HWTEST_F(UtilitiesTest, IsStringToIntSuccess_ValidPositive, TestSize.Level1) +{ + int val; + + // Valid cases + EXPECT_TRUE(IsStringToIntSuccess("0", val)); + EXPECT_EQ(val, 0); + + EXPECT_TRUE(IsStringToIntSuccess("123", val)); + EXPECT_EQ(val, 123); + + EXPECT_TRUE(IsStringToIntSuccess("-456", val)); + EXPECT_EQ(val, -456); + + EXPECT_TRUE(IsStringToIntSuccess(std::to_string(INT_MAX), val)); + EXPECT_EQ(val, INT_MAX); + + EXPECT_TRUE(IsStringToIntSuccess(std::to_string(INT_MIN), val)); + EXPECT_EQ(val, INT_MIN); + + EXPECT_TRUE(IsStringToIntSuccess(" 789", val)); // Leading spaces (strtol skips whitespace) + EXPECT_EQ(val, 789); + + EXPECT_TRUE(IsStringToIntSuccess("+901", val)); // Positive sign + EXPECT_EQ(val, 901); + + // Invalid cases + EXPECT_FALSE(IsStringToIntSuccess("", val)); // Empty string + + EXPECT_FALSE(IsStringToIntSuccess("abc", val)); // Non-numeric + + EXPECT_FALSE(IsStringToIntSuccess("123abc", val)); // Trailing non-numeric + + EXPECT_FALSE(IsStringToIntSuccess("123 ", val)); // Trailing spaces + + EXPECT_FALSE(IsStringToIntSuccess("-", val)); // Only negative sign + + EXPECT_FALSE(IsStringToIntSuccess("+", val)); // Only positive sign + + EXPECT_FALSE(IsStringToIntSuccess("+-123", val)); // Invalid sign combination + + EXPECT_FALSE(IsStringToIntSuccess("9223372036854775808", val)); // Exceeds long range (errno set) +} + +/** + * @tc.name: StringToUint64_AllCases + * @tc.desc: Test various cases for StringToUint64, covering valid and invalid scenarios + * @tc.type: FUNC + */ +HWTEST_F(UtilitiesTest, StringToUint64_AllCases, TestSize.Level2) +{ + uint64_t val; + + // Valid cases + EXPECT_TRUE(StringToUint64("0", val)); + EXPECT_EQ(val, 0ULL); + + EXPECT_TRUE(StringToUint64("1234567890123456789", val)); + EXPECT_EQ(val, 1234567890123456789ULL); + + EXPECT_TRUE(StringToUint64(std::to_string(ULLONG_MAX), val)); + EXPECT_EQ(val, ULLONG_MAX); + + EXPECT_TRUE(StringToUint64(" 9876543210", val)); // Leading spaces (strtoull skips whitespace) + EXPECT_EQ(val, 9876543210ULL); + + EXPECT_TRUE(StringToUint64("+123", val)); // Positive sign allowed + EXPECT_EQ(val, 123ULL); + + // Invalid cases + EXPECT_FALSE(StringToUint64("", val)); // Empty string (endPtr == str.c_str()) + + EXPECT_FALSE(StringToUint64("abc123", val)); // Non-numeric prefix (endPtr == str.c_str()) + + EXPECT_FALSE(StringToUint64("123abc", val)); // Trailing non-numeric (*endPtr != '\0') + + EXPECT_FALSE(StringToUint64("123 ", val)); // Trailing spaces (*endPtr != '\0') + + EXPECT_FALSE(StringToUint64("-123", val)); // Negative sign (str.c_str()[0] == '-') + + EXPECT_FALSE(StringToUint64("-", val)); // Only negative sign + + EXPECT_FALSE(StringToUint64("+-123", val)); // Invalid sign combination + + EXPECT_FALSE(StringToUint64("18446744073709551616", val)); // Larger than ULLONG_MAX (if ULLONG_MAX is 2^64-1) +} + +/** + * @tc.name: StringToUnsignedLong_AllCases + * @tc.desc: Test various cases for StringToUnsignedLong, covering valid and invalid scenarios + * @tc.type: FUNC + */ +HWTEST_F(UtilitiesTest, StringToUnsignedLong_AllCases, TestSize.Level2) +{ + unsigned long val; + + // Valid cases + EXPECT_TRUE(StringToUnsignedLong("0", val)); + EXPECT_EQ(val, 0UL); + + EXPECT_TRUE(StringToUnsignedLong("12345", val)); + EXPECT_EQ(val, 12345UL); + + EXPECT_TRUE(StringToUnsignedLong(std::to_string(ULONG_MAX), val)); + EXPECT_EQ(val, ULONG_MAX); + + EXPECT_TRUE(StringToUnsignedLong(" 6789", val)); // Leading spaces (strtoul skips whitespace) + EXPECT_EQ(val, 6789UL); + + EXPECT_TRUE(StringToUnsignedLong("+9876", val)); // Positive sign allowed + EXPECT_EQ(val, 9876UL); + + // Invalid cases + EXPECT_FALSE(StringToUnsignedLong("", val)); // Empty string (endPtr == str.c_str()) + + EXPECT_FALSE(StringToUnsignedLong("abc123", val)); // Non-numeric prefix (endPtr == str.c_str()) + + EXPECT_FALSE(StringToUnsignedLong("123abc", val)); // Trailing non-numeric (*endPtr != '\0') + + EXPECT_FALSE(StringToUnsignedLong("123 ", val)); // Trailing spaces (*endPtr != '\0') + + EXPECT_FALSE(StringToUnsignedLong("-123", val)); // Negative sign (parsed as invalid by strtoul with errno) + + EXPECT_FALSE(StringToUnsignedLong("-", val)); // Only negative sign (endPtr == str.c_str()) + + EXPECT_FALSE(StringToUnsignedLong("+-123", val)); // Invalid sign combination (endPtr points to '+') + + EXPECT_FALSE(StringToUnsignedLong("18446744073709551616", val)); // Larger than typical ULONG_MAX (if 64-bit) +} + +/** + * @tc.name: StringToUnsignedLongLong_AllCases + * @tc.desc: Test various cases for StringToUnsignedLongLong, covering valid and invalid scenarios + * @tc.type: FUNC + */ +HWTEST_F(UtilitiesTest, StringToUnsignedLongLong_AllCases, TestSize.Level2) +{ + unsigned long long val; + + // Valid cases + EXPECT_TRUE(StringToUnsignedLongLong("0", val)); + EXPECT_EQ(val, 0ULL); + + EXPECT_TRUE(StringToUnsignedLongLong("1234567890123456789", val)); + EXPECT_EQ(val, 1234567890123456789ULL); + + EXPECT_TRUE(StringToUnsignedLongLong(std::to_string(ULLONG_MAX), val)); + EXPECT_EQ(val, ULLONG_MAX); + + EXPECT_TRUE(StringToUnsignedLongLong(" 9876543210", val)); // Leading spaces (strtoull skips whitespace) + EXPECT_EQ(val, 9876543210ULL); + + EXPECT_TRUE(StringToUnsignedLongLong("+12345", val)); // Positive sign allowed + EXPECT_EQ(val, 12345ULL); + + // Invalid cases + EXPECT_FALSE(StringToUnsignedLongLong("", val)); // Empty string (endPtr == str.c_str()) + + EXPECT_FALSE(StringToUnsignedLongLong("abc123", val)); // Non-numeric prefix (endPtr == str.c_str()) + + EXPECT_FALSE(StringToUnsignedLongLong("123abc", val)); // Trailing non-numeric (*endPtr != '\0') + + EXPECT_FALSE(StringToUnsignedLongLong("123 ", val)); // Trailing spaces (*endPtr != '\0') + + EXPECT_FALSE(StringToUnsignedLongLong("-12345", val)); // Negative sign (parsed as invalid by strtoull with errno) + + EXPECT_FALSE(StringToUnsignedLongLong("-", val)); // Only negative sign (endPtr == str.c_str()) + + EXPECT_FALSE(StringToUnsignedLongLong("+-123", val)); // Invalid sign combination (endPtr points to '+') + + EXPECT_FALSE(StringToUnsignedLongLong("18446744073709551616", val)); // Larger than ULLONG_MAX (if 64-bit) +} + +/** + * @tc.name: StringToLong_AllCases + * @tc.desc: Test various cases for StringToLong, covering valid and invalid scenarios + * @tc.type: FUNC + */ +HWTEST_F(UtilitiesTest, StringToLong_AllCases, TestSize.Level2) +{ + long val; + + // Valid cases + EXPECT_TRUE(StringToLong("0", val)); + EXPECT_EQ(val, 0L); + + EXPECT_TRUE(StringToLong("123456", val)); + EXPECT_EQ(val, 123456L); + + EXPECT_TRUE(StringToLong("-7890", val)); + EXPECT_EQ(val, -7890L); + + EXPECT_TRUE(StringToLong(std::to_string(LONG_MAX), val)); + EXPECT_EQ(val, LONG_MAX); + + EXPECT_TRUE(StringToLong(std::to_string(LONG_MIN), val)); + EXPECT_EQ(val, LONG_MIN); + + EXPECT_TRUE(StringToLong(" 98765", val)); // Leading spaces (strtol skips whitespace) + EXPECT_EQ(val, 98765L); + + EXPECT_TRUE(StringToLong("+4321", val)); // Positive sign allowed + EXPECT_EQ(val, 4321L); + + // Invalid cases + EXPECT_FALSE(StringToLong("", val)); // Empty string (endPtr == str.c_str()) + + EXPECT_FALSE(StringToLong("abc123", val)); // Non-numeric prefix (endPtr == str.c_str()) + + EXPECT_FALSE(StringToLong("123abc", val)); // Trailing non-numeric (*endPtr != '\0') + + EXPECT_FALSE(StringToLong("123 ", val)); // Trailing spaces (*endPtr != '\0') + + EXPECT_FALSE(StringToLong("+-123", val)); // Invalid sign combination (endPtr points to '+') + + EXPECT_FALSE(StringToLong("-", val)); // Only negative sign (endPtr == str.c_str()) + + EXPECT_FALSE(StringToLong("+", val)); // Only positive sign (endPtr == str.c_str()) + + EXPECT_FALSE(StringToLong("9223372036854775808", val)); // Larger than typical LONG_MAX (if 64-bit) + EXPECT_FALSE(StringToLong("-9223372036854775809", val)); // Smaller than typical LONG_MIN (64-bit) +} + +/** + * @tc.name: StringToLongLong_AllCases + * @tc.desc: Test various cases for StringToLongLong, covering valid and invalid scenarios + * @tc.type: FUNC + */ +HWTEST_F(UtilitiesTest, StringToLongLong_AllCases, TestSize.Level2) +{ + long long val; + + // Valid cases + EXPECT_TRUE(StringToLongLong("0", val)); + EXPECT_EQ(val, 0LL); + + EXPECT_TRUE(StringToLongLong("123456789012345", val)); + EXPECT_EQ(val, 123456789012345LL); + + EXPECT_TRUE(StringToLongLong("-98765432101234", val)); + EXPECT_EQ(val, -98765432101234LL); + + EXPECT_TRUE(StringToLongLong(std::to_string(LLONG_MAX), val)); + EXPECT_EQ(val, LLONG_MAX); + + EXPECT_TRUE(StringToLongLong(std::to_string(LLONG_MIN), val)); + EXPECT_EQ(val, LLONG_MIN); + + EXPECT_TRUE(StringToLongLong(" 456789", val)); // Leading spaces (strtoll skips whitespace) + EXPECT_EQ(val, 456789LL); + + EXPECT_TRUE(StringToLongLong("+789012", val)); // Positive sign allowed + EXPECT_EQ(val, 789012LL); + + // Invalid cases + EXPECT_FALSE(StringToLongLong("", val)); // Empty string (endPtr == str.c_str()) + + EXPECT_FALSE(StringToLongLong("abc123", val)); // Non-numeric prefix (endPtr == str.c_str()) + + EXPECT_FALSE(StringToLongLong("123abc", val)); // Trailing non-numeric (*endPtr != '\0') + + EXPECT_FALSE(StringToLongLong("123 ", val)); // Trailing spaces (*endPtr != '\0') + + EXPECT_FALSE(StringToLongLong("+-123", val)); // Invalid sign combination (endPtr points to '+') + + EXPECT_FALSE(StringToLongLong("-", val)); // Only negative sign (endPtr == str.c_str()) + + EXPECT_FALSE(StringToLongLong("+", val)); // Only positive sign (endPtr == str.c_str()) + + EXPECT_FALSE(StringToLongLong("9223372036854775808", val)); // Larger than typical LLONG_MAX (64-bit) + EXPECT_FALSE(StringToLongLong("-9223372036854775809", val)); // Smaller than typical LLONG_MIN (64-bit) +} } // namespace HiPerf } // namespace Developtools } // namespace OHOS