]> granicus.if.org Git - php/commitdiff
php_zip_pcre: Match pattern before stating for directories
authorNikita Popov <nikita.ppv@gmail.com>
Thu, 6 Jun 2019 09:46:23 +0000 (11:46 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Thu, 6 Jun 2019 09:46:23 +0000 (11:46 +0200)
For two reasons: First, it's generally cheaper to match a regex than
perform a stat (especially on Windows). Second, it will not fail on
concurrent modification of a directory in parts that are not matched
by the pattern, such as the spurious failure in ext/zip/tests/bug72660.phpt.

ext/zip/php_zip.c

index b8e01c1fe23028bfc17e842449eb85e0b5cb5be4..fabd30e8eae4699d2274123c6dfb8d890437d65a 100644 (file)
@@ -677,19 +677,6 @@ int php_zip_pcre(zend_string *regexp, char *path, int path_len, zval *return_val
                                break;
                        }
 
-                       snprintf(fullpath, MAXPATHLEN, "%s%c%s", path, DEFAULT_SLASH, ZSTR_VAL(namelist[i]));
-
-                       if (0 != VCWD_STAT(fullpath, &s)) {
-                               php_error_docref(NULL, E_WARNING, "Cannot read <%s>", fullpath);
-                               zend_string_release_ex(namelist[i], 0);
-                               continue;
-                       }
-
-                       if (S_IFDIR == (s.st_mode & S_IFMT)) {
-                               zend_string_release_ex(namelist[i], 0);
-                               continue;
-                       }
-
                        match_data = php_pcre_create_match_data(capture_count, re);
                        if (!match_data) {
                                /* Allocation failed, but can proceed to the next pattern. */
@@ -704,6 +691,19 @@ int php_zip_pcre(zend_string *regexp, char *path, int path_len, zval *return_val
                                continue;
                        }
 
+                       snprintf(fullpath, MAXPATHLEN, "%s%c%s", path, DEFAULT_SLASH, ZSTR_VAL(namelist[i]));
+
+                       if (0 != VCWD_STAT(fullpath, &s)) {
+                               php_error_docref(NULL, E_WARNING, "Cannot read <%s>", fullpath);
+                               zend_string_release_ex(namelist[i], 0);
+                               continue;
+                       }
+
+                       if (S_IFDIR == (s.st_mode & S_IFMT)) {
+                               zend_string_release_ex(namelist[i], 0);
+                               continue;
+                       }
+
                        add_next_index_string(return_value, fullpath);
                        zend_string_release_ex(namelist[i], 0);
                }