Skip to content

realpath and readfile (and probably others in zend_virtual_cwd) fail with valid path of length 4095 #9903

@SlivTaMere

Description

@SlivTaMere

Description

The following code:

<?php
$p = "/bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/../bin/sh";
var_dump(PHP_MAXPATHLEN);
var_dump(strlen($p));
var_dump(file_exists($p));
var_dump(realpath($p));

Resulted in this output:

int(4096)
int(4095)
bool(true)
bool(false)

But I expected this output instead:

int(4096)
int(4095)
bool(true)
string(7) "/bin/sh" //or similar

I didn't dig much but I think the issue is at Zend/zend_virtual_cwd.c , a path of length 4095 should be accepted as it is the case with file_exists() and stat family functions.

I didn't test with PHP 8 but probably has the same issue.

PHP Version

PHP 7.4.33

Operating System

Ubuntu 18.04.6

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions