Skip to content

Env vars with non-ASCII values are mangled when read from $_SERVER on Windows #7896

Closed

Description

@Seldaek

Description

The following code:

<?php
var_dump(
    $_SERVER['FOO'] ?? 'unset', 
    $_ENV['FOO'] ?? 'unset', 
    getenv('FOO')
);

When run with variables_order = "EGPCS" and FOO=GüИter传 set in the environment variables in Windows (or using $env:FOO = 'GüИter传' in PowerShell before executing the test file above).

Resulted in this output:

string(7) "G?ter?"
string(7) "G?ter?"
string(11) "GüИter传"

But I expected this output instead:

string(11) "GüИter传"
string(11) "GüИter传"
string(11) "GüИter传"

Doing the same in WSL/Ubuntu seems to yield the correct result, so I assume it's Windows specific.

Regarding PHP version, it appears all versions <7.2 fail completely, with even getenv() returning string(7) "G?ter?" or string(7) "Gⁿ?ter?" for 5.x. From PHP 7.2 onwards I get the behavior described above.

PHP Version

8.0.13

Operating System

Windows 10

Activity

  1. cmb69 commented on Jan 6, 2022

    @cmb69
    Member

    From PHP 7.2 onwards I get the behavior described above.

    This is likely due to fixing https://bugs.php.net/75574, so should be fixed as of PHP 7.1.13 and 7.2.1, respectively. That fix only affected getenv(), though, but not _php_import_environment_variables (and possibly other places).

  2. self-assigned this
    on Jan 6, 2022
  3. Seldaek commented on Jan 6, 2022

    @Seldaek
    Author

    Thanks, do you see any way to mitigate/detect this in userland?

    I see that doing this when starting up to ensure $_SERVER is in a good state appears to work.. not sure if there's a better way:

    foreach ($_SERVER as $var => $val) {
        if (($val = getenv($var)) !== false) {
            $_SERVER[$var] = $val;
        }
    }
    

    Once fixed in a release I'll at least be able to exclude this hackery from newer PHP versions.

  4. cmb69 commented on Jan 6, 2022

    @cmb69
    Member

    Nope, no better idea per se, but note that this wouldn't help with env var names containing non-ASCII characters (e.g. FÖÖ=bar). If that's important, you could traverse getenv() instead (that's likely a bit faster anyway).

  5. Seldaek commented on Jan 6, 2022

    @Seldaek
    Author

    Ok yes using getenv() once makes more sense, although we're really only interested in ascii vars in the context of Composer.

  6. Seldaek commented on Jan 7, 2022

    @Seldaek
    Author

    @cmb69 it's been brought to my attention that calling getenv() also still suffers from the same issue and mangles unicode values. Only getenv('FOO') appears to work correctly.

    So here's a working workaround: https://github.com/composer/composer/blob/d9619985dbabb58255fb27cf78fe702345d31793/bin/composer#L68-L76

  7. cmb69 commented on Jan 7, 2022

    @cmb69
    Member

    Argh! getenv() without parameter also calls php_import_environment_variables(), and I tested with an already patched version.

  8. added a commit that references this issue on Jan 11, 2022
    fbdace5
  9. added 2 commits that reference this issue on Jan 17, 2022
    93a3c71
    8d2ed19
  10. added a commit that references this issue on Jan 17, 2022
    3e32717
  11. Seldaek commented on Jan 21, 2022

    @Seldaek
    Author

    Thanks @cmb69 !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions