Skip to content

Module regression from 1.4.1 to 1.5.0 #99

@zeryl

Description

@zeryl

Updated a CentOS server, from pecl ssh2 version 1.4.1 to 1.5.0, and completely changed/broke the existing ssh/sftp connectivity we had built.

Below is a short example showing the issue at hand.

<?php
/**
 * Minimal reproduction: ssh2.sftp:// stream wrapper opendir() failure
 *
 * Tests whether opendir() works via the ssh2.sftp:// stream wrapper.
 * Known behavior:
 *   php-pecl-ssh2 1.4.1 -- opendir() returns a valid handle
 *   php-pecl-ssh2 1.5.0 -- opendir() returns false (regression)
 *
 * Usage:
 *   php ssh2_stream_wrapper_repro.php <host> <port> <user> <password> [<dir>]
 *
 * Example:
 *   php ssh2_stream_wrapper_repro.php sftp.example.com 22 myuser mypassword /
 */

if ($argc < 5) {
    fprintf(STDERR, "Usage: %s <host> <port> <user> <password> [<dir>]\n", $argv[0]);
    exit(1);
}

$host = $argv[1];
$port = (int)$argv[2];
$user = $argv[3];
$pwd  = $argv[4];
$dir  = isset($argv[5]) ? $argv[5] : "/";

echo "ssh2 extension version : " . phpversion("ssh2") . "\n";
echo "PHP version            : " . PHP_VERSION . "\n";
echo "Host                   : {$host}:{$port}\n";
echo "User                   : {$user}\n";
echo "Directory              : {$dir}\n";
echo str_repeat("-", 50) . "\n";

// Step 1: connect
echo "ssh2_connect()         : ";
$conn = ssh2_connect($host, $port);
var_dump($conn);
if (!$conn) { echo "FAIL: could not connect\n"; exit(1); }

// Step 2: authenticate
echo "ssh2_auth_password()   : ";
$auth = ssh2_auth_password($conn, $user, $pwd);
var_dump($auth);
if (!$auth) { echo "FAIL: authentication failed\n"; exit(1); }

// Step 3: open SFTP subsystem
echo "ssh2_sftp()            : ";
$sftp = ssh2_sftp($conn);
var_dump($sftp);
if (!$sftp) { echo "FAIL: could not open SFTP subsystem\n"; exit(1); }

// Step 4: show how the resource looks and what intval() gives
echo "intval(\$sftp)          : ";
var_dump(intval($sftp));

// Step 5: build the stream wrapper URL
$url = "ssh2.sftp://" . intval($sftp) . $dir;
echo "Stream wrapper URL     : {$url}\n";

// Step 6: the actual test — opendir via stream wrapper
echo "opendir()              : ";
$handle = opendir($url);
var_dump($handle);

if ($handle === false) {
    echo "FAIL: opendir() returned false — stream wrapper is broken\n";
    exit(1);
}

// Step 7: list a few entries to confirm it actually works
echo "Directory listing      :\n";
$count = 0;
while (false !== ($entry = readdir($handle))) {
    if ($entry === "." || $entry === "..") continue;
    echo "  {$entry}\n";
    if (++$count >= 10) { echo "  (truncated after 10 entries)\n"; break; }
}
closedir($handle);

echo str_repeat("-", 50) . "\n";
echo "PASS: stream wrapper opendir() works correctly\n";

Examples of each:

v1.4.1:

php tmp.php host.com 22 user REDACTED /
ssh2 extension version : 1.4.1
PHP version            : 8.4.20
Host                   : host.com:22
User                   : user
Directory              : /
--------------------------------------------------
ssh2_connect()         : resource(4) of type (SSH2 Session)
ssh2_auth_password()   : bool(true)
ssh2_sftp()            : resource(5) of type (SSH2 SFTP)
intval($sftp)          : int(5)
Stream wrapper URL     : ssh2.sftp://5/
opendir()              : resource(7) of type (stream)
Directory listing      :
  boot
  dev
  home
  proc
  run
  sys
  tmp
  etc
  root
  var
  (truncated after 10 entries)

v1.5.0

php tmp.php host.com 22 user REDACTED /
ssh2 extension version : 1.5.0
PHP version            : 8.4.20
Host                   : host.com:22
User                   : user
Directory              : /
--------------------------------------------------
ssh2_connect()         : resource(4) of type (SSH2 Session)
ssh2_auth_password()   : bool(true)
ssh2_sftp()            : resource(5) of type (SSH2 SFTP)
intval($sftp)          : int(5)
Stream wrapper URL     : ssh2.sftp://5/
opendir()              : bool(false)
FAIL: opendir() returned false — stream wrapper is broken

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions