php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #79875 getenv() can't get the right binary string passed by putenv()
Submitted: 2020-07-18 17:02 UTC Modified: 2020-07-18 20:13 UTC
Votes:2
Avg. Score:3.0 ± 1.0
Reproduced:1 of 2 (50.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: paulbalandan at gmail dot com Assigned:
Status: Verified Package: *General Issues
PHP Version: 7.4.8 OS: Windows 10
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: paulbalandan at gmail dot com
New email:
PHP Version: OS:

 

 [2020-07-18 17:02 UTC] paulbalandan at gmail dot com
Description:
------------
In Windows when posting binary string to the environment via putenv and then getting it back via getenv, the results are different.

Test script:
---------------
<?php

$bin = hex2bin('f699c7fd18a8e082d0228932f3acd40e1ef5ef92efcedda32842a211d62f0aa6');

putenv("key=$bin");

$bin2 = getenv('key', true);

var_dump(bin2hex($bin) === bin2hex($bin2));


Expected result:
----------------
bool(true)

Actual result:
--------------
bool(false)

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-07-18 20:13 UTC] cmb@php.net
-Status: Open +Status: Verified -Type: Bug +Type: Documentation Problem
 [2020-07-18 20:13 UTC] cmb@php.net
As of PHP 7.1.0, PHP on Windows has transparent support for
Unicode file paths[1], and that also applies to environment
variables (the values and the keys).  Since environment variables
are usually character strings (and not general binary strings),
this increases interoperability overall.  I would suggest not to
store arbitrary binary strings as values of environment variables,
but as character strings instead (e.g. in this case you could
store the hexadecimal string in the first place, and hex2bin() it
after retrieval).  If you absolutely need to store such binary
strings in environment variables, you should convert them first to
Unicode (i.e. UTF-8, because UTF-16 and UTF-32 code pages are only
available to managed applications[2], and UTF-7 is … to be
avoided), e.g.

    <?php
    $bin = sapi_windows_cp_conv(
        sapi_windows_cp_get('ansi'),
        65001, // UTF-8 codepage
        hex2bin('f699c7fd18a8e082d0228932f3acd40e1ef5ef92efcedda32842a211d62f0aa6')
    );
    putenv("key=$bin");
    $bin2 = getenv('key', true);
    var_dump(bin2hex($bin) === bin2hex($bin2));
    ?>

So this is expected, but currently undocumented behavior.

[1] <https://www.php.net/manual/en/migration71.windows-support.php#migration71.windows-support.long-and-utf8-path>
[2] <https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers>
 [2020-07-19 12:41 UTC] paulbalandan at gmail dot com
Thank you for that excellent explanation.

One interesting note to add is that once you did that, the binary string is now converted to UTF-8 and cannot be blindly compared against the raw binary string. You need to convert it back to ANSI codepage (1252).

<?php
$bin = hex2bin('f699c7fd18a8e082d0228932f3acd40e1ef5ef92efcedda32842a211d62f0aa6');
$bin1 = sapi_windows_cp_conv(1252, 65001, $bin); // converted to UTF-8
putenv("key=$bin1");
$bin2 = getenv('key', true);
$bin3 = sapi_windows_cp_conv(65001, 1252, $bin2); // converted back to ANSI

var_dump(bin2hex($bin1) === bin2hex($bin2)); // bool(true)
var_dump(bin2hex($bin) === bin2hex($bin2)); // bool(false)
var_dump(bin2hex($bin) === bin2hex($bin3)); // bool(true)

And yes, this definitely needs to be documented.
 [2023-01-04 06:53 UTC] a dot minari242 at gmail dot com
That was sso amaz9ng. 

(https://www.myccpay.one/)github.com
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Dec 30 17:01:29 2024 UTC