Skip to content

Commit d9dbe79

Browse files
committed
Fix special directory references to -find
Fixes #171. Also fixes cases of subsequent directory separators.
1 parent a76aad2 commit d9dbe79

File tree

2 files changed

+153
-11
lines changed

2 files changed

+153
-11
lines changed

src/vswhere.lib/Glob.cpp

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,32 @@ Glob::Glob(_In_ const wstring& root, _In_ const wstring& pattern) :
2626
// Append directories to root until wildcard found, then accumulate to optimize match.
2727
case L'/':
2828
case L'\\':
29+
if (lastch == L'/' || lastch == L'\\')
30+
{
31+
// Ignore subsequent directory separators.
32+
continue;
33+
}
34+
2935
if (value.length())
3036
{
31-
// Replase globstar with any characer match plus optional directory separator.
3237
if (found_globstar)
3338
{
39+
// Replase globstar with any characer match plus optional directory separator.
3440
accumulator += L".*\\\\?";
3541
}
42+
else if (value_raw.length() == 1 && value_raw == L".")
43+
{
44+
// Ignore current directory references.
45+
value.clear();
46+
value_raw.clear();
47+
48+
continue;
49+
}
50+
else if (value_raw.length() == 2 && value_raw == L"..")
51+
{
52+
// Block parent directory references.
53+
ThrowError(pattern);
54+
}
3655
else if (found_wildcard)
3756
{
3857
// A single star (asterisk) searches the any subdirectory not including the current directory.
@@ -45,13 +64,9 @@ Glob::Glob(_In_ const wstring& root, _In_ const wstring& pattern) :
4564
accumulator += value;
4665
}
4766
}
48-
else if (value_raw.length())
49-
{
50-
m_root /= value_raw;
51-
}
5267
else
5368
{
54-
m_root /= value;
69+
m_root /= value_raw;
5570
}
5671

5772
value.clear();
@@ -126,11 +141,7 @@ Glob::Glob(_In_ const wstring& root, _In_ const wstring& pattern) :
126141
}
127142

128143
value += ch;
129-
if (!found_wildcard)
130-
{
131-
// Keep track of possible subdirectories until we find a wildcard.
132-
value_raw += ch;
133-
}
144+
value_raw += ch;
134145

135146
break;
136147
}

