diff --git a/base/BUILD.gn b/base/BUILD.gn index e2e2a2636f88f82bf8863c079a042df6ab880f44..338aafbe5898b0c07cf3576c1c8f00377bcc8e3d 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn @@ -19,6 +19,7 @@ declare_args() { c_utils_track_all = false c_utils_print_track_at_once = false c_utils_debug_log_enabled = false + c_utils_feature_intsan = true } config("utils_config") { @@ -148,6 +149,13 @@ ohos_shared_library("utils") { } else { sources = sources_utils configs = [ ":utils_coverage_config" ] + + if (c_utils_feature_intsan) { + sanitize = { + integer_overflow = true + } + } + if (c_utils_debug_refbase) { configs += [ ":debug_refbase" ] if (c_utils_track_all) { @@ -204,7 +212,7 @@ if (host_os == "linux" && !is_asan) { ] deps = [ ":cxx_rust_gen", - "//build/rust/tests:cxx_cppdeps", + "//third_party/rust/crates/cxx:cxx_cppdeps", ] public_deps = [ "//third_party/bounds_checking_function:libsec_shared" ] diff --git a/base/src/datetime_ex.cpp b/base/src/datetime_ex.cpp index 12a814562a9c1fc4e4b4761a271198bae1fd3839..3ec5508108617dc7e3f7c98b6a98253f5b3d2f27 100644 --- a/base/src/datetime_ex.cpp +++ b/base/src/datetime_ex.cpp @@ -46,6 +46,9 @@ int64_t GetSecondsBetween(struct tm inputTm1, struct tm inputTm2) { int64_t second1 = GetSecondsSince1970ToPointTime(inputTm1); int64_t second2 = GetSecondsSince1970ToPointTime(inputTm2); + if (second1 == -1 || second2 == -1) { + return -1; + } return second1 >= second2 ? (second1 - second2) : (second2 - second1); } diff --git a/base/src/directory_ex.cpp b/base/src/directory_ex.cpp index dd8e6f720d3ddc5e22cd48166ecfc182cd8ceb3d..9e79b9ba9b0e6c6bb381ac3e683dfc3eeaf82c10 100644 --- a/base/src/directory_ex.cpp +++ b/base/src/directory_ex.cpp @@ -15,7 +15,8 @@ #include "directory_ex.h" #include -#include +#include +#include #include "securec.h" #include "unistd.h" #include "utils_log.h" @@ -217,7 +218,7 @@ bool ForceRemoveDirectory(const string& path) if (ptr->d_type == DT_DIR) { ret = ForceRemoveDirectory(subPath); } else { - if (access(subPath.c_str(), F_OK) == 0) { + if (faccessat(AT_FDCWD, subPath.c_str(), F_OK, AT_SYMLINK_NOFOLLOW) == 0) { if (remove(subPath.c_str()) != 0) { closedir(dir); return false; @@ -228,13 +229,13 @@ bool ForceRemoveDirectory(const string& path) closedir(dir); string currentPath = ExcludeTrailingPathDelimiter(path); - if (access(currentPath.c_str(), F_OK) == 0) { + if (faccessat(AT_FDCWD, currentPath.c_str(), F_OK, AT_SYMLINK_NOFOLLOW) == 0) { if (remove(currentPath.c_str()) != 0) { return false; } } - return ret && (access(path.c_str(), F_OK) != 0); + return ret && (faccessat(AT_FDCWD, path.c_str(), F_OK, AT_SYMLINK_NOFOLLOW) != 0); } bool RemoveFile(const string& fileName) diff --git a/base/src/event_demultiplexer.cpp b/base/src/event_demultiplexer.cpp index 87df8a71f0527960f537ad45991a12f199ccca61..e4446845e83141b6471f61eeab4f63e6f49d7d82 100644 --- a/base/src/event_demultiplexer.cpp +++ b/base/src/event_demultiplexer.cpp @@ -70,7 +70,7 @@ uint32_t EventDemultiplexer::UpdateEventHandler(EventHandler* handler) std::lock_guard lock(mutex_); auto itor = eventHandlers_.find(handler->GetHandle()); if (itor == eventHandlers_.end()) { - eventHandlers_.insert(std::make_pair(handler->GetHandle(), handler)); + eventHandlers_.insert(std::make_pair(handler->GetHandle(), handler->shared_from_this())); return Update(EPOLL_CTL_ADD, handler); } @@ -79,7 +79,7 @@ uint32_t EventDemultiplexer::UpdateEventHandler(EventHandler* handler) return Update(EPOLL_CTL_DEL, handler); } - if (handler != itor->second) { + if (handler != itor->second.get()) { return TIMER_ERR_DEAL_FAILED; } return Update(EPOLL_CTL_MOD, handler); @@ -102,7 +102,19 @@ uint32_t EventDemultiplexer::Update(int operation, EventHandler* handler) void EventDemultiplexer::Polling(int timeout /* ms */) { + std::vector> holdHandlers; std::vector epollEvents(maxEvents_); + { + std::lock_guard lock(mutex_); + if (eventHandlers_.size() == 0) { + return; + } + + for (auto itor = eventHandlers_.begin(); itor != eventHandlers_.end();++itor) { + holdHandlers.emplace_back(itor->second); + } + } + int nfds = epoll_wait(epollFd_, &epollEvents[0], static_cast(epollEvents.size()), timeout); if (nfds == 0) { return; @@ -113,8 +125,8 @@ void EventDemultiplexer::Polling(int timeout /* ms */) } for (int idx = 0; idx < nfds; ++idx) { - uint32_t events = epollEvents[idx].events; void* ptr = epollEvents[idx].data.ptr; + uint32_t events = epollEvents[idx].events; auto handler = reinterpret_cast(ptr); if (handler != nullptr) { handler->HandleEvents(Epoll2Reactor(events)); @@ -149,4 +161,4 @@ uint32_t EventDemultiplexer::Reactor2Epoll(uint32_t reactorEvent) } } -} +} \ No newline at end of file diff --git a/base/src/event_demultiplexer.h b/base/src/event_demultiplexer.h index 5c25e5663c090835009b9066f20ea6c67d439edc..13fe966d42c2c7c5f7716e88d888a0094424df18 100644 --- a/base/src/event_demultiplexer.h +++ b/base/src/event_demultiplexer.h @@ -17,6 +17,7 @@ #define UTILS_EVENT_DEMULTIPLEXER_H #include +#include #include #include @@ -47,7 +48,7 @@ private: int epollFd_; int maxEvents_; std::recursive_mutex mutex_; - std::map eventHandlers_; // guard by mutex_ + std::map> eventHandlers_; // guard by mutex_ }; } diff --git a/base/src/event_handler.h b/base/src/event_handler.h index af75cbea09bfb1a381843b1cf5a9c7e43465c8da..511bb6f8b93726194dbb1875becc22cfc2d91690 100644 --- a/base/src/event_handler.h +++ b/base/src/event_handler.h @@ -19,13 +19,15 @@ #include #include #include +#include +#include namespace OHOS { namespace Utils { class EventReactor; -class EventHandler { +class EventHandler : public std::enable_shared_from_this { public: using Callback = std::function; diff --git a/base/src/file_ex.cpp b/base/src/file_ex.cpp index b7e3a6e1016890e2a946dfb5f564cafba08e067c..897cc412c083f2bd33ebbeedb1a40751ebe004fd 100644 --- a/base/src/file_ex.cpp +++ b/base/src/file_ex.cpp @@ -116,9 +116,9 @@ bool LoadStringFromFile(const string& filePath, string& content) } file.seekg(0, ios::end); - const long fileLength = file.tellg(); + const long long fileLength = file.tellg(); if (fileLength > MAX_FILE_LENGTH) { - UTILS_LOGD("invalid file length(%{public}ld)!", fileLength); + UTILS_LOGD("invalid file length(%{public}lld)!", fileLength); return false; } @@ -137,7 +137,7 @@ string GetFileNameByFd(const int fd) string fdPath = "/proc/self/fd/" + std::to_string(fd); char fileName[PATH_MAX + 1] = {0}; - int ret = readlink(fdPath.c_str(), fileName, PATH_MAX); + ssize_t ret = readlink(fdPath.c_str(), fileName, PATH_MAX); if (ret < 0 || ret > PATH_MAX) { UTILS_LOGD("Get fileName failed, ret is: %{public}d!", ret); return string(); @@ -168,9 +168,9 @@ bool LoadStringFromFd(int fd, string& content) return false; } - const long fileLength = lseek(fd, 0, SEEK_END); + const off_t fileLength = lseek(fd, 0, SEEK_END); if (fileLength > MAX_FILE_LENGTH) { - UTILS_LOGE("invalid file length(%{public}ld)!", fileLength); + UTILS_LOGE("invalid file length(%{public}jd)!", static_cast(fileLength)); return false; } @@ -184,16 +184,16 @@ bool LoadStringFromFd(int fd, string& content) } content.resize(fileLength); - int loc = lseek(fd, 0, SEEK_SET); + off_t loc = lseek(fd, 0, SEEK_SET); if (loc == -1) { UTILS_LOGE("lseek file to begin failed!"); return false; } - const long len = read(fd, content.data(), fileLength); + const ssize_t len = read(fd, content.data(), fileLength); if (len != fileLength) { - UTILS_LOGE("the length read from file is not equal to fileLength!len:%{public}ld,fileLen:%{public}ld", - len, fileLength); + UTILS_LOGE("the length read from file is not equal to fileLength!len:%{public}zd,fileLen:%{public}jd", + len, static_cast(fileLength)); return false; } @@ -240,14 +240,14 @@ bool SaveStringToFd(int fd, const std::string& content) return true; } - const long len = write(fd, content.c_str(), content.length()); + const ssize_t len = write(fd, content.c_str(), content.length()); if (len < 0) { UTILS_LOGE("write file failed!errno:%{public}d, err:%{public}s", errno, strerror(errno)); return false; } if (static_cast(len) != content.length()) { - UTILS_LOGE("the length write to file is not equal to fileLength!len:%{public}ld, fileLen:%{public}zu", + UTILS_LOGE("the length write to file is not equal to fileLength!len:%{public}zd, fileLen:%{public}zu", len, content.length()); return false; } @@ -301,9 +301,9 @@ bool LoadBufferFromFile(const string& filePath, vector& content) } file.seekg(0, std::ios::end); - const long fileLength = file.tellg(); + const long long fileLength = file.tellg(); if (fileLength > MAX_FILE_LENGTH) { - UTILS_LOGD("invalid file length(%{public}ld)!", fileLength); + UTILS_LOGD("invalid file length(%{public}lld)!", fileLength); return false; } diff --git a/base/src/rust/ashmem.rs b/base/src/rust/ashmem.rs index 055885cdfa13db1d3ab6b7cfe4626eb9aad3fbe9..36ff005213dad1254b912b3f20ad78c169088de2 100644 --- a/base/src/rust/ashmem.rs +++ b/base/src/rust/ashmem.rs @@ -36,13 +36,6 @@ pub mod ffi { include!("commonlibrary/c_utils/base/include/ashmem.h"); // global function - /** - * Create an ashmem and return its FD. - * # Safety - * Requires C-style string as parameter to specify the name of Ashmem. - */ - pub unsafe fn AshmemCreate(name: *const c_char, size: usize) -> i32; - /** * Create an C++ Ashmem object managed by std::shared_ptr. * # Safety @@ -217,16 +210,4 @@ pub unsafe fn create_ashmem_instance(name: &str, size: i32) -> Option { } else { Some(Ashmem::new(c_ashmem_ptr)) } -} - -/** - * Create raw ashmem and returns its FD. - * # Safety - * Transmits c-style string of `name`. - */ -#[allow(dead_code)] -pub unsafe fn ashmem_create(name: &str, size: i32) -> i32 { - let c_name = CString::new(name).expect("CString::new Failed!"); - let name_ptr = c_name.as_ptr(); - ffi::AshmemCreate(name_ptr, size.try_into().expect("Invalid size.")) } \ No newline at end of file diff --git a/base/src/string_ex.cpp b/base/src/string_ex.cpp index b279544be72336255a93c0006acb6f2bebeed0f8..0082ff75420c97f1c88826a7a6052247e1a4bd9e 100644 --- a/base/src/string_ex.cpp +++ b/base/src/string_ex.cpp @@ -56,9 +56,21 @@ string ReplaceStr(const string& str, const string& src, const string& dst) string TrimStr(const string& str, const char cTrim /*= ' '*/) { + if (str.size() == 1 && str[0] == cTrim) { + return string{}; + } + string strTmp = str; - strTmp.erase(0, strTmp.find_first_not_of(cTrim)); - strTmp.erase(strTmp.find_last_not_of(cTrim) + sizeof(char)); + std::string::size_type firstBound = strTmp.find_first_not_of(cTrim); + if (firstBound != std::string::npos) { + strTmp.erase(0, firstBound); + } + + std::string::size_type lastBound = strTmp.find_last_not_of(cTrim); + if (lastBound != std::string::npos && lastBound != strTmp.size() - 1) { + strTmp.erase(lastBound + sizeof(char)); + } + return strTmp; } diff --git a/base/src/timer.cpp b/base/src/timer.cpp index 4fc9a1d074152cbc73e4f1d00eda49808412c82c..bb4db90a5564ef6a91ef00d435aac42501a0ae86 100644 --- a/base/src/timer.cpp +++ b/base/src/timer.cpp @@ -49,14 +49,6 @@ void Timer::Shutdown(bool useJoin) } reactor_->SwitchOff(); - if (timeoutMs_ == -1) { - std::lock_guard lock(mutex_); - if (intervalToTimers_.empty()) { - UTILS_LOGI("no event for epoll wait, use detach to shutdown"); - thread_.detach(); - return; - } - } if (!useJoin) { thread_.detach(); return; diff --git a/base/src/timer_event_handler.h b/base/src/timer_event_handler.h index 3201480b565c24485bf547ee8318f73ee90e9618..1fd0bd69c231c84d671c9b78b57a5e76b16b99e2 100644 --- a/base/src/timer_event_handler.h +++ b/base/src/timer_event_handler.h @@ -55,7 +55,7 @@ private: uint32_t interval_; EventReactor* reactor_; - std::unique_ptr handler_; + std::shared_ptr handler_; TimerCallback callback_; }; diff --git a/base/test/unittest/common/utils_datetime_test.cpp b/base/test/unittest/common/utils_datetime_test.cpp index 4cc88a53daea22ea66cc9e19be914824239a3fdd..c10c2194b25cbf17a1004aa738918abb570e0497 100644 --- a/base/test/unittest/common/utils_datetime_test.cpp +++ b/base/test/unittest/common/utils_datetime_test.cpp @@ -91,6 +91,8 @@ HWTEST_F(UtilsDateTimeTest, testTime001, TestSize.Level0) info.tm_isdst = 0; second2 = GetSecondsSince1970ToPointTime(info); EXPECT_EQ(-1, second2); + int64_t ret2 = GetSecondsBetween(curTime, info); + EXPECT_TRUE(ret2 = -1); } /* diff --git a/base/test/unittest/common/utils_directory_test.cpp b/base/test/unittest/common/utils_directory_test.cpp index d8d0f95d5201177123dc701f08ca484ec1f2fbfd..3ac71486c6e4857ed41264b5ffcd8ed56ef3a88f 100644 --- a/base/test/unittest/common/utils_directory_test.cpp +++ b/base/test/unittest/common/utils_directory_test.cpp @@ -12,11 +12,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include + #include "directory_ex.h" +#include +#include #include #include #include + using namespace testing::ext; using namespace std; @@ -212,6 +215,73 @@ HWTEST_F(UtilsDirectoryTest, testRemoveFile001, TestSize.Level0) EXPECT_EQ(ret, true); } +/* + * @tc.name: testRemoveFile002 + * @tc.desc: Remove soft link file. + */ +HWTEST_F(UtilsDirectoryTest, testRemoveFile002, TestSize.Level0) +{ + string dirpath = "/data/test_dir"; + bool ret = ForceCreateDirectory(dirpath); + EXPECT_EQ(ret, true); + + string targetname = "/data/test_target.txt"; + FILE *fp = fopen(targetname.c_str(), "w"); + if (NULL != fp) { + fclose(fp); + } + + // symlink to a directory + string linkpath = "/data/test_symlink_dir"; + int res = symlink(dirpath.c_str(), linkpath.c_str()); + EXPECT_EQ(res, 0); + + ret = ForceRemoveDirectory(linkpath); + EXPECT_EQ(ret, true); + + // Target dir is not removed. + ret = faccessat(AT_FDCWD, dirpath.c_str(), F_OK, AT_SYMLINK_NOFOLLOW); + EXPECT_EQ(ret, 0); + + // symlink to a file + string filename = dirpath + "/test.txt"; + res = symlink(targetname.c_str(), filename.c_str()); + EXPECT_EQ(res, 0); + + ret = ForceRemoveDirectory(dirpath); + EXPECT_EQ(ret, true); + + // Target file is not removed. + ret = faccessat(AT_FDCWD, targetname.c_str(), F_OK, AT_SYMLINK_NOFOLLOW); + EXPECT_EQ(ret, 0); + + ret = RemoveFile(targetname); + EXPECT_EQ(ret, true); +} + +/* + * @tc.name: testRemoveFile003 + * @tc.desc: Remove dangling soft link file. + */ +HWTEST_F(UtilsDirectoryTest, testRemoveFile003, TestSize.Level0) +{ + string dirpath = "/data/test_dir"; + bool ret = ForceCreateDirectory(dirpath); + EXPECT_EQ(ret, true); + + // symlink to a file + string targetname = "/data/nonexisted.txt"; + string filename = dirpath + "/test.txt"; + int res = symlink(targetname.c_str(), filename.c_str()); + EXPECT_EQ(res, 0); + + ret = ForceRemoveDirectory(dirpath); + EXPECT_EQ(ret, true); + + ret = RemoveFile(targetname); + EXPECT_EQ(ret, true); +} + /* * @tc.name: testGetFolderSize001 * @tc.desc: directory unit test diff --git a/base/test/unittest/common/utils_parcel_test.cpp b/base/test/unittest/common/utils_parcel_test.cpp index ff8bbbfe7ba5e915a64596cab53db8480e4868b6..46653d85cf8b93d24b796ea7482c196429e5fef6 100644 --- a/base/test/unittest/common/utils_parcel_test.cpp +++ b/base/test/unittest/common/utils_parcel_test.cpp @@ -1307,12 +1307,6 @@ HWTEST_F(UtilsParcelTest, test_parcel_Data_Structure_002, TestSize.Level0) result = parcel.WriteBufferAddTerminator(static_cast(str.data()), 0, sizeof(char)); EXPECT_EQ(false, result); - result = parcel.WriteBuffer(static_cast(strOverflow.data()), SIZE_MAX); - EXPECT_EQ(false, result); - result = parcel.WriteBufferAddTerminator(static_cast(strOverflow.data()), - SIZE_MAX, sizeof(char)); - EXPECT_EQ(false, result); - result = parcel.WriteBuffer(static_cast(strWriteFail.data()), strWriteFail.length()); EXPECT_EQ(false, result); result = parcel.WriteBufferAddTerminator(static_cast(strWriteFail.data()), diff --git a/base/test/unittest/rust/rust_utils_ashmem_test.rs b/base/test/unittest/rust/rust_utils_ashmem_test.rs index b7816522f292dc9b1fcabdda32e1ffdb021facf2..0187a503e5f3e05eabbb47ea89fca876397b7327 100644 --- a/base/test/unittest/rust/rust_utils_ashmem_test.rs +++ b/base/test/unittest/rust/rust_utils_ashmem_test.rs @@ -290,7 +290,6 @@ fn test_ashmem_ffi_invalid_006() ashmem.CloseAshmem(); } - #[test] fn test_ashmem_write_read_001() { @@ -299,6 +298,8 @@ fn test_ashmem_write_read_001() let ashmem = ashmem.unwrap(); assert_eq!(ashmem.get_ashmem_size(), MEMORY_SIZE); + assert_eq!(ashmem.get_protection(), ashmem::PROT_READ | ashmem::PROT_WRITE | ashmem::PROT_EXEC); // default protection mask. + assert_ne!(ashmem.get_ashmem_fd(), -1); assert!(ashmem.map_ashmem(ashmem::PROT_READ | ashmem::PROT_WRITE)); diff --git a/bundle.json b/bundle.json index 19d708d1d512dab454ef2b3245484159c7bccbc2..4366b17f3a2b7b01632d8a22924cd58e4428e730 100644 --- a/bundle.json +++ b/bundle.json @@ -16,7 +16,10 @@ "name": "c_utils", "subsystem": "commonlibrary", "adapted_system_type": [ "standard" ], - "features":[ "c_utils_feature_coverage = false" ], + "features":[ + "c_utils_feature_coverage = false", + "c_utils_feature_intsan = true" + ], "deps": { "components": [ "hilog"