@@ -359,7 +359,6 @@ PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle)
359359 char * path_info ;
360360 zend_string * filename = NULL ;
361361 zend_string * resolved_path = NULL ;
362- size_t length ;
363362 bool orig_display_errors ;
364363
365364 memset (file_handle , 0 , sizeof (zend_file_handle ));
@@ -372,7 +371,7 @@ PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle)
372371 if (s ) { /* if there is no path name after the file, do not bother */
373372 char user [32 ]; /* to try open the directory */
374373
375- length = s - (path_info + 2 );
374+ size_t length = s - (path_info + 2 );
376375 if (length > sizeof (user ) - 1 ) {
377376 length = sizeof (user ) - 1 ;
378377 }
@@ -421,19 +420,37 @@ PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle)
421420 }
422421 } else
423422#endif
424- if (PG (doc_root ) && path_info && (length = strlen (PG (doc_root ))) &&
425- IS_ABSOLUTE_PATH (PG (doc_root ), length )) {
426- size_t path_len = strlen (path_info );
427- filename = zend_string_alloc (length + path_len + 2 , 0 );
428- memcpy (ZSTR_VAL (filename ), PG (doc_root ), length );
429- if (!IS_SLASH (ZSTR_VAL (filename )[length - 1 ])) { /* length is never 0 */
430- ZSTR_VAL (filename )[length ++ ] = PHP_DIR_SEPARATOR ;
431- }
432- if (IS_SLASH (path_info [0 ])) {
433- length -- ;
434- }
435- strncpy (ZSTR_VAL (filename ) + length , path_info , path_len + 1 );
436- ZSTR_LEN (filename ) = length + path_len ;
423+ if (PG (doc_root ) && path_info && IS_ABSOLUTE_PATH (ZSTR_VAL (PG (doc_root )), ZSTR_LEN (PG (doc_root )))) {
424+ const size_t path_len = strlen (path_info );
425+
426+ /* We need to concatenate two paths together, there are 3 situations:
427+ * - No trailing slash AND no leading slash
428+ * - Trailing slash AND leading slash
429+ * - Either a trailing slash OR a leading slash
430+ * In the first case we need to add a slash, in the second one we need to skip the leading slash,
431+ * and in the third we can just concatenate them together */
432+ const unsigned int nb_slashes = IS_SLASH (ZSTR_VAL (PG (doc_root ))[ZSTR_LEN (PG (doc_root )) - 1 ]) + IS_SLASH (path_info [0 ]);
433+ switch (nb_slashes ) {
434+ case 0 :
435+ filename = zend_string_concat3 (
436+ ZSTR_VAL (PG (doc_root )), ZSTR_LEN (PG (doc_root )),
437+ ZEND_STRL ("/" ),
438+ path_info , path_len
439+ );
440+ break ;
441+ case 1 :
442+ filename = zend_string_concat2 (
443+ ZSTR_VAL (PG (doc_root )), ZSTR_LEN (PG (doc_root )),
444+ path_info , path_len
445+ );
446+ break ;
447+ case 2 :
448+ filename = zend_string_concat2 (
449+ ZSTR_VAL (PG (doc_root )), ZSTR_LEN (PG (doc_root )),
450+ path_info + 1 , path_len - 1
451+ );
452+ break ;
453+ }
437454 } else if (SG (request_info ).path_translated ) {
438455 filename = zend_string_init (SG (request_info ).path_translated ,
439456 strlen (SG (request_info ).path_translated ), 0 );
0 commit comments