@@ -50,6 +50,15 @@ class Filter extends \RecursiveFilterIterator
50
50
*/
51
51
protected $ ignoreFilePatterns = null ;
52
52
53
+ /**
54
+ * A list of file paths we've already accepted.
55
+ *
56
+ * Used to ensure we aren't following circular symlinks.
57
+ *
58
+ * @var array
59
+ */
60
+ protected $ acceptedPaths = [];
61
+
53
62
54
63
/**
55
64
* Constructs a filter.
@@ -82,7 +91,18 @@ public function __construct($iterator, $basedir, Config $config, Ruleset $rulese
82
91
public function accept ()
83
92
{
84
93
$ filePath = $ this ->current ();
94
+ $ realPath = Util \Common::realpath ($ filePath );
85
95
96
+ if ($ realPath !== false ) {
97
+ // It's a real path somewhere, so record it
98
+ // to check for circular symlinks.
99
+ if (isset ($ this ->acceptedPaths [$ realPath ]) === true ) {
100
+ // We've been here before.
101
+ return false ;
102
+ }
103
+ }
104
+
105
+ $ filePath = $ this ->current ();
86
106
if (is_dir ($ filePath ) === true ) {
87
107
if ($ this ->config ->local === true ) {
88
108
return false ;
@@ -95,6 +115,7 @@ public function accept()
95
115
return false ;
96
116
}
97
117
118
+ $ this ->acceptedPaths [$ realPath ] = true ;
98
119
return true ;
99
120
100
121
}//end accept()
@@ -120,6 +141,7 @@ public function getChildren()
120
141
// Set the ignore patterns so we don't have to generate them again.
121
142
$ children ->ignoreDirPatterns = $ this ->ignoreDirPatterns ;
122
143
$ children ->ignoreFilePatterns = $ this ->ignoreFilePatterns ;
144
+ $ children ->acceptedPaths = $ this ->acceptedPaths ;
123
145
return $ children ;
124
146
125
147
}//end getChildren()
0 commit comments