Skip to content

Commit c0d5f0f

Browse files
authored
[Ignore] Fix recursion count bug (#802)
1 parent fbe8871 commit c0d5f0f

File tree

1 file changed

+59
-71
lines changed

1 file changed

+59
-71
lines changed

src/PowerShellEditorServices/Workspace/Workspace.cs

Lines changed: 59 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,9 @@ public IEnumerable<string> EnumeratePSFiles()
292292
return Enumerable.Empty<string>();
293293
}
294294

295-
return this.RecursivelyEnumerateFiles(WorkspacePath);
295+
var foundFiles = new List<string>();
296+
this.RecursivelyEnumerateFiles(WorkspacePath, ref foundFiles);
297+
return foundFiles;
296298
}
297299

298300
#endregion
@@ -301,109 +303,95 @@ public IEnumerable<string> EnumeratePSFiles()
301303

302304
/// <summary>
303305
/// Find PowerShell files recursively down from a given directory path.
304-
/// Currently returns files in depth-first order.
306+
/// Currently collects files in depth-first order.
305307
/// Directory.GetFiles(folderPath, pattern, SearchOption.AllDirectories) would provide this,
306308
/// but a cycle in the filesystem will cause that to enter an infinite loop.
307309
/// </summary>
308-
/// <param name="folderPath">The absolute path of the base folder to search.</param>
309-
/// <returns>
310-
/// All PowerShell files in the recursive directory hierarchy under the given base directory, up to 64 directories deep.
311-
/// </returns>
312-
private IEnumerable<string> RecursivelyEnumerateFiles(string folderPath)
310+
/// <param name="folderPath">The path of the current directory to find files in</param>
311+
/// <param name="foundFiles">The accumulator for files found so far.</param>
312+
/// <param name="currDepth">The current depth of the recursion from the original base directory.</param>
313+
private void RecursivelyEnumerateFiles(string folderPath, ref List<string> foundFiles, int currDepth = 0)
313314
{
314-
var foundFiles = new List<string>();
315-
var dirStack = new Stack<string>();
316-
317-
// Kick the search off with the base directory
318-
dirStack.Push(folderPath);
319-
320315
const int recursionDepthLimit = 64;
321-
while (dirStack.Any())
322-
{
323-
string currDir = dirStack.Pop();
324-
325-
// Look for any PowerShell files in the current directory
326-
foreach (string pattern in s_psFilePatterns)
327-
{
328-
string[] psFiles;
329-
try
330-
{
331-
psFiles = Directory.GetFiles(currDir, pattern, SearchOption.TopDirectoryOnly);
332-
}
333-
catch (DirectoryNotFoundException e)
334-
{
335-
this.logger.WriteHandledException(
336-
$"Could not enumerate files in the path '{currDir}' due to it being an invalid path",
337-
e);
338-
339-
continue;
340-
}
341-
catch (PathTooLongException e)
342-
{
343-
this.logger.WriteHandledException(
344-
$"Could not enumerate files in the path '{currDir}' due to the path being too long",
345-
e);
346-
347-
continue;
348-
}
349-
catch (Exception e) when (e is SecurityException || e is UnauthorizedAccessException)
350-
{
351-
this.logger.WriteHandledException(
352-
$"Could not enumerate files in the path '{currDir}' due to the path not being accessible",
353-
e);
354-
355-
continue;
356-
}
357-
358-
foundFiles.AddRange(psFiles);
359-
}
360-
361-
// Prevent unbounded recursion here
362-
// If we get too deep, keep processing but go no deeper
363-
if (dirStack.Count >= recursionDepthLimit)
364-
{
365-
this.logger.Write(LogLevel.Warning, $"Recursion depth limit hit for path {folderPath}");
366-
continue;
367-
}
368316

369-
// Add the recursive directories to search next
370-
string[] subDirs;
317+
// Look for any PowerShell files in the current directory
318+
foreach (string pattern in s_psFilePatterns)
319+
{
320+
string[] psFiles;
371321
try
372322
{
373-
subDirs = Directory.GetDirectories(currDir);
323+
psFiles = Directory.GetFiles(folderPath, pattern, SearchOption.TopDirectoryOnly);
374324
}
375325
catch (DirectoryNotFoundException e)
376326
{
377327
this.logger.WriteHandledException(
378-
$"Could not enumerate directories in the path '{currDir}' due to it being an invalid path",
328+
$"Could not enumerate files in the path '{folderPath}' due to it being an invalid path",
379329
e);
380330

381331
continue;
382332
}
383333
catch (PathTooLongException e)
384334
{
385335
this.logger.WriteHandledException(
386-
$"Could not enumerate directories in the path '{currDir}' due to the path being too long",
336+
$"Could not enumerate files in the path '{folderPath}' due to the path being too long",
387337
e);
388338

389339
continue;
390340
}
391341
catch (Exception e) when (e is SecurityException || e is UnauthorizedAccessException)
392342
{
393343
this.logger.WriteHandledException(
394-
$"Could not enumerate directories in the path '{currDir}' due to the path not being accessible",
344+
$"Could not enumerate files in the path '{folderPath}' due to the path not being accessible",
395345
e);
396346

397347
continue;
398348
}
399349

400-
foreach (string subDir in subDirs)
401-
{
402-
dirStack.Push(subDir);
403-
}
350+
foundFiles.AddRange(psFiles);
404351
}
405352

406-
return foundFiles;
353+
// Prevent unbounded recursion here
354+
if (currDepth >= recursionDepthLimit)
355+
{
356+
this.logger.Write(LogLevel.Warning, $"Recursion depth limit hit for path {folderPath}");
357+
return;
358+
}
359+
360+
// Add the recursive directories to search next
361+
string[] subDirs;
362+
try
363+
{
364+
subDirs = Directory.GetDirectories(folderPath);
365+
}
366+
catch (DirectoryNotFoundException e)
367+
{
368+
this.logger.WriteHandledException(
369+
$"Could not enumerate directories in the path '{folderPath}' due to it being an invalid path",
370+
e);
371+
372+
return;
373+
}
374+
catch (PathTooLongException e)
375+
{
376+
this.logger.WriteHandledException(
377+
$"Could not enumerate directories in the path '{folderPath}' due to the path being too long",
378+
e);
379+
380+
return;
381+
}
382+
catch (Exception e) when (e is SecurityException || e is UnauthorizedAccessException)
383+
{
384+
this.logger.WriteHandledException(
385+
$"Could not enumerate directories in the path '{folderPath}' due to the path not being accessible",
386+
e);
387+
388+
return;
389+
}
390+
391+
foreach (string subDir in subDirs)
392+
{
393+
RecursivelyEnumerateFiles(subDir, ref foundFiles, currDepth: currDepth + 1);
394+
}
407395
}
408396

409397
/// <summary>

0 commit comments

Comments
 (0)