Search code examples
phpchecksumpharhotpatching

how to hotpatch phar package?


how do you hotpatch a phar package? for example if i want to hotpatch

if (function_exists('posix_getuid') && posix_getuid() === 0) {
if ($commandName !== 'self-update' && $commandName !== 'selfupdate') {
$io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');

from composer into

if (false && posix_getuid() === 0) {
if ($commandName !== 'self-update' && $commandName !== 'selfupdate') {
$io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');

how should i do that? just editing the code normally results in

PHP Fatal error:  Uncaught PharException: phar "/usr/local/bin/composer" has a broken signature in /usr/local/bin/composer:28
Stack trace:
#0 /usr/local/bin/composer(28): Phar::mapPhar()
#1 {main}
  thrown in /usr/local/bin/composer on line 28

Solution

  • first unpack the phar:

    rm -rfv unpacked;
    mkdir unpacked;
    php --define open_basedir= --define phar.readonly=0 -r '(new Phar("composer.phar"))->convertToExecutable(Phar::TAR,Phar::NONE)->extractTo("unpacked/");'
    

    then do your patching in the unpacked dir, in your case unpacked/src/Composer/Console/Application.php , then re-pack the phar:

    rm -f hotpatched.phar;
    php --define open_basedir= --define phar.readonly=0 -r '$phar=new Phar("hotpatched.phar");$phar->buildFromDirectory("unpacked");$phar->setStub("#!/usr/bin/env php\n".$phar->createDefaultStub("bin/composer"));'
    

    but replace bin/composer with the phar package's real entrypoint (in the case of composer, it's bin/composer ) then make the hotpatched phar executable:

    chmod +x hotpached.phar
    

    and voila, your phar is patched :) the phar even works with php.ini phar.require_hash=1

    tip: you can add $phar->compress(Phar::BZ2); if you want the phar compressed/smaller