@@ -100,7 +100,7 @@ public function max_size(?string $blank, string $params): bool
100100 }
101101
102102 if ($ file ->getError () === UPLOAD_ERR_NO_FILE ) {
103- return true ;
103+ continue ;
104104 }
105105
106106 if ($ file ->getError () === UPLOAD_ERR_INI_SIZE ) {
@@ -135,7 +135,7 @@ public function is_image(?string $blank, string $params): bool
135135 }
136136
137137 if ($ file ->getError () === UPLOAD_ERR_NO_FILE ) {
138- return true ;
138+ continue ;
139139 }
140140
141141 // We know that our mimes list always has the first mime
@@ -149,6 +149,10 @@ public function is_image(?string $blank, string $params): bool
149149 if ($ this ->hasInvalidImageClientExtension ($ file )) {
150150 return false ;
151151 }
152+
153+ if ($ this ->hasUnsafeClientFilename ($ file )) {
154+ return false ;
155+ }
152156 }
153157
154158 return true ;
@@ -173,7 +177,7 @@ public function mime_in(?string $blank, string $params): bool
173177 }
174178
175179 if ($ file ->getError () === UPLOAD_ERR_NO_FILE ) {
176- return true ;
180+ continue ;
177181 }
178182
179183 if (! in_array ($ file ->getMimeType (), $ params , true )) {
@@ -183,6 +187,10 @@ public function mime_in(?string $blank, string $params): bool
183187 if ($ this ->hasMismatchedClientExtension ($ file )) {
184188 return false ;
185189 }
190+
191+ if ($ this ->hasUnsafeClientFilename ($ file )) {
192+ return false ;
193+ }
186194 }
187195
188196 return true ;
@@ -207,7 +215,7 @@ public function ext_in(?string $blank, string $params): bool
207215 }
208216
209217 if ($ file ->getError () === UPLOAD_ERR_NO_FILE ) {
210- return true ;
218+ continue ;
211219 }
212220
213221 // Check the real filename extension, not only the guessed extension.
@@ -220,6 +228,10 @@ public function ext_in(?string $blank, string $params): bool
220228 if ($ file ->guessExtension () !== $ clientExtension ) {
221229 return false ;
222230 }
231+
232+ if ($ this ->hasUnsafeClientFilename ($ file )) {
233+ return false ;
234+ }
223235 }
224236
225237 return true ;
@@ -245,7 +257,11 @@ public function max_dims(?string $blank, string $params): bool
245257 }
246258
247259 if ($ file ->getError () === UPLOAD_ERR_NO_FILE ) {
248- return true ;
260+ continue ;
261+ }
262+
263+ if ($ file ->getError () !== UPLOAD_ERR_OK ) {
264+ return false ;
249265 }
250266
251267 // Get Parameter sizes
@@ -291,7 +307,11 @@ public function min_dims(?string $blank, string $params): bool
291307 }
292308
293309 if ($ file ->getError () === UPLOAD_ERR_NO_FILE ) {
294- return true ;
310+ continue ;
311+ }
312+
313+ if ($ file ->getError () !== UPLOAD_ERR_OK ) {
314+ return false ;
295315 }
296316
297317 // Get Parameter sizes
@@ -346,4 +366,35 @@ private function hasMismatchedClientExtension(UploadedFile $file): bool
346366
347367 return $ file ->guessExtension () !== $ clientExtension ;
348368 }
369+
370+ /**
371+ * Reject trailing-dot names and names with a PHP extension before the final extension.
372+ */
373+ private function hasUnsafeClientFilename (UploadedFile $ file ): bool
374+ {
375+ helper ('security ' );
376+
377+ // Check the name that UploadedFile::move() uses when no name is supplied.
378+ $ filename = sanitize_filename ($ file ->getClientName ());
379+ $ parts = explode ('. ' , strtolower (rtrim ($ filename , ' ' )));
380+
381+ if (count ($ parts ) === 1 ) {
382+ return false ;
383+ }
384+
385+ if (array_pop ($ parts ) === '' ) {
386+ return true ;
387+ }
388+
389+ // Some server configurations select a PHP handler from an earlier extension.
390+ array_shift ($ parts );
391+
392+ foreach ($ parts as $ part ) {
393+ if (preg_match ('/^php[0-9]*$/ ' , $ part ) === 1 || in_array ($ part , ['pht ' , 'phtml ' , 'phar ' , 'phps ' ], true )) {
394+ return true ;
395+ }
396+ }
397+
398+ return false ;
399+ }
349400}
0 commit comments