@@ -41,6 +41,9 @@ typedef struct {
41
41
size_t path_len ;
42
42
char * pattern ;
43
43
size_t pattern_len ;
44
+ size_t * open_basedir_indexmap ;
45
+ size_t open_basedir_indexmap_size ;
46
+ bool open_basedir_indexmap_used ;
44
47
} glob_s_t ;
45
48
46
49
PHPAPI char * _php_glob_stream_get_path (php_stream * stream , size_t * plen STREAMS_DC ) /* {{{ */
@@ -79,6 +82,9 @@ PHPAPI char* _php_glob_stream_get_pattern(php_stream *stream, size_t *plen STREA
79
82
}
80
83
/* }}} */
81
84
85
+ #define _php_glob_stream_get_result_count (pglob ) \
86
+ pglob->open_basedir_indexmap_used ? (int) pglob->open_basedir_indexmap_size : pglob->glob.gl_pathc
87
+
82
88
PHPAPI int _php_glob_stream_get_count (php_stream * stream , int * pflags STREAMS_DC ) /* {{{ */
83
89
{
84
90
glob_s_t * pglob = (glob_s_t * )stream -> abstract ;
@@ -87,7 +93,7 @@ PHPAPI int _php_glob_stream_get_count(php_stream *stream, int *pflags STREAMS_DC
87
93
if (pflags ) {
88
94
* pflags = pglob -> flags ;
89
95
}
90
- return pglob -> glob . gl_pathc ;
96
+ return _php_glob_stream_get_result_count ( pglob ) ;
91
97
} else {
92
98
if (pflags ) {
93
99
* pflags = 0 ;
@@ -130,15 +136,21 @@ static ssize_t php_glob_stream_read(php_stream *stream, char *buf, size_t count)
130
136
glob_s_t * pglob = (glob_s_t * )stream -> abstract ;
131
137
php_stream_dirent * ent = (php_stream_dirent * )buf ;
132
138
const char * path ;
139
+ int glob_result_count ;
140
+ size_t index ;
133
141
134
142
/* avoid problems if someone mis-uses the stream */
135
143
if (count == sizeof (php_stream_dirent ) && pglob ) {
136
- if (pglob -> index < (size_t )pglob -> glob .gl_pathc ) {
137
- php_glob_stream_path_split (pglob , pglob -> glob .gl_pathv [pglob -> index ++ ], pglob -> flags & GLOB_APPEND , & path );
144
+ glob_result_count = _php_glob_stream_get_result_count (pglob );
145
+ if (pglob -> index < (size_t ) glob_result_count ) {
146
+ index = pglob -> open_basedir_indexmap_used && pglob -> open_basedir_indexmap ?
147
+ pglob -> open_basedir_indexmap [pglob -> index ] : pglob -> index ;
148
+ php_glob_stream_path_split (pglob , pglob -> glob .gl_pathv [index ], pglob -> flags & GLOB_APPEND , & path );
149
+ ++ pglob -> index ;
138
150
PHP_STRLCPY (ent -> d_name , path , sizeof (ent -> d_name ), strlen (path ));
139
151
return sizeof (php_stream_dirent );
140
152
}
141
- pglob -> index = pglob -> glob . gl_pathc ;
153
+ pglob -> index = glob_result_count ;
142
154
if (pglob -> path ) {
143
155
efree (pglob -> path );
144
156
pglob -> path = NULL ;
@@ -162,6 +174,9 @@ static int php_glob_stream_close(php_stream *stream, int close_handle) /* {{{ *
162
174
if (pglob -> pattern ) {
163
175
efree (pglob -> pattern );
164
176
}
177
+ if (pglob -> open_basedir_indexmap ) {
178
+ efree (pglob -> open_basedir_indexmap );
179
+ }
165
180
}
166
181
efree (stream -> abstract );
167
182
return 0 ;
@@ -198,7 +213,7 @@ static php_stream *php_glob_stream_opener(php_stream_wrapper *wrapper, const cha
198
213
int options , zend_string * * opened_path , php_stream_context * context STREAMS_DC )
199
214
{
200
215
glob_s_t * pglob ;
201
- int ret ;
216
+ int ret , i ;
202
217
const char * tmp , * pos ;
203
218
204
219
if (!strncmp (path , "glob://" , sizeof ("glob://" )- 1 )) {
@@ -208,10 +223,6 @@ static php_stream *php_glob_stream_opener(php_stream_wrapper *wrapper, const cha
208
223
}
209
224
}
210
225
211
- if (((options & STREAM_DISABLE_OPEN_BASEDIR ) == 0 ) && php_check_open_basedir (path )) {
212
- return NULL ;
213
- }
214
-
215
226
pglob = ecalloc (sizeof (* pglob ), 1 );
216
227
217
228
if (0 != (ret = glob (path , pglob -> flags & GLOB_FLAGMASK , NULL , & pglob -> glob ))) {
@@ -224,6 +235,19 @@ static php_stream *php_glob_stream_opener(php_stream_wrapper *wrapper, const cha
224
235
}
225
236
}
226
237
238
+ /* if open_basedir in use, check and filter restricted paths */
239
+ if ((options & STREAM_DISABLE_OPEN_BASEDIR ) == 0 ) {
240
+ pglob -> open_basedir_indexmap_used = true;
241
+ for (i = 0 ; i < pglob -> glob .gl_pathc ; i ++ ) {
242
+ if (!php_check_open_basedir_ex (pglob -> glob .gl_pathv [i ], 0 )) {
243
+ if (!pglob -> open_basedir_indexmap ) {
244
+ pglob -> open_basedir_indexmap = (size_t * ) emalloc (sizeof (size_t ) * pglob -> glob .gl_pathc );
245
+ }
246
+ pglob -> open_basedir_indexmap [pglob -> open_basedir_indexmap_size ++ ] = i ;
247
+ }
248
+ }
249
+ }
250
+
227
251
pos = path ;
228
252
if ((tmp = strrchr (pos , '/' )) != NULL ) {
229
253
pos = tmp + 1 ;
0 commit comments