1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/chrome_cleaner/os/disk_util.h"
6
7 #include <windows.h>
8
9 #include <shlobj.h>
10
11 #include "base/bind.h"
12 #include "base/callback_helpers.h"
13 #include "base/command_line.h"
14 #include "base/files/file.h"
15 #include "base/files/file_path.h"
16 #include "base/files/file_util.h"
17 #include "base/files/scoped_temp_dir.h"
18 #include "base/logging.h"
19 #include "base/path_service.h"
20 #include "base/process/launch.h"
21 #include "base/stl_util.h"
22 #include "base/strings/strcat.h"
23 #include "base/strings/string_util.h"
24 #include "base/strings/stringprintf.h"
25 #include "base/strings/utf_string_conversions.h"
26 #include "base/test/scoped_path_override.h"
27 #include "base/test/test_shortcut_win.h"
28 #include "base/test/test_timeouts.h"
29 #include "base/unguessable_token.h"
30 #include "base/win/windows_version.h"
31 #include "chrome/chrome_cleaner/os/file_path_sanitization.h"
32 #include "chrome/chrome_cleaner/os/layered_service_provider_wrapper.h"
33 #include "chrome/chrome_cleaner/os/system_util_cleaner.h"
34 #include "chrome/chrome_cleaner/strings/string_util.h"
35 #include "chrome/chrome_cleaner/test/test_executables.h"
36 #include "chrome/chrome_cleaner/test/test_file_util.h"
37 #include "chrome/chrome_cleaner/test/test_layered_service_provider.h"
38 #include "chrome/chrome_cleaner/test/test_strings.h"
39 #include "chrome/chrome_cleaner/test/test_util.h"
40 #include "testing/gmock/include/gmock/gmock.h"
41 #include "testing/gtest/include/gtest/gtest.h"
42
43 namespace chrome_cleaner {
44
45 namespace {
46
47 // A path name under program files.
48 const wchar_t kProgramFilesBaseName[] = L"Foo";
49
50 // Keep these digests in sorted order.
51 const char* const kFileContentDigests[] = {
52 "02544E052F29BBA79C81243EC63B43B6CD85B185461928E65BFF501346C62A75",
53 "04614470DDF4939091F5EC4A13C92A9EAAACF07CA5C3F713E792E2D21CD24075",
54 // Hash for content: |kFileContent2|.
55 "82E0B92772BC0DA59AAB0B9231AA006FB37B4F99EC3E853C5A62786A1C7215BD",
56 "94F7BDF53CDFDE7AA5E5C90BCDA6793B7377CE39E2591ABC758EBAE8072A275C",
57 // Hash for content: |kFileContent1|.
58 "BD283E41A3672B6BDAA574F8BD7176F8BCA95BD81383CDE32AA6D78B1DB0E371"};
59
60 const wchar_t kFileName1[] = L"Filename one";
61 const wchar_t kFileName2[] = L"Filename two";
62 const wchar_t kFileName3[] = L"Third filename";
63 const wchar_t kLongFileName1[] = L"Long File Name.bla";
64 const wchar_t kLongFileName2[] = L"Other Long File Name.bla";
65 const char kFileContent1[] = "This is the file content.";
66 const char kFileContent2[] = "Hi!";
67 const char kFileContent3[] = "Hello World!";
68
69 const internal::FileInformation kFileInformation1(L"some/path/something.tmp",
70 "3/1/2016",
71 "3/3/2016",
72 "somedigest1234",
73 9876,
74 L"Company Name",
75 L"CNShort",
76 L"Product Name",
77 L"PNShort",
78 L"Internal Name",
79 L"Something_Original.tmp",
80 L"Very descriptive",
81 L"42.1.2");
82
83 const wchar_t kFileInformation1ExpectedString[] =
84 L"path = 'some/path/something.tmp', file_creation_date = "
85 L"'3/1/2016', file_last_modified_date = '3/3/2016', digest = "
86 L"'somedigest1234', size = '9876', company_name = 'Company Name', "
87 L"company_short_name = 'CNShort', product_name = 'Product Name', "
88 L"product_short_name = 'PNShort', internal_name = 'Internal Name', "
89 L"original_filename = 'Something_Original.tmp', file_description = 'Very "
90 L"descriptive', file_version = '42.1.2', active_file = '0'";
91
92 // All potential format of content that get from registry. %ls will be replaced
93 // by the executable path.
94 // clang-format off
95 const wchar_t* kMockRegistryContents[] = {
96 // Straight path as is.
97 L"%ls",
98 L"\"%ls\"",
99 // With command line arguments.
100 L"%ls -s",
101 L"\"%ls\" -s",
102 L"\"%ls -s\"",
103 // Using rundll.
104 L"C:\\Windows\\SysWow64\\rundll32 %ls",
105 L"C:\\Windows\\SysWow64\\rundll32 \"%ls\"",
106 // Using rundll with args.
107 L"C:\\Windows\\SysWow64\\rundll32.exe %ls,OpenAs_RunDLL %%1",
108 L"C:\\Windows\\SysWow64\\rundll32.exe \"%ls\",OpenAs_RunDLL %%1",
109 L"C:\\Windows\\SysWow64\\rundll32.exe \"%ls,OpenAs_RunDLL\" %%1",
110 L"C:\\Windows\\SysWow64\\rundll32.exe %ls a1 a2,OpenAs_RunDLL %%1",
111 L"C:\\Windows\\SysWow64\\rundll32.exe \"%ls\" a1,OpenAs_RunDLL %%1",
112 L"C:\\Windows\\SysWow64\\rundll32.exe \"%ls a1,OpenAs_RunDLL\" %%1",
113 L"C:\\Windows\\System32\\rundll32 %ls",
114 // Rundll without a path.
115 L"rundll32.exe %ls a1 a2,OpenAs_RunDLL %%1",
116 L"rundll32.exe \"%ls\" -s %%1",
117 L"rundll32.exe \"%ls -s\" %%1",
118 // Rundll without extension.
119 L"C:\\Windows\\SysWow64\\rundll32 %ls a1 a2,OpenAs_RunDLL %%1",
120 L"C:\\Windows\\SysWow64\\rundll32 \"%ls\" -s %%1",
121 L"C:\\Windows\\SysWow64\\rundll32 \"%ls -s\" %%1"};
122 // clang-format on
123
LaunchTestProcess(const wchar_t * executable,const char * action,bool wait)124 bool LaunchTestProcess(const wchar_t* executable,
125 const char* action,
126 bool wait) {
127 base::FilePath executable_path(executable);
128 base::CommandLine command_line(executable_path);
129 command_line.AppendSwitch(action);
130 base::LaunchOptions options = base::LaunchOptions();
131 options.wait = wait;
132 return base::LaunchProcess(command_line, options).IsValid();
133 }
134
DoesVolumeSupportNamedStreams(const base::FilePath & path)135 bool DoesVolumeSupportNamedStreams(const base::FilePath& path) {
136 std::vector<std::wstring> components;
137 path.GetComponents(&components);
138 DCHECK(!components.empty());
139 std::wstring& drive = components[0];
140 drive += L'\\';
141 DWORD system_flags = 0;
142 if (::GetVolumeInformation(drive.c_str(), nullptr, 0, nullptr, nullptr,
143 &system_flags, nullptr, 0) != TRUE) {
144 PLOG(ERROR) << "Cannot retrieve drive information: '" << path.value()
145 << "'.";
146 return false;
147 }
148
149 return (system_flags & FILE_NAMED_STREAMS) != 0;
150 }
151
CreateProgramPathsAndFiles(const base::FilePath & temp_dir_path,base::FilePath * program_path,base::FilePath * spaced_program_path)152 void CreateProgramPathsAndFiles(const base::FilePath& temp_dir_path,
153 base::FilePath* program_path,
154 base::FilePath* spaced_program_path) {
155 DCHECK(program_path);
156 DCHECK(spaced_program_path);
157 base::FilePath folder;
158 base::FilePath file_path;
159 base::FilePath spaced_folder;
160 base::FilePath spaced_file_path;
161
162 ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir_path, L"folder", &folder));
163 ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir_path, L" spaced folder",
164 &spaced_folder));
165
166 ASSERT_TRUE(CreateTemporaryFileInDir(folder, &file_path));
167 ASSERT_TRUE(CreateTemporaryFileInDir(spaced_folder, &spaced_file_path));
168
169 *program_path = file_path;
170 *spaced_program_path = spaced_file_path;
171 }
172
173 // Substitutes |registry_path| into each entry in the mock registry in turn
174 // and passes the result to ExtractExecutablePathFromRegistryContent to get a
175 // file path. Returns success if every file path matches |expected_path|.
ExtractExecutablePathFromMockRegistryAndExpect(const std::wstring & registry_path,const base::FilePath & expected_path)176 ::testing::AssertionResult ExtractExecutablePathFromMockRegistryAndExpect(
177 const std::wstring& registry_path,
178 const base::FilePath& expected_path) {
179 for (const std::wstring& registry_content : kMockRegistryContents) {
180 std::wstring full_registry_content =
181 base::StringPrintf(registry_content.c_str(), registry_path.c_str());
182 base::FilePath extracted_path =
183 ExtractExecutablePathFromRegistryContent(full_registry_content);
184 if (!PathEqual(expected_path, extracted_path)) {
185 return ::testing::AssertionFailure()
186 << expected_path.value() << " != " << extracted_path.value()
187 << ", full_registry_content = " << full_registry_content;
188 }
189 }
190 return ::testing::AssertionSuccess();
191 }
192
193 // Return that the sample DLL is whitelisted and all other files are not.
WhitelistSampleDLL(const base::FilePath & path)194 bool WhitelistSampleDLL(const base::FilePath& path) {
195 return PathEqual(path, GetSampleDLLPath());
196 }
197
198 } // namespace
199
TEST(DiskUtilTests,GetX64ProgramFilePath)200 TEST(DiskUtilTests, GetX64ProgramFilePath) {
201 base::FilePath x64_program_files =
202 GetX64ProgramFilesPath(base::FilePath(kProgramFilesBaseName));
203 if (base::win::OSInfo::GetArchitecture() ==
204 base::win::OSInfo::X86_ARCHITECTURE) {
205 EXPECT_TRUE(x64_program_files.empty());
206 return;
207 }
208
209 EXPECT_FALSE(x64_program_files.empty());
210 EXPECT_NE(x64_program_files,
211 ExpandSpecialFolderPath(CSIDL_PROGRAM_FILES,
212 base::FilePath(kProgramFilesBaseName)));
213 }
214
TEST(DiskUtilTests,PathContainsWildcards)215 TEST(DiskUtilTests, PathContainsWildcards) {
216 EXPECT_FALSE(PathContainsWildcards(base::FilePath(L"c:\\foo.txt")));
217 EXPECT_FALSE(PathContainsWildcards(base::FilePath(L"c:\\bar\\foo.txt")));
218 EXPECT_TRUE(PathContainsWildcards(base::FilePath(L"c:\\foo.t?t")));
219 EXPECT_TRUE(PathContainsWildcards(base::FilePath(L"c:\\foo.t*t")));
220 EXPECT_TRUE(
221 PathContainsWildcards(base::FilePath(L"c:\\"
222 LR"(???)"
223 L"*\\foo.txt")));
224 EXPECT_TRUE(PathContainsWildcards(base::FilePath(L"*:\\")));
225 EXPECT_FALSE(PathContainsWildcards(base::FilePath(L"foo.txt")));
226 EXPECT_TRUE(PathContainsWildcards(base::FilePath(LR"(foo.???)")));
227 }
228
TEST(DiskUtilTests,CollectMatchingPathsMultipleWildcards)229 TEST(DiskUtilTests, CollectMatchingPathsMultipleWildcards) {
230 base::ScopedTempDir temp_dir;
231 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
232
233 // Create files and folders under |temp_dir| and add them to |expected_files|.
234 std::set<base::FilePath> expected_files;
235
236 base::ScopedTempDir sub_dir1;
237 ASSERT_TRUE(sub_dir1.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
238
239 base::ScopedTempDir sub_dir2;
240 ASSERT_TRUE(sub_dir2.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
241
242 base::FilePath sub_dir1_file_path1(sub_dir1.GetPath().Append(kFileName1));
243 base::File sub_dir1_file1(sub_dir1_file_path1, base::File::FLAG_CREATE);
244 ASSERT_TRUE(base::PathExists(sub_dir1_file_path1));
245
246 base::FilePath sub_dir1_file_path2(sub_dir1.GetPath().Append(kFileName2));
247 base::File sub_dir1_file2(sub_dir1_file_path2, base::File::FLAG_CREATE);
248 ASSERT_TRUE(base::PathExists(sub_dir1_file_path2));
249
250 base::FilePath sub_dir1_file_path3(sub_dir1.GetPath().Append(kFileName3));
251 base::File sub_dir1_file3(sub_dir1_file_path3, base::File::FLAG_CREATE);
252 ASSERT_TRUE(base::PathExists(sub_dir1_file_path3));
253
254 base::FilePath sub_dir2_file_path1(sub_dir2.GetPath().Append(kFileName1));
255 base::File sub_dir2_file1(sub_dir2_file_path1, base::File::FLAG_CREATE);
256 ASSERT_TRUE(base::PathExists(sub_dir2_file_path1));
257
258 base::FilePath sub_dir2_file_path2(sub_dir2.GetPath().Append(kFileName2));
259 base::File sub_dir2_file2(sub_dir2_file_path2, base::File::FLAG_CREATE);
260 ASSERT_TRUE(base::PathExists(sub_dir2_file_path2));
261
262 expected_files.insert(sub_dir1_file_path1);
263 expected_files.insert(sub_dir1_file_path2);
264 expected_files.insert(sub_dir2_file_path1);
265 expected_files.insert(sub_dir2_file_path2);
266
267 base::FilePath wildcard_path1(
268 temp_dir.GetPath().Append(L"*").Append(L"Filename*"));
269 std::vector<base::FilePath> matches;
270 CollectMatchingPaths(wildcard_path1, &matches);
271 EXPECT_THAT(expected_files, testing::UnorderedElementsAreArray(matches));
272 }
273
TEST(DiskUtilTests,CollectMatchingPathsDriveWildcard)274 TEST(DiskUtilTests, CollectMatchingPathsDriveWildcard) {
275 std::vector<base::FilePath> matches;
276
277 // The drive could not be enumerated, thus no file will exists..
278 base::FilePath wildcard_path1(L"*:\\test");
279 CollectMatchingPaths(wildcard_path1, &matches);
280 EXPECT_TRUE(matches.empty());
281
282 base::FilePath wildcard_path2(L"*:\\");
283 CollectMatchingPaths(wildcard_path2, &matches);
284 EXPECT_TRUE(matches.empty());
285 }
286
TEST(DiskUtilTests,CollectMatchingPathsDirectoryWildcard)287 TEST(DiskUtilTests, CollectMatchingPathsDirectoryWildcard) {
288 base::ScopedTempDir temp_dir;
289 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
290
291 // Create files and folders under |temp_dir| and add them to |expected_files|.
292 std::set<base::FilePath> expected_files;
293
294 base::ScopedTempDir sub_dir1;
295 ASSERT_TRUE(sub_dir1.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
296
297 base::ScopedTempDir sub_dir2;
298 ASSERT_TRUE(sub_dir2.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
299
300 base::FilePath sub_dir1_file_path1(sub_dir1.GetPath().Append(kFileName1));
301 base::File sub_dir1_file1(sub_dir1_file_path1, base::File::FLAG_CREATE);
302 ASSERT_TRUE(base::PathExists(sub_dir1_file_path1));
303
304 base::FilePath sub_dir1_file_path2(sub_dir1.GetPath().Append(kFileName2));
305 base::File sub_dir1_file2(sub_dir1_file_path2, base::File::FLAG_CREATE);
306 ASSERT_TRUE(base::PathExists(sub_dir1_file_path2));
307
308 base::FilePath sub_dir1_file_path3(sub_dir1.GetPath().Append(kFileName3));
309 base::File sub_dir1_file3(sub_dir1_file_path3, base::File::FLAG_CREATE);
310 ASSERT_TRUE(base::PathExists(sub_dir1_file_path3));
311
312 base::FilePath sub_dir2_file_path1(sub_dir2.GetPath().Append(kFileName1));
313 base::File sub_dir2_file1(sub_dir2_file_path1, base::File::FLAG_CREATE);
314 ASSERT_TRUE(base::PathExists(sub_dir2_file_path1));
315
316 base::FilePath sub_dir2_file_path2(sub_dir2.GetPath().Append(kFileName2));
317 base::File sub_dir2_file2(sub_dir2_file_path2, base::File::FLAG_CREATE);
318 ASSERT_TRUE(base::PathExists(sub_dir2_file_path2));
319
320 expected_files.insert(sub_dir1_file_path1);
321 expected_files.insert(sub_dir2_file_path1);
322 base::FilePath wildcard_path3(
323 temp_dir.GetPath().Append(L"*").Append(kFileName1));
324 std::vector<base::FilePath> matches;
325 CollectMatchingPaths(wildcard_path3, &matches);
326 EXPECT_THAT(expected_files, testing::UnorderedElementsAreArray(matches));
327 }
328
TEST(DiskUtilTests,CollectMatchingPathsMultipleFileWildcards)329 TEST(DiskUtilTests, CollectMatchingPathsMultipleFileWildcards) {
330 base::ScopedTempDir temp_dir;
331 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
332
333 base::ScopedTempDir sub_dir1;
334 ASSERT_TRUE(sub_dir1.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
335
336 base::ScopedTempDir sub_dir2;
337 ASSERT_TRUE(sub_dir2.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
338
339 base::FilePath sub_dir1_file_path1(sub_dir1.GetPath().Append(kFileName1));
340 base::File sub_dir1_file1(sub_dir1_file_path1, base::File::FLAG_CREATE);
341 ASSERT_TRUE(base::PathExists(sub_dir1_file_path1));
342
343 base::FilePath sub_dir1_file_path2(sub_dir1.GetPath().Append(kFileName2));
344 base::File sub_dir1_file2(sub_dir1_file_path2, base::File::FLAG_CREATE);
345 ASSERT_TRUE(base::PathExists(sub_dir1_file_path2));
346
347 base::FilePath sub_dir1_file_path3(sub_dir1.GetPath().Append(kFileName3));
348 base::File sub_dir1_file3(sub_dir1_file_path3, base::File::FLAG_CREATE);
349 ASSERT_TRUE(base::PathExists(sub_dir1_file_path3));
350
351 base::FilePath sub_dir2_file_path1(sub_dir2.GetPath().Append(kFileName1));
352 base::File sub_dir2_file1(sub_dir2_file_path1, base::File::FLAG_CREATE);
353 ASSERT_TRUE(base::PathExists(sub_dir2_file_path1));
354
355 base::FilePath sub_dir2_file_path2(sub_dir2.GetPath().Append(kFileName2));
356 base::File sub_dir2_file2(sub_dir2_file_path2, base::File::FLAG_CREATE);
357 ASSERT_TRUE(base::PathExists(sub_dir2_file_path2));
358
359 // Create files and folders under |temp_dir| and add them to |expected_files|.
360 std::set<base::FilePath> expected_files;
361 expected_files.insert(sub_dir1_file_path3);
362 base::FilePath wildcard_path4(
363 temp_dir.GetPath().Append(L"*").Append(L"*Third*"));
364 std::vector<base::FilePath> matches;
365 CollectMatchingPaths(wildcard_path4, &matches);
366 EXPECT_THAT(expected_files, testing::UnorderedElementsAreArray(matches));
367 }
368
TEST(DiskUtilTests,CollectMatchingPathsNoWildcards)369 TEST(DiskUtilTests, CollectMatchingPathsNoWildcards) {
370 base::ScopedTempDir temp_dir;
371 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
372
373 base::ScopedTempDir sub_dir;
374 ASSERT_TRUE(sub_dir.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
375
376 base::FilePath sub_dir_file_path1(sub_dir.GetPath().Append(kFileName1));
377 base::File sub_dir_file1(sub_dir_file_path1, base::File::FLAG_CREATE);
378 ASSERT_TRUE(base::PathExists(sub_dir_file_path1));
379
380 base::FilePath sub_dir_file_path2(sub_dir.GetPath().Append(kFileName2));
381 base::File sub_dir_file2(sub_dir_file_path2, base::File::FLAG_CREATE);
382 ASSERT_TRUE(base::PathExists(sub_dir_file_path2));
383
384 base::FilePath sub_dir_file_path3(sub_dir.GetPath().Append(kFileName3));
385 base::File sub_dir_file3(sub_dir_file_path3, base::File::FLAG_CREATE);
386 ASSERT_TRUE(base::PathExists(sub_dir_file_path3));
387
388 // Create files and folders under |temp_dir| and add them to |expected_files|.
389 std::vector<base::FilePath> matches;
390
391 base::FilePath no_wildcard_path(sub_dir.GetPath());
392 CollectMatchingPaths(no_wildcard_path, &matches);
393 EXPECT_EQ(1UL, matches.size());
394 EXPECT_TRUE(base::Contains(matches, sub_dir.GetPath()));
395 }
396
TEST(DiskUtilTests,CollectExecutableMatchingPaths)397 TEST(DiskUtilTests, CollectExecutableMatchingPaths) {
398 base::ScopedTempDir temp_dir;
399 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
400
401 base::FilePath subfolder1_path;
402 ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub1",
403 &subfolder1_path));
404
405 base::FilePath subfolder2_path;
406 ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub2",
407 &subfolder2_path));
408
409 base::FilePath subfolder3_path(subfolder2_path.Append(L"folder.exe"));
410 ASSERT_TRUE(base::CreateDirectory(subfolder3_path));
411
412 base::FilePath file_path1(subfolder1_path.Append(L"dummy1.exe"));
413 base::FilePath file_path2(subfolder1_path.Append(L"dummy2.exe"));
414 base::FilePath file_path3(subfolder2_path.Append(L"dummy3.exe"));
415 base::FilePath file_path4(subfolder2_path.Append(L"dummy4.exe"));
416 base::FilePath file_path5(subfolder2_path.Append(L"info.exe.txt"));
417 base::FilePath file_path6(subfolder3_path.Append(L"bad-mad.exe"));
418
419 CreateFileWithContent(file_path1, kFileContent1, sizeof(kFileContent1));
420 CreateFileWithContent(file_path2, kFileContent2, sizeof(kFileContent2));
421 CreateFileWithContent(file_path3, kFileContent3, sizeof(kFileContent3));
422 CreateFileWithContent(file_path4, kFileContent1, sizeof(kFileContent1));
423 CreateFileWithContent(file_path5, kFileContent2, sizeof(kFileContent2));
424 CreateFileWithContent(file_path6, kFileContent2, sizeof(kFileContent2));
425
426 base::FilePath wildcard_path(temp_dir.GetPath().Append(L"*\\*.exe"));
427 std::vector<base::FilePath> executable_matches;
428 CollectMatchingPaths(wildcard_path, &executable_matches);
429
430 EXPECT_THAT(executable_matches,
431 testing::ElementsAre(file_path1, file_path2, file_path3,
432 file_path4, subfolder3_path));
433 }
434
TEST(DiskUtilTests,CollectMultipleDotWildcardsMatchingPaths)435 TEST(DiskUtilTests, CollectMultipleDotWildcardsMatchingPaths) {
436 base::ScopedTempDir temp_dir;
437 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
438
439 base::FilePath subfolder1_path;
440 ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub1",
441 &subfolder1_path));
442
443 base::FilePath subfolder2_path;
444 ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub2",
445 &subfolder2_path));
446
447 base::FilePath subfolder3_path;
448 ASSERT_TRUE(base::CreateTemporaryDirInDir(subfolder2_path, L"folder.exe",
449 &subfolder3_path));
450
451 base::FilePath file_path1(subfolder1_path.Append(L"dummy1.tar.gz"));
452 base::FilePath file_path2(subfolder1_path.Append(L"dummy2.12.exe"));
453 base::FilePath file_path3(subfolder2_path.Append(L"dummy3.tar.gz"));
454 base::FilePath file_path4(subfolder2_path.Append(L"dummy4.12.exe"));
455 base::FilePath file_path5(subfolder2_path.Append(L"info.tar.gz.txt"));
456 base::FilePath file_path6(subfolder3_path.Append(L"bad-mad.exe"));
457
458 CreateFileWithContent(file_path1, kFileContent1, sizeof(kFileContent1));
459 CreateFileWithContent(file_path2, kFileContent2, sizeof(kFileContent2));
460 CreateFileWithContent(file_path3, kFileContent3, sizeof(kFileContent3));
461 CreateFileWithContent(file_path4, kFileContent1, sizeof(kFileContent1));
462 CreateFileWithContent(file_path5, kFileContent2, sizeof(kFileContent2));
463 CreateFileWithContent(file_path6, kFileContent2, sizeof(kFileContent2));
464
465 base::FilePath wildcard_path_tar_gz(
466 temp_dir.GetPath().Append(L"*\\*.tar.gz"));
467 std::vector<base::FilePath> executable_matches_tar_gz;
468 CollectMatchingPaths(wildcard_path_tar_gz, &executable_matches_tar_gz);
469
470 EXPECT_THAT(executable_matches_tar_gz,
471 testing::ElementsAre(file_path1, file_path3));
472
473 base::FilePath wildcard_path_all(temp_dir.GetPath().Append(L"*\\*.*.*"));
474 std::vector<base::FilePath> executable_matches_all;
475 CollectMatchingPaths(wildcard_path_all, &executable_matches_all);
476
477 EXPECT_THAT(executable_matches_all,
478 testing::ElementsAre(file_path1, file_path2, file_path3,
479 file_path4, file_path5));
480 }
481
TEST(DiskUtilTests,CollectEmptyDirMatchingPaths)482 TEST(DiskUtilTests, CollectEmptyDirMatchingPaths) {
483 base::ScopedTempDir temp_dir;
484 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
485
486 base::FilePath subfolder1_path;
487 ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub1",
488 &subfolder1_path));
489
490 base::FilePath subfolder2_path;
491 ASSERT_TRUE(base::CreateTemporaryDirInDir(temp_dir.GetPath(), L"sub2",
492 &subfolder2_path));
493
494 base::FilePath wildcard_path1(temp_dir.GetPath().Append(L"*\\dummy.exe"));
495 std::vector<base::FilePath> executable_matches;
496 CollectMatchingPaths(wildcard_path1, &executable_matches);
497 EXPECT_TRUE(executable_matches.empty());
498 }
499
TEST(DiskUtilTests,CollectCumulativeMatchingPaths)500 TEST(DiskUtilTests, CollectCumulativeMatchingPaths) {
501 base::ScopedTempDir temp_dir;
502 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
503
504 base::ScopedTempDir sub_dir1;
505 ASSERT_TRUE(sub_dir1.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
506
507 // Create files and folders under |sub_dirX| and add them to |expected_files|.
508 std::set<base::FilePath> expected_files;
509 base::FilePath sub_dir1_file_path1(sub_dir1.GetPath().Append(kFileName1));
510 base::File sub_dir1_file1(sub_dir1_file_path1, base::File::FLAG_CREATE);
511 ASSERT_TRUE(base::PathExists(sub_dir1_file_path1));
512 expected_files.insert(sub_dir1_file_path1);
513
514 base::FilePath sub_dir1_file_path2(sub_dir1.GetPath().Append(kFileName2));
515 base::File sub_dir1_file2(sub_dir1_file_path2, base::File::FLAG_CREATE);
516 ASSERT_TRUE(base::PathExists(sub_dir1_file_path2));
517 expected_files.insert(sub_dir1_file_path2);
518
519 base::ScopedTempDir sub_dir2;
520 ASSERT_TRUE(sub_dir2.CreateUniqueTempDirUnderPath(temp_dir.GetPath()));
521
522 base::FilePath sub_dir2_file_path1(sub_dir2.GetPath().Append(kFileName1));
523 base::File sub_dir2_file1(sub_dir2_file_path1, base::File::FLAG_CREATE);
524 ASSERT_TRUE(base::PathExists(sub_dir2_file_path1));
525 expected_files.insert(sub_dir2_file_path1);
526
527 base::FilePath wildcard_path1(sub_dir1.GetPath().Append(L"*"));
528 std::vector<base::FilePath> matches;
529 CollectMatchingPaths(wildcard_path1, &matches);
530 base::FilePath wildcard_path2(sub_dir2.GetPath().Append(L"*"));
531 CollectMatchingPaths(wildcard_path2, &matches);
532 EXPECT_THAT(expected_files, testing::UnorderedElementsAreArray(matches));
533 }
534
TEST(DiskUtilTests,PathHasActiveExtension)535 TEST(DiskUtilTests, PathHasActiveExtension) {
536 EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.exe")));
537 EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.exe ")));
538 EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.jpg.exe")));
539 EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.lnk")));
540 EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file")));
541 EXPECT_TRUE(PathHasActiveExtension(base::FilePath(L"C:\\file.lnk::$DATA")));
542
543 EXPECT_FALSE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.wvm")));
544 EXPECT_FALSE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.jpg")));
545 EXPECT_FALSE(PathHasActiveExtension(base::FilePath(L"C:\\uws\\file.jpg ")));
546 EXPECT_FALSE(PathHasActiveExtension(base::FilePath(L"C:\\file.txt::$DATA")));
547 }
548
TEST(DiskUtilTests,ExpandEnvPath)549 TEST(DiskUtilTests, ExpandEnvPath) {
550 ASSERT_TRUE(
551 ::SetEnvironmentVariable(L"CLEANER_TEST_VAR", L"CLEANER_TEST_VALUE"));
552 ASSERT_TRUE(::SetEnvironmentVariable(L"ROOT_TEST_VAR", L"c:\\root"));
553 base::FilePath test_path1(L"C:\\%CLEANER_TEST_VAR%\\test\\foo");
554 base::FilePath test_path2(L"%ROOT_TEST_VAR%\\test\\foo");
555 base::FilePath test_path3(
556 L"C:\\aa%CLEANER_TEST_VAR%bb\\test\\%%CLEANER_TEST_VAR%%");
557
558 base::FilePath expanded_path;
559 ExpandEnvPath(test_path1, &expanded_path);
560 EXPECT_EQ(L"C:\\CLEANER_TEST_VALUE\\test\\foo", expanded_path.value());
561
562 ExpandEnvPath(test_path2, &expanded_path);
563 EXPECT_EQ(L"c:\\root\\test\\foo", expanded_path.value());
564
565 ExpandEnvPath(test_path3, &expanded_path);
566 EXPECT_EQ(L"C:\\aaCLEANER_TEST_VALUEbb\\test\\%CLEANER_TEST_VALUE%",
567 expanded_path.value());
568 }
569
TEST(DiskUtilTests,ExpandWow64Path)570 TEST(DiskUtilTests, ExpandWow64Path) {
571 base::ScopedPathOverride windows_override(
572 CsidlToPathServiceKey(CSIDL_WINDOWS));
573 base::FilePath windows_folder;
574 ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_WINDOWS),
575 &windows_folder));
576
577 base::FilePath system_folder(windows_folder.Append(L"system32"));
578 base::ScopedPathOverride system_override(CsidlToPathServiceKey(CSIDL_SYSTEM),
579 system_folder, true, true);
580
581 base::FilePath native_folder(windows_folder.Append(L"sysnative"));
582 ASSERT_TRUE(base::CreateDirectory(native_folder));
583
584 base::FilePath file_path1(system_folder.Append(kFileName1));
585 base::FilePath file_path2(native_folder.Append(kFileName2));
586 base::FilePath file_path3_system(system_folder.Append(kFileName3));
587 base::FilePath file_path3_native(native_folder.Append(kFileName3));
588 CreateFileWithContent(file_path1, kFileContent1, sizeof(kFileContent1));
589 CreateFileWithContent(file_path2, kFileContent2, sizeof(kFileContent2));
590 CreateFileWithContent(file_path3_system, kFileContent3,
591 sizeof(kFileContent3));
592 CreateFileWithContent(file_path3_native, kFileContent3,
593 sizeof(kFileContent3));
594
595 base::FilePath expanded_file1;
596 ExpandWow64Path(file_path1, &expanded_file1);
597 ASSERT_TRUE(PathEqual(expanded_file1, file_path1));
598
599 base::FilePath expanded_file2;
600 ExpandWow64Path(file_path2, &expanded_file2);
601 ASSERT_TRUE(PathEqual(expanded_file2, file_path2));
602
603 base::FilePath expanded_file3;
604 ExpandWow64Path(file_path3_system, &expanded_file3);
605 ASSERT_TRUE(PathEqual(expanded_file3, file_path3_native));
606 }
607
TEST(DiskUtilTests,ComputeSHA256DigestOfPath)608 TEST(DiskUtilTests, ComputeSHA256DigestOfPath) {
609 base::ScopedTempDir temp_dir;
610 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
611
612 // Check the digest of an non-existing file.
613 base::FilePath file_path1(temp_dir.GetPath().Append(kFileName1));
614 std::string digest1;
615 EXPECT_FALSE(ComputeSHA256DigestOfPath(file_path1, &digest1));
616 EXPECT_TRUE(digest1.empty());
617
618 // Create an empty file and validate the digest.
619 base::FilePath file_path2(temp_dir.GetPath().Append(kFileName2));
620 base::File empty_file(file_path2, base::File::FLAG_CREATE);
621 empty_file.Close();
622
623 std::string digest2;
624 EXPECT_TRUE(ComputeSHA256DigestOfPath(file_path2, &digest2));
625 EXPECT_STREQ(
626 "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
627 digest2.c_str());
628
629 // Create a file with some content and validate the digest.
630 base::FilePath file_path3(temp_dir.GetPath().Append(kFileName3));
631 base::File valid_file(
632 file_path3, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
633 ASSERT_EQ(sizeof(kFileContent),
634 static_cast<size_t>(valid_file.WriteAtCurrentPos(
635 kFileContent, sizeof(kFileContent))));
636 valid_file.Close();
637
638 std::string digest3;
639 EXPECT_TRUE(ComputeSHA256DigestOfPath(file_path3, &digest3));
640 EXPECT_STREQ(
641 "BD283E41A3672B6BDAA574F8BD7176F8BCA95BD81383CDE32AA6D78B1DB0E371",
642 digest3.c_str());
643 }
644
TEST(DiskUtilTests,ComputeSHA256DigestOfPathOnBigFile)645 TEST(DiskUtilTests, ComputeSHA256DigestOfPathOnBigFile) {
646 base::ScopedTempDir temp_dir;
647 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
648
649 struct DigestInfo {
650 size_t size;
651 const char* digest;
652 } digests[] = {
653 {1, "CA978112CA1BBDCAFAC231B39A23DC4DA786EFF8147C4E72B9807785AFEE48BB"},
654 {2, "FB8E20FC2E4C3F248C60C39BD652F3C1347298BB977B8B4D5903B85055620603"},
655 {3, "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD"},
656 {100, "2AC123DCD759EEBABFA1B17C0332B88B3815EF3F95FBFCCEB5FAC07E233235BD"},
657 {128, "6C05BE2C4268843AE47E68E611277CE62C02153F2F4D2E1E2A1A4B44F766CF74"},
658 {1000,
659 "915E53A44C18B19BB06BA5B3F5FCAF1DC4651E8404C63425CFC6174E74659D87"},
660 {1023,
661 "6A6EE128AAC6B98D2697EED0A912AE264603D046B3CBFD5E7EA1D01C865474D9"},
662 {1024,
663 "DBA4A6315B76548B7A4DD079EF6AA29A7B34FA8B92C11668473441715C5F0AF5"},
664 {1025,
665 "2B4B65474580781B4DC0AB66B9A0F39B869DE5A44CF26DBA22AC0496760D4230"},
666 {4095,
667 "7413609B553226A9A8A3203A82062111DC1F98C24163E303774F27E4F615BFB2"},
668 {4096,
669 "BC45051AC426475F459EC0B0C88A6646D037B8DFB1B9FA3CA3EF9203CE33E283"},
670 {4097,
671 "A9145EB3812CA8F11A014029FEE1854FABB76D2FFEA680D0875F78FA786F58B8"},
672 {10000,
673 "5B92F844F0ED521B75688F4B6FF58E127711709613589EB6EC88FDFBBDC7DC63"}};
674
675 for (size_t offset = 0; offset < base::size(digests); ++offset) {
676 DigestInfo* info = &digests[offset];
677 DCHECK(info);
678
679 // Create a file and write some content into it.
680 base::FilePath file_path(temp_dir.GetPath().Append(kFileName1));
681 base::File valid_file(
682 file_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
683 for (size_t position = 0; position < info->size; ++position) {
684 char c = 'a' + (position % 26);
685 ASSERT_EQ(1, valid_file.WriteAtCurrentPos(&c, 1));
686 }
687 valid_file.Close();
688
689 std::string digest;
690 EXPECT_TRUE(ComputeSHA256DigestOfPath(file_path, &digest));
691 EXPECT_STREQ(info->digest, digest.c_str());
692 }
693 }
694
TEST(DiskUtilTests,ComputeSHA256DigestOfString)695 TEST(DiskUtilTests, ComputeSHA256DigestOfString) {
696 std::string digest_result;
697 std::string content(kFileContent2, sizeof(kFileContent2));
698 EXPECT_TRUE(ComputeSHA256DigestOfString(content, &digest_result));
699 EXPECT_STREQ(kFileContentDigests[2], digest_result.c_str());
700 }
701
TEST(DiskUtilTests,GetLayeredServiceProviders)702 TEST(DiskUtilTests, GetLayeredServiceProviders) {
703 // Make sure that running the OS implementation doesn't crash/dcheck.
704 LSPPathToGUIDs providers;
705 GetLayeredServiceProviders(LayeredServiceProviderWrapper(), &providers);
706 providers.clear();
707
708 // Make sure an empty test provider returns nothing
709 TestLayeredServiceProvider lsp;
710 GetLayeredServiceProviders(lsp, &providers);
711 EXPECT_TRUE(providers.empty());
712
713 // Now try with a couple of providers
714 base::FilePath file_path1 = base::FilePath(kFileName1);
715 base::FilePath file_path2 = base::FilePath(kFileName2);
716 lsp.AddProvider(kGUID1, file_path1);
717 lsp.AddProvider(kGUID2, file_path2);
718 lsp.AddProvider(kGUID3, file_path2);
719
720 GetLayeredServiceProviders(lsp, &providers);
721
722 EXPECT_EQ(2UL, providers.size());
723 EXPECT_NE(providers.end(), providers.find(file_path1));
724 EXPECT_NE(providers.end(), providers.find(file_path2));
725 EXPECT_EQ(1UL, providers.find(file_path1)->second.size());
726 EXPECT_NE(providers.find(file_path1)->second.end(),
727 providers.find(file_path1)->second.find(kGUID1));
728 EXPECT_EQ(2UL, providers.find(file_path2)->second.size());
729 EXPECT_NE(providers.find(file_path2)->second.end(),
730 providers.find(file_path2)->second.find(kGUID2));
731 EXPECT_NE(providers.find(file_path2)->second.end(),
732 providers.find(file_path2)->second.find(kGUID3));
733 }
734
TEST(DiskUtilTests,DeleteFileFromTempProcess)735 TEST(DiskUtilTests, DeleteFileFromTempProcess) {
736 base::FilePath test_file;
737 base::ScopedTempDir test_dir;
738 ASSERT_TRUE(test_dir.CreateUniqueTempDir());
739 base::CreateTemporaryFileInDir(test_dir.GetPath(), &test_file);
740 ASSERT_TRUE(base::PathExists(test_file));
741 base::WriteFile(test_file, "foo", 3);
742 base::win::ScopedHandle process_handle;
743 EXPECT_TRUE(DeleteFileFromTempProcess(test_file, 0, &process_handle));
744 ASSERT_NE(static_cast<HANDLE>(nullptr), process_handle.Get());
745 DWORD wait_result = ::WaitForSingleObject(
746 process_handle.Get(),
747 TestTimeouts::action_max_timeout().InMilliseconds());
748 process_handle.Close();
749 EXPECT_EQ(WAIT_OBJECT_0, wait_result);
750 EXPECT_FALSE(base::PathExists(test_file));
751 EXPECT_FALSE(DeleteFileFromTempProcess(test_file, 0, &process_handle));
752 EXPECT_FALSE(process_handle.IsValid());
753 }
754
TEST(DiskUtilTests,PathEqual)755 TEST(DiskUtilTests, PathEqual) {
756 base::ScopedTempDir temp_dir;
757 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
758 base::FilePath long_path1(temp_dir.GetPath().Append(kLongFileName1));
759 base::FilePath long_path2(temp_dir.GetPath().Append(kLongFileName2));
760 base::FilePath long_path1_upper(base::ToUpperASCII(long_path1.value()));
761
762 base::FilePath short_path1;
763 CreateFileAndGetShortName(long_path1, &short_path1);
764
765 // Same paths are equal.
766 EXPECT_TRUE(PathEqual(long_path1, long_path1));
767 EXPECT_TRUE(PathEqual(long_path2, long_path2));
768 // Same paths with different case are equal.
769 EXPECT_TRUE(PathEqual(long_path1, long_path1_upper));
770 // Different path are not equal.
771 EXPECT_FALSE(PathEqual(long_path1, long_path2));
772
773 // Short and long path to the same file are equal.
774 EXPECT_TRUE(PathEqual(short_path1, long_path1));
775 // Short and long path to different files are not equal.
776 EXPECT_FALSE(PathEqual(short_path1, long_path2));
777 }
778
TEST(DiskUtilTests,GetAppDataProductDirectory)779 TEST(DiskUtilTests, GetAppDataProductDirectory) {
780 base::ScopedPathOverride appdata_override(
781 CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA));
782 base::FilePath appdata_dir;
783 ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
784 &appdata_dir));
785
786 base::FilePath product_folder;
787 EXPECT_TRUE(GetAppDataProductDirectory(&product_folder));
788 EXPECT_TRUE(base::DirectoryExists(product_folder));
789 EXPECT_TRUE(PathEqual(appdata_dir, product_folder.DirName().DirName()));
790 }
791
TEST(DiskUtilTests,ZoneIdentifier)792 TEST(DiskUtilTests, ZoneIdentifier) {
793 base::ScopedTempDir temp_dir;
794 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
795 base::FilePath path(temp_dir.GetPath().Append(kTestProcessExecutableName));
796
797 if (!DoesVolumeSupportNamedStreams(temp_dir.GetPath())) {
798 LOG(ERROR) << "Skip ZoneIdentifier : alternate streams not supported.";
799 return;
800 }
801
802 // Copy the test_process executable in a temporary folder.
803 base::FilePath executable_path;
804 ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &executable_path));
805 base::FilePath source_path =
806 executable_path.Append(kTestProcessExecutableName);
807 ASSERT_TRUE(base::CopyFile(source_path, path));
808
809 // Overwrite the ZoneIdentifier.
810 EXPECT_FALSE(HasZoneIdentifier(path));
811 EXPECT_TRUE(OverwriteZoneIdentifier(path));
812 EXPECT_TRUE(HasZoneIdentifier(path));
813
814 // Validate the content of the Zone.Identifier stream.
815 base::FilePath stream_path(path.value() + L":Zone.Identifier");
816 std::string content;
817 ASSERT_TRUE(base::ReadFileToString(stream_path, &content));
818 EXPECT_EQ("[ZoneTransfer]\r\nZoneId=0\r\n", content);
819 }
820
TEST(DiskUtilTests,ZoneIdentifierWhenProcessIsRunning)821 TEST(DiskUtilTests, ZoneIdentifierWhenProcessIsRunning) {
822 base::FilePath executable_path;
823 ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &executable_path));
824
825 if (!DoesVolumeSupportNamedStreams(executable_path)) {
826 LOG(ERROR) << "Skip ZoneIdentifier : alternate streams not supported.";
827 return;
828 }
829
830 // Copy the test_process executable to a temporary name. We don't use a
831 // ScopedTempDir here because in a component build, the executable depends on
832 // DLL's that would have to be copied into the folder too.
833 base::FilePath source_exe_path(
834 executable_path.Append(kTestProcessExecutableName));
835 std::wstring target_exe_name = base::StrCat(
836 {base::UTF8ToWide(base::UnguessableToken::Create().ToString()), L".exe"});
837 base::FilePath target_exe_path(executable_path.Append(target_exe_name));
838
839 ASSERT_TRUE(base::CopyFile(source_exe_path, target_exe_path));
840 base::ScopedClosureRunner delete_temp_file(
841 base::BindOnce(base::GetDeleteFileCallback(), target_exe_path));
842
843 // Launch the test_process and wait it's completion. The process must set its
844 // zone identifier.
845 EXPECT_FALSE(HasZoneIdentifier(target_exe_path));
846 ASSERT_FALSE(IsProcessRunning(target_exe_name.c_str()));
847 ASSERT_TRUE(LaunchTestProcess(target_exe_path.value().c_str(),
848 kTestForceOverwriteZoneIdentifier, false));
849 EXPECT_TRUE(WaitForProcessesStopped(target_exe_name.c_str()));
850 EXPECT_TRUE(HasZoneIdentifier(target_exe_path));
851
852 // Validate the content of the Zone.Identifier stream.
853 base::FilePath stream_path(target_exe_path.value() + L":Zone.Identifier");
854 std::string content;
855 ASSERT_TRUE(base::ReadFileToString(stream_path, &content));
856 EXPECT_EQ("[ZoneTransfer]\r\nZoneId=0\r\n", content);
857 }
858
TEST(DiskUtilTests,ExtractExecutablePathFromRegistryContentWithSysnativeReplacement)859 TEST(DiskUtilTests,
860 ExtractExecutablePathFromRegistryContentWithSysnativeReplacement) {
861 base::FilePath system_folder;
862 ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_SYSTEM),
863 &system_folder));
864
865 base::FilePath native_folder(system_folder.DirName().Append(L"sysnative"));
866 // Only run this test on 64-bits Windows with 32-bits process.
867 if (base::PathExists(native_folder)) {
868 base::ScopedTempDir temp_dir;
869 ASSERT_TRUE(temp_dir.CreateUniqueTempDirUnderPath(native_folder));
870
871 base::FilePath program_path, spaced_program_path;
872 CreateProgramPathsAndFiles(temp_dir.GetPath(), &program_path,
873 &spaced_program_path);
874 const base::FilePath program_paths[] = {program_path, spaced_program_path};
875 for (const auto& program_path : program_paths) {
876 // convert C:\\Windows\sysnative\scoped_folder\folder1234\file1 into
877 // C:\\Windows\system32\scoped_folder\folder1234\file1
878 base::FilePath program_path_system =
879 system_folder.Append(program_path.DirName().DirName().BaseName())
880 .Append(program_path.DirName().BaseName())
881 .Append(program_path.BaseName());
882 EXPECT_TRUE(ExtractExecutablePathFromMockRegistryAndExpect(
883 program_path_system.value(), program_path));
884 }
885 }
886 }
887
TEST(DiskUtilTests,ExtractExecutablePathFromRegistryContentWithEnvVariable)888 TEST(DiskUtilTests, ExtractExecutablePathFromRegistryContentWithEnvVariable) {
889 // This test expects files to be placed in %TEMP% and not anywhere else
890 // ScopedTempDir might decide to put them.
891 std::wstring temp_str;
892 ASSERT_NE(0U, ::GetEnvironmentVariableW(
893 L"TEMP", ::base::WriteInto(&temp_str, MAX_PATH), MAX_PATH))
894 << logging::SystemErrorCodeToString(logging::GetLastSystemErrorCode());
895 base::FilePath temp_path(temp_str);
896 ASSERT_TRUE(base::PathExists(temp_path));
897
898 base::ScopedTempDir temp_dir;
899 ASSERT_TRUE(temp_dir.CreateUniqueTempDirUnderPath(temp_path));
900
901 base::FilePath program_path, spaced_program_path;
902 CreateProgramPathsAndFiles(temp_dir.GetPath(), &program_path,
903 &spaced_program_path);
904 const base::FilePath program_paths[] = {program_path, spaced_program_path};
905
906 for (const auto& program_path : program_paths) {
907 // Convert
908 // "C:\Users\$USER\AppData\Local\Temp\scoped_dir1234\folder6788\A111.tmp"
909 // into "scoped_dir1234\folder6789\A111.tmp"
910 base::FilePath relative_program_path =
911 program_path.DirName()
912 .DirName()
913 .BaseName()
914 .Append(program_path.DirName().BaseName())
915 .Append(program_path.BaseName());
916 const auto program_path_with_var =
917 base::StrCat({L"%TEMP%\\", relative_program_path.value()});
918
919 EXPECT_TRUE(ExtractExecutablePathFromMockRegistryAndExpect(
920 program_path_with_var, program_path));
921 }
922 }
923
TEST(DiskUtilTests,ExtractExecutablePathFromRegistryContent)924 TEST(DiskUtilTests, ExtractExecutablePathFromRegistryContent) {
925 // Create the executable to be recognized.
926 base::ScopedTempDir temp_dir;
927
928 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
929 base::FilePath program_path, spaced_program_path;
930 CreateProgramPathsAndFiles(temp_dir.GetPath(), &program_path,
931 &spaced_program_path);
932 const base::FilePath program_paths[] = {program_path, spaced_program_path};
933
934 for (const auto& program_path : program_paths) {
935 EXPECT_TRUE(ExtractExecutablePathFromMockRegistryAndExpect(
936 program_path.value(), program_path));
937 }
938 }
939
TEST(DiskUtilTests,FilePathLess)940 TEST(DiskUtilTests, FilePathLess) {
941 base::FilePath path_a(L"c:\\a");
942 base::FilePath path_upper_a(L"c:\\A");
943 base::FilePath path_b(L"c:\\b");
944 FilePathLess file_path_less;
945 EXPECT_TRUE(file_path_less(path_a, path_b));
946 EXPECT_TRUE(file_path_less(path_upper_a, path_b));
947 EXPECT_FALSE(file_path_less(path_b, path_a));
948 EXPECT_FALSE(file_path_less(path_a, path_upper_a));
949 EXPECT_FALSE(file_path_less(path_upper_a, path_a));
950
951 std::map<base::FilePath, int, FilePathLess> collection;
952 collection[path_a] = 0;
953 EXPECT_NE(collection.find(path_a), collection.end());
954 EXPECT_NE(collection.find(path_upper_a), collection.end());
955 EXPECT_EQ(collection.find(path_b), collection.end());
956 }
957
TEST(DiskUtilTests,RetrieveDetailedFileInformation)958 TEST(DiskUtilTests, RetrieveDetailedFileInformation) {
959 base::ScopedPathOverride appdata_override(
960 CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA));
961 base::FilePath appdata_folder;
962
963 ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
964 &appdata_folder));
965
966 base::FilePath temp_file(appdata_folder.Append(L"DUMMY.inactive"));
967 CreateFileWithContent(temp_file, kFileContent1, sizeof(kFileContent1));
968
969 bool whitelisted = false;
970 internal::FileInformation file_information;
971 RetrieveDetailedFileInformation(temp_file, &file_information, &whitelisted);
972
973 EXPECT_FALSE(whitelisted);
974
975 std::wstring sanitized_path = SanitizePath(temp_file);
976
977 EXPECT_EQ(sanitized_path, file_information.path);
978 EXPECT_FALSE(file_information.creation_date.empty());
979 EXPECT_FALSE(file_information.last_modified_date.empty());
980 EXPECT_FALSE(file_information.active_file);
981 EXPECT_EQ(kFileContentDigests[4], file_information.sha256);
982 EXPECT_EQ(sizeof(kFileContent1), static_cast<size_t>(file_information.size));
983 // The next fields are parsed from PE headers so they won't exist.
984 EXPECT_TRUE(file_information.company_name.empty());
985 EXPECT_TRUE(file_information.company_short_name.empty());
986 EXPECT_TRUE(file_information.product_name.empty());
987 EXPECT_TRUE(file_information.product_short_name.empty());
988 EXPECT_TRUE(file_information.internal_name.empty());
989 EXPECT_TRUE(file_information.original_filename.empty());
990 EXPECT_TRUE(file_information.file_description.empty());
991 EXPECT_TRUE(file_information.file_version.empty());
992 }
993
TEST(DiskUtilTests,RetrieveDetailedFileInformationNoFile)994 TEST(DiskUtilTests, RetrieveDetailedFileInformationNoFile) {
995 base::FilePath appdata_folder;
996
997 ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
998 &appdata_folder));
999
1000 base::FilePath non_existent_file(
1001 appdata_folder.DirName().Append(L"abcd1234CCT1234.tmp"));
1002
1003 bool whitelisted = false;
1004 internal::FileInformation file_information;
1005 RetrieveDetailedFileInformation(non_existent_file, &file_information,
1006 &whitelisted);
1007
1008 EXPECT_FALSE(whitelisted);
1009 EXPECT_TRUE(file_information.path.empty());
1010 EXPECT_TRUE(file_information.creation_date.empty());
1011 EXPECT_TRUE(file_information.last_modified_date.empty());
1012 EXPECT_FALSE(file_information.active_file);
1013 EXPECT_TRUE(file_information.sha256.empty());
1014 EXPECT_EQ(0, file_information.size);
1015 EXPECT_TRUE(file_information.company_name.empty());
1016 EXPECT_TRUE(file_information.company_short_name.empty());
1017 EXPECT_TRUE(file_information.product_name.empty());
1018 EXPECT_TRUE(file_information.product_short_name.empty());
1019 EXPECT_TRUE(file_information.internal_name.empty());
1020 EXPECT_TRUE(file_information.original_filename.empty());
1021 EXPECT_TRUE(file_information.file_description.empty());
1022 EXPECT_TRUE(file_information.file_version.empty());
1023 }
1024
TEST(DiskUtilTests,RetrieveDetailedFileInformationWhitelisted)1025 TEST(DiskUtilTests, RetrieveDetailedFileInformationWhitelisted) {
1026 bool whitelisted = false;
1027 internal::FileInformation file_information;
1028
1029 RetrieveDetailedFileInformation(GetSampleDLLPath(), &file_information,
1030 &whitelisted,
1031 base::BindOnce(&WhitelistSampleDLL));
1032
1033 EXPECT_TRUE(whitelisted);
1034 EXPECT_TRUE(file_information.path.empty());
1035 EXPECT_TRUE(file_information.creation_date.empty());
1036 EXPECT_TRUE(file_information.last_modified_date.empty());
1037 EXPECT_FALSE(file_information.active_file);
1038 EXPECT_TRUE(file_information.sha256.empty());
1039 EXPECT_EQ(0, file_information.size);
1040 EXPECT_TRUE(file_information.company_name.empty());
1041 EXPECT_TRUE(file_information.company_short_name.empty());
1042 EXPECT_TRUE(file_information.product_name.empty());
1043 EXPECT_TRUE(file_information.product_short_name.empty());
1044 EXPECT_TRUE(file_information.internal_name.empty());
1045 EXPECT_TRUE(file_information.original_filename.empty());
1046 EXPECT_TRUE(file_information.file_description.empty());
1047 EXPECT_TRUE(file_information.file_version.empty());
1048 }
1049
TEST(DiskUtilTests,RetrieveBasicFileInformation)1050 TEST(DiskUtilTests, RetrieveBasicFileInformation) {
1051 base::ScopedPathOverride appdata_override(
1052 CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA));
1053 base::FilePath appdata_folder;
1054
1055 ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
1056 &appdata_folder));
1057
1058 base::FilePath temp_file(appdata_folder.Append(L"DUMMY.exe"));
1059 CreateFileWithContent(temp_file, kFileContent1, sizeof(kFileContent1));
1060
1061 internal::FileInformation file_information;
1062 RetrieveBasicFileInformation(temp_file, &file_information);
1063
1064 // The expected file path value should be sanitized.
1065 EXPECT_EQ(SanitizePath(temp_file), file_information.path);
1066 EXPECT_FALSE(file_information.creation_date.empty());
1067 EXPECT_FALSE(file_information.last_modified_date.empty());
1068 EXPECT_EQ(sizeof(kFileContent1), static_cast<size_t>(file_information.size));
1069 EXPECT_TRUE(file_information.active_file);
1070 // The next fields are not included in basic file information.
1071 EXPECT_TRUE(file_information.sha256.empty());
1072 EXPECT_TRUE(file_information.company_name.empty());
1073 EXPECT_TRUE(file_information.company_short_name.empty());
1074 EXPECT_TRUE(file_information.product_name.empty());
1075 EXPECT_TRUE(file_information.product_short_name.empty());
1076 EXPECT_TRUE(file_information.internal_name.empty());
1077 EXPECT_TRUE(file_information.original_filename.empty());
1078 EXPECT_TRUE(file_information.file_description.empty());
1079 EXPECT_TRUE(file_information.file_version.empty());
1080 }
1081
TEST(DiskUtilTests,RetrieveBasicFileInformationNoFile)1082 TEST(DiskUtilTests, RetrieveBasicFileInformationNoFile) {
1083 base::FilePath appdata_folder;
1084 ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
1085 &appdata_folder));
1086
1087 base::FilePath non_existent_file(
1088 appdata_folder.DirName().Append(L"abcd1234CCT1234.tmp"));
1089
1090 internal::FileInformation file_information;
1091 RetrieveBasicFileInformation(non_existent_file, &file_information);
1092
1093 EXPECT_TRUE(file_information.path.empty());
1094 EXPECT_TRUE(file_information.creation_date.empty());
1095 EXPECT_TRUE(file_information.last_modified_date.empty());
1096 EXPECT_FALSE(file_information.active_file);
1097 EXPECT_TRUE(file_information.sha256.empty());
1098 EXPECT_EQ(0, file_information.size);
1099 EXPECT_TRUE(file_information.company_name.empty());
1100 EXPECT_TRUE(file_information.company_short_name.empty());
1101 EXPECT_TRUE(file_information.product_name.empty());
1102 EXPECT_TRUE(file_information.product_short_name.empty());
1103 EXPECT_TRUE(file_information.internal_name.empty());
1104 EXPECT_TRUE(file_information.original_filename.empty());
1105 EXPECT_TRUE(file_information.file_description.empty());
1106 EXPECT_TRUE(file_information.file_version.empty());
1107 }
1108
TEST(DiskUtilTests,FileInformationToString)1109 TEST(DiskUtilTests, FileInformationToString) {
1110 std::wstring display_str = FileInformationToString(kFileInformation1);
1111 EXPECT_EQ(kFileInformation1ExpectedString, display_str);
1112 }
1113
TEST(DiskUtilTests,FileInformationToStringEmpty)1114 TEST(DiskUtilTests, FileInformationToStringEmpty) {
1115 internal::FileInformation file_information;
1116 EXPECT_TRUE(FileInformationToString(file_information).empty());
1117 }
1118
TEST(DiskUtilTests,TryToExpandPath_NonSystemNativePath)1119 TEST(DiskUtilTests, TryToExpandPath_NonSystemNativePath) {
1120 base::ScopedPathOverride appdata_override(
1121 CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA));
1122 base::FilePath appdata_folder;
1123 ASSERT_TRUE(base::PathService::Get(CsidlToPathServiceKey(CSIDL_LOCAL_APPDATA),
1124 &appdata_folder));
1125
1126 base::FilePath non_existing_file(
1127 appdata_folder.DirName().Append(L"non-existing-file.tmp"));
1128 base::FilePath unused_expanded_path;
1129 ASSERT_FALSE(TryToExpandPath(non_existing_file, &unused_expanded_path));
1130
1131 base::FilePath existing_file(appdata_folder.Append(L"existing-file.tmp"));
1132 CreateFileWithContent(existing_file, kFileContent1, sizeof(kFileContent1));
1133 base::FilePath expanded_path;
1134 ASSERT_TRUE(TryToExpandPath(existing_file, &expanded_path));
1135 ASSERT_EQ(existing_file.value(), expanded_path.value());
1136
1137 // TODO: Figure out how to test paths in C:\Windows\System32.
1138 }
1139
TEST(DiskUtilTests,TruncateLogFileToTail_FindsNewline)1140 TEST(DiskUtilTests, TruncateLogFileToTail_FindsNewline) {
1141 const char kFileContents[] = "File with utf8 \n\xe2\x82\xac \ntail";
1142 const int kFileSize = strlen(kFileContents);
1143 const char kTailContents[] = "\ntail";
1144 const int kTailSize = strlen(kTailContents);
1145
1146 base::ScopedTempDir temp_dir;
1147 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1148 base::FilePath file_path = temp_dir.GetPath().Append(L"file.txt");
1149 ASSERT_EQ(kFileSize, base::WriteFile(file_path, kFileContents, kFileSize));
1150
1151 // The tail threshold lands in the middle of a multi-byte character.
1152 TruncateLogFileToTail(file_path, kTailSize + 3);
1153
1154 int64_t file_size;
1155 ASSERT_TRUE(base::GetFileSize(file_path, &file_size));
1156 EXPECT_EQ(kTailSize, file_size);
1157 std::string tail;
1158 ASSERT_TRUE(base::ReadFileToString(file_path, &tail));
1159 EXPECT_EQ(kTailContents, tail);
1160 }
1161
TEST(DiskUtilTests,TruncateLogFileToTail_FileSmallerThanLimit)1162 TEST(DiskUtilTests, TruncateLogFileToTail_FileSmallerThanLimit) {
1163 const char kFileContents[] = "I am file";
1164 const int kFileSize = strlen(kFileContents);
1165
1166 base::ScopedTempDir temp_dir;
1167 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1168 base::FilePath file_path = temp_dir.GetPath().Append(L"file.txt");
1169 ASSERT_EQ(kFileSize, base::WriteFile(file_path, kFileContents, kFileSize));
1170
1171 TruncateLogFileToTail(file_path, kFileSize * 2);
1172
1173 int64_t file_size;
1174 ASSERT_TRUE(base::GetFileSize(file_path, &file_size));
1175 EXPECT_EQ(kFileSize, file_size);
1176 std::string tail;
1177 ASSERT_TRUE(base::ReadFileToString(file_path, &tail));
1178 EXPECT_EQ(kFileContents, tail);
1179 }
1180
TEST(DiskUtilTests,TruncateLogFileToTail_NotExisting)1181 TEST(DiskUtilTests, TruncateLogFileToTail_NotExisting) {
1182 base::ScopedTempDir temp_dir;
1183 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1184 base::FilePath file_path = temp_dir.GetPath().Append(L"file.txt");
1185
1186 TruncateLogFileToTail(file_path, 42);
1187
1188 EXPECT_FALSE(base::PathExists(file_path));
1189 }
1190
TEST(DiskUtilTests,IgnoredReportingList)1191 TEST(DiskUtilTests, IgnoredReportingList) {
1192 EXPECT_TRUE(IsCompanyOnIgnoredReportingList(L"Google LLC"));
1193 EXPECT_FALSE(IsCompanyOnIgnoredReportingList(L"google llc"));
1194 EXPECT_FALSE(IsCompanyOnIgnoredReportingList(L"Unrecognized Inc"));
1195 }
1196
1197 } // namespace chrome_cleaner
1198