php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #80731 escapeshellarg() silently corrupts "\xFF" on linux
Submitted: 2021-02-11 15:03 UTC Modified: 2022-03-11 09:34 UTC
From: divinity76 at gmail dot com Assigned: cmb (profile)
Status: Duplicate Package: Program Execution
PHP Version: 8.0.2 OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: divinity76 at gmail dot com
New email:
PHP Version: OS:

 

 [2021-02-11 15:03 UTC] divinity76 at gmail dot com
Description:
------------
escapeshellarg() silently corrupts "\xFF" on linux

Test script:
---------------
<?php
/**
 * quote arguments using linux escape rules, regardless of host OS
 * (eg, it will use linux escape rules even when running on Windows)
 *
 * @param string $arg
 * @throws \InvalidArgumentException if argument contains null bytes
 * @return string
 */
function linux_escapeshellarg(string $arg): string
{
    if (false !== strpos($arg, "\x00")) {
        throw new \InvalidArgumentException("argument contains null bytes, it's impossible to escape null bytes!");
    }
    return "'" . strtr($arg, [
        "'" => "'\\''"
    ]) . "'";
}

$cmd = "printf '%s' ".linux_escapeshellarg("\xFF");
var_dump(bin2hex(shell_exec($cmd)));
// ^ works fine.
$cmd = "printf '%s' ".escapeshellarg("\xFF");
var_dump(bin2hex(shell_exec($cmd)));
// ^ is corrupted..

Expected result:
----------------
string(2) "ff"
string(2) "ff"

Actual result:
--------------
string(2) "ff"
string(0) ""

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-02-11 15:34 UTC] divinity76 at gmail dot com
FWIW this returns bool(true): 

<?php
function linux_escapeshellarg(string $arg):string{
    if(false!==strpos($arg, "\x00")){
        throw new \InvalidArgumentException("argument contains null bytes, it's impossible to escape null bytes!");
    }
    return "'".strtr($arg,["'"=>"'\\''"])."'";
}
$everything_except_null = "";
for($i=1;$i<=0xFF;++$i){
    $everything_except_null.=chr($i);
}
$cmd = "printf '%s' ".linux_escapeshellarg($everything_except_null);
$res = shell_exec($cmd);
var_dump($res === $everything_except_null);
 [2021-02-11 15:40 UTC] cmb@php.net
-Status: Open +Status: Verified -Type: Bug +Type: Documentation Problem -Package: *Data Exchange functions +Package: Program Execution
 [2021-02-11 15:40 UTC] cmb@php.net
If mblen() is available on the system, escapeshellarg() works on
multibyte characters according to the system locale[1], and skips
invalid characters[2].  This is, however, not documented.

[1] <https://3v4l.org/rdjpk>
[2] <https://github.com/php/php-src/blob/c6723538054d96291abb6bad4628b9f55bc7fc17/ext/standard/exec.c#L313>
 [2021-02-11 16:27 UTC] divinity76 at gmail dot com
@cmd interesting, but that begs the question, why does it only complain when given null bytes, and not complain when given locale-invalid-characters?
 [2022-03-11 09:34 UTC] cmb@php.net
-Status: Verified +Status: Duplicate -Assigned To: +Assigned To: cmb
 [2022-03-11 09:34 UTC] cmb@php.net
> why does it only complain when given null bytes, and not
> complain when given locale-invalid-characters?

There is an explicit check for NUL bytes, since these mark the end
of C strings, and as such may cause particularly dangerous
behavior.

Anyhow, closing as duplicate of
<https://github.com/php/doc-en/issues/1452>.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Dec 22 03:01:28 2024 UTC