From 8a1bbd074e7394cc86309c2da8a5377870b639da Mon Sep 17 00:00:00 2001 From: Francis Tsui Date: Thu, 23 Jul 2026 14:54:23 -0700 Subject: [PATCH] Verify custom save path is an absolute path. PiperOrigin-RevId: 952971544 --- internal/base/files.cc | 4 ++++ internal/base/files.h | 5 +++++ internal/base/files_test.cc | 16 ++++++++++++++++ sharing/BUILD | 1 + sharing/nearby_sharing_service_impl_test.cc | 12 ++++++++---- sharing/nearby_sharing_settings.cc | 12 +++++++++++- 6 files changed, 45 insertions(+), 5 deletions(-) diff --git a/internal/base/files.cc b/internal/base/files.cc index 2c76f78e..dc94ac08 100644 --- a/internal/base/files.cc +++ b/internal/base/files.cc @@ -142,4 +142,8 @@ std::optional Files::GetAvailableDiskSpaceInBytes( return std::nullopt; } +bool Files::IsAbsolutePath(const FilePath& path) { + return path.path_.is_absolute(); +} + } // namespace nearby diff --git a/internal/base/files.h b/internal/base/files.h index bf708786..11294728 100644 --- a/internal/base/files.h +++ b/internal/base/files.h @@ -75,6 +75,11 @@ class Files { // determined. static std::optional GetAvailableDiskSpaceInBytes( const FilePath& path); + + // Returns true if the path is an absolute path. + // On Posix systems, this is a path that starts with a `/`. + // On Windows, this is a path that starts with a drive letter or a UNC path. + static bool IsAbsolutePath(const FilePath& path); }; } // namespace nearby diff --git a/internal/base/files_test.cc b/internal/base/files_test.cc index 735b025d..6d861945 100644 --- a/internal/base/files_test.cc +++ b/internal/base/files_test.cc @@ -46,5 +46,21 @@ TEST(FilesTest, CreateHardLinkSuccess) { Files::RemoveFile(target); } +#if defined(_WIN32) +TEST(FilesTest, IsAbsolutePathWindows) { + EXPECT_TRUE(Files::IsAbsolutePath(FilePath("C:\\Users\\test\\file.txt"))); + EXPECT_TRUE(Files::IsAbsolutePath(FilePath("\\\\server\\share\\file.txt"))); + EXPECT_FALSE(Files::IsAbsolutePath(FilePath("file.txt"))); + EXPECT_FALSE(Files::IsAbsolutePath(FilePath("C:Users\\test\\file.txt"))); +} +#endif + +#if defined(__linux__) || defined(__APPLE__) +TEST(FilesTest, IsAbsolutePathPosix) { + EXPECT_TRUE(Files::IsAbsolutePath(FilePath("/Users/test/file.txt"))); + EXPECT_FALSE(Files::IsAbsolutePath(FilePath("file.txt"))); +} +#endif + } // namespace } // namespace nearby diff --git a/sharing/BUILD b/sharing/BUILD index b666406e..b6132a68 100644 --- a/sharing/BUILD +++ b/sharing/BUILD @@ -393,6 +393,7 @@ cc_library( "//connections/implementation/analytics:analytics_recorder_impl", "//internal/base", "//internal/base:file_path", + "//internal/base:files", "//internal/flags:nearby_flags", "//internal/network:url", "//internal/platform:base", diff --git a/sharing/nearby_sharing_service_impl_test.cc b/sharing/nearby_sharing_service_impl_test.cc index 7c71d8b4..c4a3eefb 100644 --- a/sharing/nearby_sharing_service_impl_test.cc +++ b/sharing/nearby_sharing_service_impl_test.cc @@ -5231,7 +5231,9 @@ TEST_F(NearbySharingServiceImplTest, InitiatePairingSuccess) { EXPECT_EQ(frame->v1().bindings().binding_request().type(), service::proto::BindingRequest::FILESYNC); - preference_manager_.SetString(PrefNames::kCustomSavePath, "Downloads"); + FilePath custom_save_path = Files::GetTemporaryDirectory(); + preference_manager_.SetString(PrefNames::kCustomSavePath, + custom_save_path.ToString()); Frame binding_response_frame; binding_response_frame.set_version(Frame::V1); binding_response_frame.mutable_v1()->set_type( @@ -5261,7 +5263,7 @@ TEST_F(NearbySharingServiceImplTest, InitiatePairingSuccess) { expected_binding.set_binding_id(kBindingId); expected_binding.set_source_name(kDeviceName); expected_binding.set_destination_directory( - FilePath("Downloads").append(FilePath(kDeviceName)).ToString()); + FilePath(custom_save_path).append(FilePath(kDeviceName)).ToString()); expected_binding.set_source_device_type( sync::SyncBinding::SOURCE_DEVICE_TYPE_PHONE); EXPECT_THAT(binding->sync_bindings(0), EqualsProto(expected_binding)); @@ -5336,7 +5338,9 @@ TEST_F(NearbySharingServiceImplTest, EXPECT_EQ(frame->v1().bindings().binding_request().type(), service::proto::BindingRequest::FILESYNC); - preference_manager_.SetString(PrefNames::kCustomSavePath, "Downloads"); + FilePath custom_save_path = Files::GetTemporaryDirectory(); + preference_manager_.SetString(PrefNames::kCustomSavePath, + custom_save_path.ToString()); Frame binding_response_frame; binding_response_frame.set_version(Frame::V1); binding_response_frame.mutable_v1()->set_type( @@ -5363,7 +5367,7 @@ TEST_F(NearbySharingServiceImplTest, expected_binding.set_binding_id(kBindingId); expected_binding.set_source_name(kDeviceName); expected_binding.set_destination_directory( - FilePath("Downloads").append(FilePath(kDeviceName)).ToString()); + FilePath(custom_save_path).append(FilePath(kDeviceName)).ToString()); expected_binding.set_source_device_type( sync::SyncBinding::SOURCE_DEVICE_TYPE_PHONE); EXPECT_THAT(binding->sync_bindings(0), EqualsProto(expected_binding)); diff --git a/sharing/nearby_sharing_settings.cc b/sharing/nearby_sharing_settings.cc index 8d915aa9..8bee5def 100644 --- a/sharing/nearby_sharing_settings.cc +++ b/sharing/nearby_sharing_settings.cc @@ -26,6 +26,8 @@ #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "absl/time/time.h" +#include "internal/base/file_path.h" +#include "internal/base/files.h" #include "internal/platform/clock.h" #include "internal/platform/implementation/device_info.h" #include "internal/platform/task_runner.h" @@ -184,8 +186,12 @@ void NearbyShareSettings::RestoreFallbackVisibility() { } std::string NearbyShareSettings::GetCustomSavePath() const { - return preference_manager_.GetString( + std::string custom_save_path = preference_manager_.GetString( PrefNames::kCustomSavePath, device_info_.GetDownloadPath().ToString()); + if (Files::IsAbsolutePath(FilePath(custom_save_path))) { + return custom_save_path; + } + return device_info_.GetDownloadPath().ToString(); } SyncBindingPrefs NearbyShareSettings::GetSyncBindingPrefs() const { @@ -347,6 +353,10 @@ void NearbyShareSettings::SetFallbackVisibility(DeviceVisibility visibility) { void NearbyShareSettings::SetCustomSavePathAsync( absl::string_view save_path, const std::function& callback) { + if (!Files::IsAbsolutePath(FilePath(save_path))) { + callback(); + return; + } absl::MutexLock lock(mutex_); preference_manager_.SetString(PrefNames::kCustomSavePath, save_path); callback();