test/vswhere.test/GlobTests.cpp

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,4 +190,135 @@ TEST_CLASS(GlobTests)
190190
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\Current\\Bin\\amd64\\MSBuild.exe"));
191191
Assert::IsFalse(sut.Match(L"C:\\ShouldNotExist\\MSBuild.exe"));
192192
}
193+
194+
BEGIN_TEST_METHOD_ATTRIBUTE(Leading_Backslash)
195+
TEST_WORKITEM(171)
196+
END_TEST_METHOD_ATTRIBUTE()
197+
TEST_METHOD(Leading_Backslash)
198+
{
199+
Glob sut(L"C:\\ShouldNotExist", L"\\MSBuild\\**\\MSBuild.exe");
200+
Assert::AreEqual(L"C:\\ShouldNotExist\\MSBuild", sut.Root().c_str());
201+
202+
#ifdef _DEBUG
203+
Assert::AreEqual(L"^\\\\.*\\\\?MSBuild\\.exe$", sut.Pattern().c_str());
204+
#endif
205+
206+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\MSBuild.exe"));
207+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\Current\\MSBuild.exe"));
208+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\Current\\Bin\\MSBuild.exe"));
209+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\Current\\Bin\\amd64\\MSBuild.exe"));
210+
Assert::IsFalse(sut.Match(L"C:\\ShouldNotExist\\MSBuild.exe"));
211+
}
212+
213+
BEGIN_TEST_METHOD_ATTRIBUTE(Leading_Double_Backslashes)
214+
TEST_WORKITEM(171)
215+
END_TEST_METHOD_ATTRIBUTE()
216+
TEST_METHOD(Leading_Double_Backslashes)
217+
{
218+
Glob sut(L"C:\\ShouldNotExist", L"\\\\MSBuild\\**\\MSBuild.exe");
219+
Assert::AreEqual(L"C:\\ShouldNotExist\\MSBuild", sut.Root().c_str());
220+
221+
#ifdef _DEBUG
222+
Assert::AreEqual(L"^\\\\.*\\\\?MSBuild\\.exe$", sut.Pattern().c_str());
223+
#endif
224+
225+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\MSBuild.exe"));
226+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\Current\\MSBuild.exe"));
227+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\Current\\Bin\\MSBuild.exe"));
228+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\Current\\Bin\\amd64\\MSBuild.exe"));
229+
Assert::IsFalse(sut.Match(L"C:\\ShouldNotExist\\MSBuild.exe"));
230+
}
231+
232+
BEGIN_TEST_METHOD_ATTRIBUTE(Double_Backslashes_Later)
233+
TEST_WORKITEM(171)
234+
END_TEST_METHOD_ATTRIBUTE()
235+
TEST_METHOD(Double_Backslashes_Later)
236+
{
237+
Glob sut(L"C:\\ShouldNotExist", L"MSBuild\\**\\Bin\\\\MSBuild.exe");
238+
Assert::AreEqual(L"C:\\ShouldNotExist\\MSBuild", sut.Root().c_str());
239+
240+
#ifdef _DEBUG
241+
Assert::AreEqual(L"^\\\\.*\\\\?Bin\\\\MSBuild\\.exe$", sut.Pattern().c_str());
242+
#endif
243+
244+
Assert::IsFalse(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\MSBuild.exe"));
245+
Assert::IsFalse(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\Current\\MSBuild.exe"));
246+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\Current\\Bin\\MSBuild.exe"));
247+
Assert::IsFalse(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\Current\\Bin\\amd64\\MSBuild.exe"));
248+
Assert::IsFalse(sut.Match(L"C:\\ShouldNotExist\\MSBuild.exe"));
249+
}
250+
251+
BEGIN_TEST_METHOD_ATTRIBUTE(Parent_Directory)
252+
TEST_WORKITEM(171)
253+
END_TEST_METHOD_ATTRIBUTE()
254+
TEST_METHOD(Parent_Directory)
255+
{
256+
try
257+
{
258+
Glob(L"C:\\ShouldNotExist", L"..\\**\\msbuild.exe");
259+
}
260+
catch (const win32_error& ex)
261+
{
262+
Assert::AreEqual<int>(ERROR_INVALID_PARAMETER, ex.code().value());
263+
return;
264+
}
265+
266+
Assert::Fail(L"No exception thrown");
267+
}
268+
269+
BEGIN_TEST_METHOD_ATTRIBUTE(Parent_Directory_Later)
270+
TEST_WORKITEM(171)
271+
END_TEST_METHOD_ATTRIBUTE()
272+
TEST_METHOD(Parent_Directory_Later)
273+
{
274+
try
275+
{
276+
Glob(L"C:\\ShouldNotExist", L"**\\..\\msbuild.exe");
277+
}
278+
catch (const win32_error& ex)
279+
{
280+
Assert::AreEqual<int>(ERROR_INVALID_PARAMETER, ex.code().value());
281+
return;
282+
}
283+
284+
Assert::Fail(L"No exception thrown");
285+
}
286+
287+
BEGIN_TEST_METHOD_ATTRIBUTE(Current_Directory)
288+
TEST_WORKITEM(171)
289+
END_TEST_METHOD_ATTRIBUTE()
290+
TEST_METHOD(Current_Directory)
291+
{
292+
Glob sut(L"C:\\ShouldNotExist", L".\\**\\msbuild.exe");
293+
Assert::AreEqual(L"C:\\ShouldNotExist", sut.Root().c_str());
294+
295+
#ifdef _DEBUG
296+
Assert::AreEqual(L"^\\\\.*\\\\?msbuild\\.exe$", sut.Pattern().c_str());
297+
#endif
298+
299+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild.exe"));
300+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\MSBuild.exe"));
301+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\Current\\MSBuild.exe"));
302+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\Current\\Bin\\MSBuild.exe"));
303+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\Current\\Bin\\amd64\\MSBuild.exe"));
304+
}
305+
306+
BEGIN_TEST_METHOD_ATTRIBUTE(Current_Directory_Later)
307+
TEST_WORKITEM(171)
308+
END_TEST_METHOD_ATTRIBUTE()
309+
TEST_METHOD(Current_Directory_Later)
310+
{
311+
Glob sut(L"C:\\ShouldNotExist", L"**\\.\\msbuild.exe");
312+
Assert::AreEqual(L"C:\\ShouldNotExist", sut.Root().c_str());
313+
314+
#ifdef _DEBUG
315+
Assert::AreEqual(L"^\\\\.*\\\\?msbuild\\.exe$", sut.Pattern().c_str());
316+
#endif
317+
318+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild.exe"));
319+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\MSBuild.exe"));
320+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\Current\\MSBuild.exe"));
321+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\Current\\Bin\\MSBuild.exe"));
322+
Assert::IsTrue(sut.Match(L"C:\\ShouldNotExist\\MSBuild\\Current\\Bin\\amd64\\MSBuild.exe"));
323+
}
193324
};

0 commit comments

Comments
 (0)