Skip to content

Module regression from 1.4.1 to 1.5.0 #99

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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions