-
Notifications
You must be signed in to change notification settings - Fork 64
Open
Description
Bug: Fragment part of path lost in PHP >= 7.3
Summary
Files with # character in their name cannot be accessed via ssh2.sftp:// stream wrapper in PHP >= 7.3 due to a regression in php_ssh2_fopen_wrapper_parse_path().
Description
The function php_ssh2_fopen_wrapper_parse_path() in ssh2_fopen_wrappers.c has different code paths for PHP < 7.3 and PHP >= 7.3. The comment says:
/*
Find resource->path in the path string, then copy the entire string from the original path.
This includes ?query#fragment in the path string
*/However, the PHP >= 7.3 code doesn't actually preserve the fragment:
#if PHP_VERSION_ID < 70300
{
char * s;
s = resource->path;
resource->path = estrdup(strstr(path, resource->path)); // Correct: copies including #fragment
efree(s);
}
#else
{
zend_string *tmp;
tmp = resource->path;
resource->path = zend_string_init(ZSTR_VAL(resource->path), ZSTR_LEN(resource->path), 0); // Bug: just copies same length
zend_string_release(tmp);
}
#endifThe PHP < 7.3 version uses strstr() to find the path in the original string and copies from that position to the end, preserving the #fragment. The PHP >= 7.3 version just creates a copy with the same length, losing everything after #.
Steps to Reproduce
$connection = ssh2_connect('example.com', 22);
ssh2_auth_password($connection, 'user', 'pass');
$sftp = ssh2_sftp($connection);
$path = '/test#file.txt';
$url = 'ssh2.sftp://' . (int) $sftp . $path;
file_put_contents($url, 'test'); // Creates file named "test" instead of "test#file.txt"Expected Result
File test#file.txt is created.
Actual Result
File test is created (everything after # is lost).
Environment
- PHP 8.4.13
- ssh2 extension from PECL
Suggested Fix
#else
{
const char *path_in_original = strstr(path, ZSTR_VAL(resource->path));
if (path_in_original) {
zend_string_release(resource->path);
resource->path = zend_string_init(path_in_original, strlen(path_in_original), 0);
}
}
#endifReactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels