From 1343cdf28f474569a8ed38335a98aa8dc579e29d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Fri, 31 Mar 2023 11:51:21 +0200 Subject: [PATCH 1/8] feat: Enrich InvalidPhar exception --- fixtures/phar/Empty.pdf | Bin 0 -> 3832 bytes src/Phar/PharFactory.php | 43 ++++++++++++++ src/Pharaoh/InvalidPhar.php | 35 +++++++++--- tests/Phar/PharFactoryTest.php | 100 +++++++++++++++++++++++++++++++++ 4 files changed, 169 insertions(+), 9 deletions(-) create mode 100644 fixtures/phar/Empty.pdf create mode 100644 src/Phar/PharFactory.php create mode 100644 tests/Phar/PharFactoryTest.php diff --git a/fixtures/phar/Empty.pdf b/fixtures/phar/Empty.pdf new file mode 100644 index 0000000000000000000000000000000000000000..25df6147af4613b75a7edfc7faf628d64e5d6c2a GIT binary patch literal 3832 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

iKDLzNGz z%)f74J}{Tbdwjq@DzI=;YCUW5(F@Bc%j~|leUXoDD^kuIoFASH?#|fPxld00#>Rz( zn8md8@@G!^%=pgTH*ct9`Ck02)e<%z9VrxX^ekPix?=2QMoC%8P)A5gsqOq@TEQE} z+BdV5BBv4+n`40)fsEPk_1M1sHJR7#W-d}DAI`ZmCOym7ua6dAtp)jY)n-j$Xt6qw zb#)_SFGuv&)sOPE=QnKMs!j$Dt#@%2Y`0Z^9-zGLyzVeFnj-}>Je*mmUcBDB-0xVx zSeUuhZ_g~h;uIHNg;m%{UMV$f+`=qi9?`APox&C4m@z9cg8}y!nm={Kq;!vl)yaH+ zw3OUcly%W}jp0OWZ~ElgHJzq@a_DZY%4*-D`vmF3Shp`_E-yc7sHj$bF=Rb^&0(Q6 zesace*)TaPR^9gk_qWe}lJ1VS%{J$Vt z@#lhHW`KeP-V)UQLUwTQ_nuXLx2DkD$bhttyC>aW2DGM8N!|`%Gb8Oza4<9h%*iw_ z3e^KZAmkMRYiTWSiW><)!f^;ijI|74>`kE20|1cqe>4w%bQzce7VLEBRM23v>F@$A ze+Zz5_9o6tYad0zktjF{g@CJ|(Fl|!94-a^zA>bi0NXJ=4@WAnS-H)zHh5)@V;mJx z$_RuCnuu^jD3eea5}brlBoQ$f3_%frMySF5|CGP3oEIIegetMessage(), 'Cannot create a phar archive from a URL like')) { + return sprintf( + 'Cannot create a PHAR object from a URL like "%s". PHAR objects can only be created from local files.', + $file, + ); + } + } + + return self::couldNotVerifyOpenSSLSignature($throwable) + ? sprintf( + 'Could not create a Phar or PharData instance for the file "%s": the OpenSSL signature could not be verified.', + $file, + ) + : sprintf( + 'Could not create a Phar or PharData instance for the file "%s".', + $file, + ); + } + private static function couldNotVerifyOpenSSLSignature(?Throwable $previous): bool { return null !== $previous diff --git a/tests/Phar/PharFactoryTest.php b/tests/Phar/PharFactoryTest.php new file mode 100644 index 000000000..18a570aaa --- /dev/null +++ b/tests/Phar/PharFactoryTest.php @@ -0,0 +1,100 @@ +expectException(InvalidPhar::class); + $this->expectExceptionMessageMatches($expectedExceptionMessageRegex); + + PharFactory::createPhar($file); + } + + public static function invalidPharProvider(): iterable + { + yield 'URL of a valid PHAR' => [ + 'https://github.com/box-project/box/releases/download/4.3.8/box.phar', + '/^Cannot create a PHAR object from a URL like ".+"\. PHAR objects can only be created from local files\.$/', + ]; + + yield 'x' => [ + self::FIXTURES_DIR.'/../phar/Empty.pdf', + '/^foo\.$/', + ]; + + // TODO: + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1330 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1343 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1351 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1430 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#LL1565C45-L1565C45 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1669 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1694 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1705 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1708 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1721 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1730 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1735 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1743 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1750 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1763 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L529 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L853 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L874 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L892 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L903 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L921 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L931 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L948 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L958 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L975 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L985 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1002 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1012 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1024 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1033 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1064 + } + + public function test_it_fails_with_a_comprehensive_error_when_cannot_create_a_phar_data(): void + { +$this->markTestSkipped(); + } +} From 545b2cef0612b4c52586977636c8d79eb5c66c37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Sat, 1 Apr 2023 14:18:29 +0200 Subject: [PATCH 2/8] refactor: Introduce a PharFactory and rework InvalidPhar --- fixtures/phar/README.md | 34 +++ .../phar/corrupted-phar-altered-binary.phar | Bin 0 -> 6779 bytes .../phar/corrupted-phar-altered-binary.tar | Bin 0 -> 6779 bytes .../corrupted-phar-altered-included-file.phar | Bin 0 -> 6820 bytes .../corrupted-phar-altered-included-file.tar | Bin 0 -> 6820 bytes .../phar/corrupted-phar-altered-stub.phar | Bin 0 -> 6833 bytes fixtures/phar/corrupted-phar-altered-stub.tar | Bin 0 -> 6833 bytes fixtures/phar/corrupted-simple.zip | Bin 0 -> 214 bytes .../phar/corruted-phar-no-halt-compiler.phar | Bin 0 -> 6757 bytes fixtures/phar/empty-file.phar | 0 fixtures/phar/empty-file.zip | 0 fixtures/phar/{Empty.pdf => empty-pdf.pdf} | Bin fixtures/phar/openssl-keys/README.md | 5 + fixtures/phar/openssl-keys/private-key.pem | 27 ++ fixtures/phar/openssl-keys/public-key.pem | 9 + fixtures/phar/openssl-pass-keys/README.md | 5 + fixtures/phar/openssl-pass-keys/passphrase | 1 + .../phar/openssl-pass-keys/private-key.pem | 27 ++ .../phar/openssl-pass-keys/public-key.pem | 9 + fixtures/phar/simple-phar-md5-sign.phar | Bin 0 -> 6761 bytes ...le-phar-openssl-sign-with-diff-pubkey.phar | Bin 0 -> 7005 bytes ...phar-openssl-sign-with-invalid-pubkey.phar | Bin 0 -> 7005 bytes ...enssl-sign-with-invalid-pubkey.phar.pubkey | 0 ...mple-phar-openssl-sign-without-pubkey.phar | Bin 0 -> 7005 bytes fixtures/phar/simple-phar-openssl-sign.phar | Bin 0 -> 7005 bytes .../phar/simple-phar-openssl-sign.phar.pubkey | 9 + fixtures/phar/simple-phar-openssl-sign.tar | Bin 0 -> 7005 bytes fixtures/phar/simple-phar-sha1-sign.phar | Bin 0 -> 6765 bytes fixtures/phar/simple-phar-sha256-sign.phar | Bin 0 -> 6777 bytes fixtures/phar/simple-phar-sha512-sign.phar | Bin 0 -> 6809 bytes fixtures/phar/simple-phar.phar | Bin 0 -> 6777 bytes fixtures/phar/simple.tar | Bin 0 -> 2048 bytes fixtures/phar/simple.tar.bz2 | Bin 0 -> 118 bytes fixtures/phar/simple.tar.bz2.phar | Bin 0 -> 118 bytes fixtures/phar/simple.tar.gz | Bin 0 -> 105 bytes fixtures/phar/simple.tar.gz.phar | Bin 0 -> 105 bytes fixtures/phar/simple.tar.phar | Bin 0 -> 2048 bytes fixtures/phar/simple.zip | Bin 0 -> 213 bytes fixtures/phar/simple.zip.phar | Bin 0 -> 213 bytes src/Console/Command/Extract.php | 2 +- src/Phar/PharFactory.php | 48 +++- src/Pharaoh/InvalidPhar.php | 117 ++++++-- src/Pharaoh/Pharaoh.php | 2 +- tests/Phar/PharFactoryTest.php | 270 ++++++++++++++---- 44 files changed, 485 insertions(+), 80 deletions(-) create mode 100644 fixtures/phar/README.md create mode 100644 fixtures/phar/corrupted-phar-altered-binary.phar create mode 100644 fixtures/phar/corrupted-phar-altered-binary.tar create mode 100644 fixtures/phar/corrupted-phar-altered-included-file.phar create mode 100644 fixtures/phar/corrupted-phar-altered-included-file.tar create mode 100644 fixtures/phar/corrupted-phar-altered-stub.phar create mode 100644 fixtures/phar/corrupted-phar-altered-stub.tar create mode 100644 fixtures/phar/corrupted-simple.zip create mode 100644 fixtures/phar/corruted-phar-no-halt-compiler.phar create mode 100644 fixtures/phar/empty-file.phar create mode 100644 fixtures/phar/empty-file.zip rename fixtures/phar/{Empty.pdf => empty-pdf.pdf} (100%) create mode 100644 fixtures/phar/openssl-keys/README.md create mode 100644 fixtures/phar/openssl-keys/private-key.pem create mode 100644 fixtures/phar/openssl-keys/public-key.pem create mode 100644 fixtures/phar/openssl-pass-keys/README.md create mode 100644 fixtures/phar/openssl-pass-keys/passphrase create mode 100644 fixtures/phar/openssl-pass-keys/private-key.pem create mode 100644 fixtures/phar/openssl-pass-keys/public-key.pem create mode 100644 fixtures/phar/simple-phar-md5-sign.phar create mode 100644 fixtures/phar/simple-phar-openssl-sign-with-diff-pubkey.phar create mode 100644 fixtures/phar/simple-phar-openssl-sign-with-invalid-pubkey.phar create mode 100644 fixtures/phar/simple-phar-openssl-sign-with-invalid-pubkey.phar.pubkey create mode 100644 fixtures/phar/simple-phar-openssl-sign-without-pubkey.phar create mode 100644 fixtures/phar/simple-phar-openssl-sign.phar create mode 100644 fixtures/phar/simple-phar-openssl-sign.phar.pubkey create mode 100644 fixtures/phar/simple-phar-openssl-sign.tar create mode 100644 fixtures/phar/simple-phar-sha1-sign.phar create mode 100644 fixtures/phar/simple-phar-sha256-sign.phar create mode 100644 fixtures/phar/simple-phar-sha512-sign.phar create mode 100644 fixtures/phar/simple-phar.phar create mode 100644 fixtures/phar/simple.tar create mode 100644 fixtures/phar/simple.tar.bz2 create mode 100644 fixtures/phar/simple.tar.bz2.phar create mode 100644 fixtures/phar/simple.tar.gz create mode 100644 fixtures/phar/simple.tar.gz.phar create mode 100644 fixtures/phar/simple.tar.phar create mode 100644 fixtures/phar/simple.zip create mode 100644 fixtures/phar/simple.zip.phar diff --git a/fixtures/phar/README.md b/fixtures/phar/README.md new file mode 100644 index 000000000..4d6c615e0 --- /dev/null +++ b/fixtures/phar/README.md @@ -0,0 +1,34 @@ +How those files were created: + +empty-pdf.pdf: open a text editor and export as PDF. +simple.zip: create a sample.txt file and compress it `$ zip -r`. +simple.tar & simple.tar.{gz|bz2}: + +```php +$phar = new PharData('simple.tar'); +$phar->addFile('sample.txt'); + +$phar->compress(Phar::GZ); +// ... +``` + +simple.tar.phar & simple.tar.{gz|bz2}.phar: copied the tar variant and added ".phar" manually + +simple.phar: + +```php +$phar = new Phar('simple-phar.phar'); +$phar->addFile('sample.php'); +``` + +corrupted-phar-no-halt-compiler.phar: copied `simple-phar.phar` and removed the `__HALT_COMPILER(); ?>` token. +corrupted-simple.zip: copied `simple.zip`, opened it in a text editor and added "3 " at the beginning of the file + +empty-file.{zip|phar}: created an empty file and renamed it + +simple-phar-openssl-sign.phar: +- https://www.php.net/manual/en/phar.setsignaturealgorithm.php +- use the key in `openssl-keys` + +corrupted-phar-altered-stub.phar: vim the file and add a comment in the stub section +corrupted-phar-altered-binary.phar: open the file in the text editor and add characters after the part identified as an included file diff --git a/fixtures/phar/corrupted-phar-altered-binary.phar b/fixtures/phar/corrupted-phar-altered-binary.phar new file mode 100644 index 0000000000000000000000000000000000000000..62ab0a52daf54e991e1aac281cd1ea0213be7836 GIT binary patch literal 6779 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 TqxI46|Mp= literal 0 HcmV?d00001 diff --git a/fixtures/phar/corrupted-phar-altered-binary.tar b/fixtures/phar/corrupted-phar-altered-binary.tar new file mode 100644 index 0000000000000000000000000000000000000000..62ab0a52daf54e991e1aac281cd1ea0213be7836 GIT binary patch literal 6779 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 TqxI46|Mp= literal 0 HcmV?d00001 diff --git a/fixtures/phar/corrupted-phar-altered-included-file.phar b/fixtures/phar/corrupted-phar-altered-included-file.phar new file mode 100644 index 0000000000000000000000000000000000000000..40fa08b3006bfa9704100306882fe72ecc343c19 GIT binary patch literal 6820 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

BbkEb;-02((ptcQhY3 ziWQ8yTI-+A>J8?m?pDi^{-P2}CHmc5!y7I4BAbQMJ#7@FgSYKWs1;t^zswD*F@~W4 z5#8+W4XFYhOoDi1nUB!x2^@@d6^U7@ez^cukQF`z&r^1gh5}Y$(Pjs;DDWe?8X`%w zz4xT)w-AjkrLHB=Xgr6D)OgjVXe2@ZB9>60>0nifcIJM!z;ze0!{O24aew&y^rVX) zQF?%$JZ^eGJvV!+E8N*E`M6t6e(mUel;mv`Mi|HJ;|_ka98Oul?}^6Y>2V;r*p literal 0 HcmV?d00001 diff --git a/fixtures/phar/corrupted-phar-altered-included-file.tar b/fixtures/phar/corrupted-phar-altered-included-file.tar new file mode 100644 index 0000000000000000000000000000000000000000..40fa08b3006bfa9704100306882fe72ecc343c19 GIT binary patch literal 6820 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

BbkEb;-02((ptcQhY3 ziWQ8yTI-+A>J8?m?pDi^{-P2}CHmc5!y7I4BAbQMJ#7@FgSYKWs1;t^zswD*F@~W4 z5#8+W4XFYhOoDi1nUB!x2^@@d6^U7@ez^cukQF`z&r^1gh5}Y$(Pjs;DDWe?8X`%w zz4xT)w-AjkrLHB=Xgr6D)OgjVXe2@ZB9>60>0nifcIJM!z;ze0!{O24aew&y^rVX) zQF?%$JZ^eGJvV!+E8N*E`M6t6e(mUel;mv`Mi|HJ;|_ka98Oul?}^6Y>2V;r*p literal 0 HcmV?d00001 diff --git a/fixtures/phar/corrupted-phar-altered-stub.phar b/fixtures/phar/corrupted-phar-altered-stub.phar new file mode 100644 index 0000000000000000000000000000000000000000..e7525f4a67d83df32acd737f1fc2e34d8a6e88ea GIT binary patch literal 6833 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 C@gS=J literal 0 HcmV?d00001 diff --git a/fixtures/phar/corrupted-phar-altered-stub.tar b/fixtures/phar/corrupted-phar-altered-stub.tar new file mode 100644 index 0000000000000000000000000000000000000000..e7525f4a67d83df32acd737f1fc2e34d8a6e88ea GIT binary patch literal 6833 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 C@gS=J literal 0 HcmV?d00001 diff --git a/fixtures/phar/corrupted-simple.zip b/fixtures/phar/corrupted-simple.zip new file mode 100644 index 0000000000000000000000000000000000000000..e7d3c9a685a30899ee924d28985f4039b14f035c GIT binary patch literal 214 zcmXqI*LuLLz z+C98s1A~BnfB*vnP(K5|Nza`*Q;T{&{aG?q&Ow2dWkW%WoY!oH4?u%}h5`8kiVlWw li&Bu}Ko-FOmj}>1608N98;}6fEWjYZ+Q7iTRsiBK008XlI|cv% literal 0 HcmV?d00001 diff --git a/fixtures/phar/corruted-phar-no-halt-compiler.phar b/fixtures/phar/corruted-phar-no-halt-compiler.phar new file mode 100644 index 0000000000000000000000000000000000000000..3d9474c8751fb72ec561bed36115fe0472a884b8 GIT binary patch literal 6757 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 literal 0 HcmV?d00001 diff --git a/fixtures/phar/simple-phar-openssl-sign-with-diff-pubkey.phar b/fixtures/phar/simple-phar-openssl-sign-with-diff-pubkey.phar new file mode 100644 index 0000000000000000000000000000000000000000..2a1d4a692d4e85f43bf73d0d3591d556f62689da GIT binary patch literal 7005 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 T_}<2t-^r4 literal 0 HcmV?d00001 diff --git a/fixtures/phar/simple-phar-openssl-sign-with-invalid-pubkey.phar b/fixtures/phar/simple-phar-openssl-sign-with-invalid-pubkey.phar new file mode 100644 index 0000000000000000000000000000000000000000..2a1d4a692d4e85f43bf73d0d3591d556f62689da GIT binary patch literal 7005 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 T_}<2t-^r4 literal 0 HcmV?d00001 diff --git a/fixtures/phar/simple-phar-openssl-sign-with-invalid-pubkey.phar.pubkey b/fixtures/phar/simple-phar-openssl-sign-with-invalid-pubkey.phar.pubkey new file mode 100644 index 000000000..e69de29bb diff --git a/fixtures/phar/simple-phar-openssl-sign-without-pubkey.phar b/fixtures/phar/simple-phar-openssl-sign-without-pubkey.phar new file mode 100644 index 0000000000000000000000000000000000000000..2a1d4a692d4e85f43bf73d0d3591d556f62689da GIT binary patch literal 7005 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 T_}<2t-^r4 literal 0 HcmV?d00001 diff --git a/fixtures/phar/simple-phar-openssl-sign.phar b/fixtures/phar/simple-phar-openssl-sign.phar new file mode 100644 index 0000000000000000000000000000000000000000..2a1d4a692d4e85f43bf73d0d3591d556f62689da GIT binary patch literal 7005 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 T_}<2t-^r4 literal 0 HcmV?d00001 diff --git a/fixtures/phar/simple-phar-openssl-sign.phar.pubkey b/fixtures/phar/simple-phar-openssl-sign.phar.pubkey new file mode 100644 index 000000000..288ba1c48 --- /dev/null +++ b/fixtures/phar/simple-phar-openssl-sign.phar.pubkey @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAywa2fvnQ9yrS6ooOycSC +Ye775MTRq71mujt/c7U52VHbNAcR5bYZ0WV+IgJLqRxSjasUbfrTfMzuW6Ge7kdq +rAmzR3Y1LX4uRrvd3J9LnhR5ATd5ujrHkaS8HVHVVC2xOEUn4Yeo23xOsWYKqDju +DlcZXtjPMofXZBVwX8h9rtWCuLlAqyP4UbcFD4YsSHuVlAIl5SxM0xtYrdkjpENa +YTzJswBDtxfJ5uN7IzwL5C6arbPRw16RvloldvkkVqAkZrNUbdDCG4QQ86lTo0tg +rALcaNK0VDRYmd2jwJK6sOjJpI0zi+/yLGih4cVenmXQzSXm0qbH9Is4E45PaNAT +mQIDAQAB +-----END PUBLIC KEY----- diff --git a/fixtures/phar/simple-phar-openssl-sign.tar b/fixtures/phar/simple-phar-openssl-sign.tar new file mode 100644 index 0000000000000000000000000000000000000000..2a1d4a692d4e85f43bf73d0d3591d556f62689da GIT binary patch literal 7005 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 T_}<2t-^r4 literal 0 HcmV?d00001 diff --git a/fixtures/phar/simple-phar-sha1-sign.phar b/fixtures/phar/simple-phar-sha1-sign.phar new file mode 100644 index 0000000000000000000000000000000000000000..973cd29b3f7965acf472a63545a974278e8b9a34 GIT binary patch literal 6765 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 literal 0 HcmV?d00001 diff --git a/fixtures/phar/simple-phar-sha256-sign.phar b/fixtures/phar/simple-phar-sha256-sign.phar new file mode 100644 index 0000000000000000000000000000000000000000..68ea76cb2bcb2c04872791ce2324911a08c382ba GIT binary patch literal 6777 zcmb_hOK;oQ6;4rfqs^c|fug%>ffLeW$+B#ZGnF03PDY7?v13)%crZ}|fg-OY#(WJ) z`8ApD`UCn0x@tECx-HOdx+%~f(f)&Ox@(vH&VA6NMJ2PSgFw3Hp7%ZXoR8GrlXw=_ zYQ_~Gv&YQzLYH5!gJka3YTkrdUO2Lo#J;i2cxESNgQZ!*?O-(J+2|^<r|F1aduf(hW>2zjVDH-+Ejk@9%y{DPID78-{P{d|Ah}yhp~(v!f9~>8Y-clR zsncqiY@Llp&tD#QMpP4;-7Z8mDABfgm#zs_2*Z+oFh#A<3BS2C}yRgvAyts>8=h<-G! zA}3)bIlIoPxUbVngH+HIY#VW*4D#>xr6;vqdM=Mzv;@aEP%(OeJ>@N0Qa)0dFqtM= zfjIRhQh{WpC8)D3kW`UTtb9fFmynB^HM{3TMb+0$B0%}um>20-P9<68NqTZe#x{j+ z-lHp%xWT^X*qIlFt?TAn`_fLG#EUah8F;Qrk3Dz2s3q2tE>+$mM=JMXLmWL9k0L7<>q)d-pbp*vwhzM1&E*=>?EkRAMDkRcb zyGrNM%Enl%%CY5SgQXS@y}Ez?WvX<*+m(_YOO+bIw2 zfaC7#ua@qrV4xnqf}S2nX+<{@{R|CMONt)j%v>+A%ALl@co361*~mr9E%r?#&fq{g zAH&pgJKx_Awnl@<=b=^bO+`btsA-Z(G|`qx6G%EhlORu+c{CXGTJ7~V+uCTeljxGW ztjCkU4tbdQH|AYx&ErU3kq)DwwAhYCp0Fcl2y8(XgD|6!Vc3WqGt(Etts-rZ`}}3U z`wUa<>(YRedc+Aq2|`jKBmH!umSN*O_B6FZvp6nQ9y;0$w!N{4*&a#I7q*vqna}rWT;EA3A~Ci!=iWGSZ=}eqy-x<3?4DE$8$w30LYVB; z3yC5GLP_$%NkqY^^HigBJTx(%c$lJ9VSdt~>d@$(;LMtXo0xZ4VT=`yQ1cw~aGK5J zK~4}@>fOprQn}hLk)&;XegXx_c`t_O&?tK%T_G+xWEb{Pg^yXA{LOENeHZnI1UE&X z-gM^Ue>Ph5uQ~~+(!I81Z{AUm~+5^su{-K{xMm}cz7 zYn=1Ob$erDLzAAq-W0UW0`27R>V4m=avPx&g`H6}4FqZoZe_rwM>lQG?jNy_wOGHr`yrPvpl zL_@)RqHbESDfCOT>yMd14B%u}GrGB!wn1b8PBlRo6-FQ{MnT06+;=^0ncaT>wBKQ9 zkKTmC0W@D+B;u!s&n6EV=i}PJZO`3N-&DZpsS8hWP(R3 ztwunhOh6a=L*Ual%0EyaD()Ar#g(G@rH?s(_?X^8v5)x(Se*NxBvH~~x4t)Kc_U$7 zis70ujL5N%{@gx58(B6l%=R=gAseO^YnvgF7Y z<(eW3xMkG4g%YtEr2td%i4K~m&7n8|Gtegs{0&y$t*^2bv`BR=i@T&vV21lb%T=wl zm9-UWmAWE|N>^!=QYaK;X(O+dXQFJWFnpT)95W?|qr^^b7=*Z!MfjFQbTIU^$msax z>FZ1u^~zEw6%4o2Y!SDTY?FDZ zRdhM^1R(9I7bqmUFq3tg!63ft4p#4|H#$ATv3~XP6_EQ~V?f9PD_z=&EO{PYTIS%S z2d*bnV1;$(ZrvpYa!ieX1M(CL=~6wwY*ExugT5f|kERslP+k(j>pfDUbc)WUm6Cz7 zgFyF{E-2}uW^#iREhMWj8wt3mxmm;^`r#_Tfi;*wAwUA~WC>GSa|x_ckZy0|>B{hd zPvD9{FO8OH$Q95C2bMEX^9dmnp&*3<&=8~;;F5*zDcw=A!gvShkrx)c__nr28HaHm zf@6tUX-0*pY_7rRE(B@j=rN=oHjxi4L3(vq!c~YV8iW~>&Z2b;b49qF@}1cTkKA)K zwA?AXbv|yLJFRoKbmUW0lxp=ZOPki`CwT(2oaYdE6S&@-1)#LYq!Gxnf}jU7rDDME?n-4leS z#^ciBJu!jBDFlt@q!)#dB>>g#-a$q|flX;k^sEJ01qroq3Bcv@Wk^o3Q9soA*uaZs z3C-&-L-9U{i5Kjl?Mpn$XhHyW;Q^O%0>7+|nWE>9RJRTqRANJvMK(kcfwoHTj>>_f zSiz{Pwf^zE-e6ARY;9W7UsOV&M8BVFc%$W9r1Lsx6^U7@ez^cukQF`z&l7f#1OirJ(P0Pk(Dy=mG(?i< zc<)KmZy_38N?l8!(WHcn)OgjVXe2@ZB9>60>0nifc1yoo;BgnSqtVgf@nH1q^rVL$ zQTiaUC;Oj0c<|r{`2S<|i4XkM@ISSK*yr@)kAc?%rpccs2gW4n8Lyj%Oj-+q1L{QK|gfBNbp|2O~o=TCq2*J$$JpMCL{x4l3A SqxI46|M)}bdGYk*>Hh%cgbo`3 literal 0 HcmV?d00001 diff --git a/fixtures/phar/simple-phar-sha512-sign.phar b/fixtures/phar/simple-phar-sha512-sign.phar new file mode 100644 index 0000000000000000000000000000000000000000..9ca0fcb218afd3c4751bca3838c1f4c283faf63a GIT binary patch literal 6809 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 O;dft#ou`kFAO8=TCL4AD literal 0 HcmV?d00001 diff --git a/fixtures/phar/simple-phar.phar b/fixtures/phar/simple-phar.phar new file mode 100644 index 0000000000000000000000000000000000000000..bf35bc0145d16cee82a3822c178497a8f18496c6 GIT binary patch literal 6777 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 R@4tWa&+kFc>zAi5{|DD(4M6|^ literal 0 HcmV?d00001 diff --git a/fixtures/phar/simple.tar b/fixtures/phar/simple.tar new file mode 100644 index 0000000000000000000000000000000000000000..586639b46bb29d550fbbf2c09c1baabe193d1373 GIT binary patch literal 2048 zcmXR;%q_@C)hnqeVW1f>00J`;6Abe~;$UEC%3x?>VrXavghoaTKru5@GXn(!3>`EO xC@n5YECO0d1EYt6kshfzIr$3Z`9(P?id;j%!J}>*4S~@R7!85Z5THs30041&5?KHM literal 0 HcmV?d00001 diff --git a/fixtures/phar/simple.tar.bz2 b/fixtures/phar/simple.tar.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..22b36732bb89279f6e4b900de793fdab6f4ac909 GIT binary patch literal 118 zcmV-+0Ez!XT4*#eL0KkKS(g6KD*ym9-+;mrU;$@<06+l%W(MBC39co;plXp8UJn6hC;JJ$W)*9co;plXp8UJn6hC;JJ$W)*00J`;6Abe~;$UEC%3x?>VrXavghoaTKru5@GXn(!3>`EO xC@n5YECO0d1EYt6kshfzIr$3Z`9(P?id;j%!J}>*4S~@R7!85Z5THs30041&5?KHM literal 0 HcmV?d00001 diff --git a/fixtures/phar/simple.zip b/fixtures/phar/simple.zip new file mode 100644 index 0000000000000000000000000000000000000000..9b52086eb29ca9d78abb0c14737056ec0017ff82 GIT binary patch literal 213 zcmWIWW@Zs#-~hs|x%FWTP{0eMxfm1}iW74Sa#Hn5DoR2_cp2EgN~@;?$*8A*=+X*q z21b^zj0_Aw{R|ABJ + * Théo Fidry + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ +namespace KevinGH\Box\Phar; use KevinGH\Box\Pharaoh\InvalidPhar; use Phar; use PharData; +use Symfony\Component\Filesystem\Path; use Throwable; +use function file_exists; - +/** + * Factory class to instantiate an _existing_ file (i.e. not to create a brand-new PHAR object). + * It is a thin wrapper around the native PHP constructor but with more friendly errors upon failure. + */ final class PharFactory { private function __construct() @@ -22,10 +36,23 @@ private function __construct() */ public static function createPhar(string $file): Phar { + if (!Path::isLocal($file)) { + // This is needed as otherwise Phar::__construct() does correctly bail out on a URL + // path, but not on other non-local variants, e.g. FTPS, which case it may fail still + // but after a timeout, which is too slow. + throw InvalidPhar::fileNotLocal($file); + } + + if (!file_exists($file)) { + // We need to check this case since the goal of this factory is to instantiate an existing + // PHAR, not create a new one. + throw InvalidPhar::fileNotFound($file); + } + try { return new Phar($file); } catch (Throwable $throwable) { - throw InvalidPhar::create($file, $throwable); + throw InvalidPhar::forPhar($file, $throwable); } } @@ -34,10 +61,23 @@ public static function createPhar(string $file): Phar */ public static function createPharData(string $file): PharData { + if (!Path::isLocal($file)) { + // This is needed as otherwise Phar::__construct() does correctly bail out on a URL + // path, but not on other non-local variants, e.g. FTPS, which case it may fail still + // but after a timeout, which is too slow. + throw InvalidPhar::fileNotLocal($file); + } + + if (!file_exists($file)) { + // We need to check this case since the goal of this factory is to instantiate an existing + // PHAR, not create a new one. + throw InvalidPhar::fileNotFound($file); + } + try { return new PharData($file); } catch (Throwable $throwable) { - throw InvalidPhar::create($file, $throwable); + throw InvalidPhar::forPharData($file, $throwable); } } } diff --git a/src/Pharaoh/InvalidPhar.php b/src/Pharaoh/InvalidPhar.php index ef30396d2..a5827e835 100644 --- a/src/Pharaoh/InvalidPhar.php +++ b/src/Pharaoh/InvalidPhar.php @@ -16,49 +16,116 @@ use Throwable; use UnexpectedValueException; -use function preg_match; +use function Safe\preg_match; use function sprintf; +use function str_contains; +use function str_ends_with; use function str_starts_with; +use function ucfirst; final class InvalidPhar extends PharError { - public static function create(string $file, ?Throwable $previous): self + public static function fileNotLocal(string $file): self { + // Covers: + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1328 return new self( - self::mapThrowableToErrorMessage($file, $previous), + sprintf( + 'Cannot create a Phar or PharData instance for the file path "%s". PHAR objects can only be created from local files.', + $file, + ), + ); + } + + public static function fileNotFound(string $file): self + { + return new self( + sprintf( + 'Could not find the file "%s".', + $file, + ), + ); + } + + public static function forPhar(string $file, ?Throwable $previous): self + { + return new self( + self::mapThrowableToErrorMessage($file, $previous, false), previous: $previous, ); } - private static function mapThrowableToErrorMessage(string $file, ?Throwable $throwable): string + public static function forPharData(string $file, ?Throwable $previous): self { + return new self( + self::mapThrowableToErrorMessage($file, $previous, true), + previous: $previous, + ); + } + + private static function mapThrowableToErrorMessage( + string $file, + ?Throwable $throwable, + bool $isPharData, + ): string { + $message = $throwable->getMessage(); + if ($throwable instanceof UnexpectedValueException) { - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1328 - if (str_starts_with($throwable->getMessage(), 'Cannot create a phar archive from a URL like')) { + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1330 + if (str_ends_with($message, 'file extension (or combination) not recognised or the directory does not exist')) { return sprintf( - 'Cannot create a PHAR object from a URL like "%s". PHAR objects can only be created from local files.', + 'Cannot create a %s instance from the file "%s". The file must have the extension "%s".', + $isPharData ? 'PharData' : 'Phar', $file, + $isPharData ? '.zip", ".tar", ".tar.bz2" or ".tar.gz' : '.phar', ); } - } - return self::couldNotVerifyOpenSSLSignature($throwable) - ? sprintf( - 'Could not create a Phar or PharData instance for the file "%s": the OpenSSL signature could not be verified.', - $file, - ) - : sprintf( - 'Could not create a Phar or PharData instance for the file "%s".', - $file, - ); - } + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1791 + // and a few other similar errors. + if (str_starts_with($message, 'internal corruption of phar ')) { + preg_match('/^internal corruption of phar \".+\" \((?.+)\)$/', $message, $matches); - private static function couldNotVerifyOpenSSLSignature(?Throwable $previous): bool - { - return null !== $previous - && 1 === preg_match( - '/^phar ".*" openssl signature could not be verified: openssl signature could not be verified/', - $previous->getMessage(), - ); + return sprintf( + 'Cannot create a %s instance from the file "%s". The archive is corrupted: %s.', + $isPharData ? 'PharData' : 'Phar', + $file, + ucfirst($matches['reason']), + ); + } + + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L874 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L892 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L903 + if (str_contains($message, ' openssl signature ')) { + return sprintf( + 'Could not create a %s instance for the file "%s". The OpenSSL signature could not be read or verified.', + $isPharData ? 'PharData' : 'Phar', + $file, + ); + } + + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1002 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1012 + // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1024 + // And analogue ones for the other signatures + if (str_contains($message, ' has a broken signature') + || str_contains($message, ' signature could not be verified') + || str_contains($message, ' has a broken or unsupported signature') + ) { + return sprintf( + 'Could not create a %s instance for the file "%s". The archive signature is broken.', + $isPharData ? 'PharData' : 'Phar', + $file, + ); + } + } + + return sprintf( + 'Could not create a %s instance for the file "%s": %s', + $isPharData ? 'PharData' : 'Phar', + $file, + $message, + ); } } diff --git a/src/Pharaoh/Pharaoh.php b/src/Pharaoh/Pharaoh.php index 9ee276b34..a822a004c 100644 --- a/src/Pharaoh/Pharaoh.php +++ b/src/Pharaoh/Pharaoh.php @@ -250,7 +250,7 @@ private static function createPhar(string $file, string $tmpFile): Phar|PharData try { return new PharData($tmpFile); } catch (UnexpectedValueException) { - throw InvalidPhar::create($file, $cannotCreatePhar); + throw InvalidPhar::forPhar($file, $cannotCreatePhar); } } diff --git a/tests/Phar/PharFactoryTest.php b/tests/Phar/PharFactoryTest.php index 18a570aaa..757a2cc93 100644 --- a/tests/Phar/PharFactoryTest.php +++ b/tests/Phar/PharFactoryTest.php @@ -2,33 +2,52 @@ declare(strict_types=1); +/* + * This file is part of the box project. + * + * (c) Kevin Herrera + * Théo Fidry + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + namespace KevinGH\Box\Phar; use KevinGH\Box\Pharaoh\InvalidPhar; use Phar; use PharData; use PHPUnit\Framework\TestCase; +use const DIRECTORY_SEPARATOR; /** * @covers \KevinGH\Box\Phar\PharFactory * * @preserveGlobalState disabled * @runTestsInSeparateProcesses + * + * @internal */ final class PharFactoryTest extends TestCase { - private const FIXTURES_DIR = __DIR__.'/../../fixtures/info'; + private const FIXTURES_DIR = __DIR__.'/../../fixtures/phar'; - public function test_it_can_create_phars(): void + /** + * @dataProvider validPharProvider + */ + public function test_it_can_create_phar_instance(string $file): void { - $phar = PharFactory::createPhar(self::FIXTURES_DIR.'/simple-phar.phar'); + $phar = PharFactory::createPhar($file); self::assertSame(Phar::class, $phar::class); } - public function test_it_can_create_phar_datas(): void + /** + * @dataProvider validPharDataProvider + */ + public function test_it_can_create_phar_data_instance(string $file): void { - $pharData = PharFactory::createPharData(self::FIXTURES_DIR.'/simple-phar.tar.gz'); + $pharData = PharFactory::createPharData($file); self::assertSame(PharData::class, $pharData::class); } @@ -39,62 +58,215 @@ public function test_it_can_create_phar_datas(): void public function test_it_fails_with_a_comprehensive_error_when_cannot_create_a_phar( string $file, string $expectedExceptionMessageRegex, - ): void - { + ): void { $this->expectException(InvalidPhar::class); $this->expectExceptionMessageMatches($expectedExceptionMessageRegex); PharFactory::createPhar($file); } + /** + * @dataProvider invalidPharDataProvider + */ + public function test_it_fails_with_a_comprehensive_error_when_cannot_create_a_phar_data( + string $file, + string $expectedExceptionMessageRegex, + ): void { + $this->expectException(InvalidPhar::class); + $this->expectExceptionMessageMatches($expectedExceptionMessageRegex); + + PharFactory::createPharData($file); + } + + public static function validPharProvider(): iterable + { + yield 'simple PHAR' => [self::FIXTURES_DIR.DIRECTORY_SEPARATOR.'simple-phar.phar']; + + // This works but results in an "empty PHAR": no signature, no stub, will fail to be executed, but can be + // instantiated nonetheless. + $tarVariants = [ + 'simple.zip.phar', + 'simple.tar.phar', + 'simple.tar.bz2.phar', + 'simple.tar.gz.phar', + ]; + + foreach ($tarVariants as $tarVariant) { + yield $tarVariant => [self::FIXTURES_DIR.DIRECTORY_SEPARATOR.$tarVariant]; + } + + $signedPhars = [ + 'MD5' => 'simple-phar-md5-sign.phar', + 'SHA1' => 'simple-phar-sha1-sign.phar', + 'SHA256' => 'simple-phar-sha256-sign.phar', + 'SHA512' => 'simple-phar-sha512-sign.phar', + 'OpenSSL (no passphrase)' => 'simple-phar-openssl-sign.phar', + ]; + + foreach ($signedPhars as $alogrithm => $signedPhar) { + yield $alogrithm => [self::FIXTURES_DIR.DIRECTORY_SEPARATOR.$signedPhar]; + } + } + + public static function validPharDataProvider(): iterable + { + $data = [ + 'simple tar archive' => 'simple.tar', + 'simple ZIP archive' => 'simple.zip', + 'simple BZ2 archive' => 'simple.tar.bz2', + 'simple GZ archive' => 'simple.tar.gz', + ]; + + foreach ($data as $label => $fileName) { + yield $label => [self::FIXTURES_DIR.DIRECTORY_SEPARATOR.$fileName]; + } + } + public static function invalidPharProvider(): iterable { yield 'URL of a valid PHAR' => [ 'https://github.com/box-project/box/releases/download/4.3.8/box.phar', - '/^Cannot create a PHAR object from a URL like ".+"\. PHAR objects can only be created from local files\.$/', - ]; - - yield 'x' => [ - self::FIXTURES_DIR.'/../phar/Empty.pdf', - '/^foo\.$/', - ]; - - // TODO: - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1330 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1343 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1351 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1430 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#LL1565C45-L1565C45 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1669 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1694 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1705 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1708 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1721 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1730 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1735 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1743 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1750 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1763 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L529 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L853 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L874 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L892 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L903 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L921 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L931 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L948 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L958 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L975 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L985 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1002 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1012 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1024 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1033 - // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1064 + '/^Cannot create a Phar or PharData instance for the file path ".+"\. PHAR objects can only be created from local files\.$/', + ]; + + yield 'FTPS URL of a valid PHAR' => [ + 'ftps://github.com/box-project/box/releases/download/4.3.8/box.phar', + '/^Cannot create a Phar or PharData instance for the file path ".+"\. PHAR objects can only be created from local files\.$/', + ]; + + yield 'local stream' => [ + 'php://stdout', + '/^Cannot create a Phar or PharData instance for the file path ".+"\. PHAR objects can only be created from local files\.$/', + ]; + + yield 'non existent file with a valid PHAR name' => [ + self::FIXTURES_DIR.DIRECTORY_SEPARATOR.'non-existent-file.phar', + '/^Could not find the file ".+"\.$/', + ]; + + yield 'non-compressed binary file (empty PDF)' => [ + self::FIXTURES_DIR.'/empty-pdf.pdf', + '/^Cannot create a Phar instance from the file ".+"\. The file must have the extension "\.phar"\.$/', + ]; + + yield 'non-compressed empty file' => [ + self::FIXTURES_DIR.'/empty-file.phar', + '/^Cannot create a Phar instance from the file ".+"\. The archive is corrupted: Truncated entry\.$/', + ]; + + $validPharDatasWithoutPharExtension = [ + 'simple.zip', + 'simple.tar', + 'simple.tar.bz2', + 'simple.tar.gz', + ]; + + foreach ($validPharDatasWithoutPharExtension as $validPharDataWithoutPharExtension) { + yield $validPharDataWithoutPharExtension => [ + self::FIXTURES_DIR.DIRECTORY_SEPARATOR.$validPharDataWithoutPharExtension, + '/^Cannot create a Phar instance from the file ".+"\. The file must have the extension "\.phar"\.$/', + ]; + } + + yield 'PHAR without the __HALT_COMPILER(); ?> token' => [ + self::FIXTURES_DIR.DIRECTORY_SEPARATOR.'corruted-phar-no-halt-compiler.phar', + '/^Cannot create a Phar instance from the file ".+"\. The archive is corrupted: __HALT_COMPILER\(\); not found\.$/', + ]; + + yield 'OpenSSL signed PHAR without its pubkey' => [ + self::FIXTURES_DIR.DIRECTORY_SEPARATOR.'simple-phar-openssl-sign-without-pubkey.phar', + '/^Could not create a Phar instance for the file ".+"\. The OpenSSL signature could not be read or verified\.$/', + ]; + + yield 'OpenSSL signed PHAR without a different pubkey' => [ + self::FIXTURES_DIR.DIRECTORY_SEPARATOR.'simple-phar-openssl-sign-with-diff-pubkey.phar', + '/^Could not create a Phar instance for the file ".+"\. The OpenSSL signature could not be read or verified\.$/', + ]; + + yield 'OpenSSL signed PHAR without an invalid pubkey' => [ + self::FIXTURES_DIR.DIRECTORY_SEPARATOR.'simple-phar-openssl-sign-with-invalid-pubkey.phar', + '/^Could not create a Phar instance for the file ".+"\. The OpenSSL signature could not be read or verified\.$/', + ]; + + yield 'PHAR for which the stub content has been altered without updating its signature' => [ + self::FIXTURES_DIR.DIRECTORY_SEPARATOR.'corrupted-phar-altered-stub.phar', + '/^Could not create a Phar instance for the file ".+"\. The archive signature is broken\.$/', + ]; + + yield 'PHAR for which the content has been altered without updating its signature' => [ + self::FIXTURES_DIR.DIRECTORY_SEPARATOR.'corrupted-phar-altered-binary.phar', + '/^Could not create a Phar instance for the file ".+"\. The archive signature is broken\.$/', + ]; + + yield 'PHAR for which an included file has been altered without updating its signature' => [ + self::FIXTURES_DIR.DIRECTORY_SEPARATOR.'corrupted-phar-altered-included-file.phar', + '/^Could not create a Phar instance for the file ".+"\. The archive signature is broken\.$/', + ]; } - public function test_it_fails_with_a_comprehensive_error_when_cannot_create_a_phar_data(): void + public static function invalidPharDataProvider(): iterable { -$this->markTestSkipped(); + // valid PHARs cannot be PharData instances + foreach (self::validPharProvider() as $label => [$file]) { + yield 'valid PHAR; '.$label => [ + $file, + '/^Cannot create a PharData instance from the file ".+"\. The file must have the extension "\.zip", "\.tar", "\.tar\.bz2" or "\.tar\.gz"\.$/', + ]; + } + + yield 'URL of a valid tar' => [ + 'https://github.com/box-project/box/releases/download/4.3.8/box.tar', + '/^Cannot create a Phar or PharData instance for the file path ".+"\. PHAR objects can only be created from local files\.$/', + ]; + + yield 'FTPS URL of a valid PHAR' => [ + 'ftps://github.com/box-project/box/releases/download/4.3.8/box.tar', + '/^Cannot create a Phar or PharData instance for the file path ".+"\. PHAR objects can only be created from local files\.$/', + ]; + + yield 'local stream' => [ + 'php://stdout', + '/^Cannot create a Phar or PharData instance for the file path ".+"\. PHAR objects can only be created from local files\.$/', + ]; + + yield 'non existent file with a valid PharData name' => [ + self::FIXTURES_DIR.DIRECTORY_SEPARATOR.'non-existent-file.tar', + '/^Could not find the file ".+"\.$/', + ]; + + yield 'corrupted ZIP file' => [ + self::FIXTURES_DIR.DIRECTORY_SEPARATOR.'corrupted-simple.zip', + '/^Cannot create a PharData instance from the file ".+"\. The archive is corrupted: __HALT_COMPILER\(\); not found\.$/', + ]; + + yield 'non-compressed binary file (empty PDF)' => [ + self::FIXTURES_DIR.'/empty-pdf.pdf', + '/^Cannot create a PharData instance from the file ".+"\. The archive is corrupted: __HALT_COMPILER\(\); not found\.$/', + ]; + + yield 'non-compressed empty file' => [ + self::FIXTURES_DIR.'/empty-file.zip', + '/^Cannot create a PharData instance from the file ".+"\. The archive is corrupted: Truncated entry\.$/', + ]; + + yield 'OpenSSL signed PHAR renamed to tar without its pubkey' => [ + self::FIXTURES_DIR.'/simple-phar-openssl-sign.tar', + '/^Could not create a PharData instance for the file ".+"\. The OpenSSL signature could not be read or verified\.$/', + ]; + + yield 'signed PHAR renamed to tar for which the stub content has been altered without updating its signature' => [ + self::FIXTURES_DIR.DIRECTORY_SEPARATOR.'corrupted-phar-altered-stub.tar', + '/^Could not create a PharData instance for the file ".+"\. The archive signature is broken\.$/', + ]; + + yield 'signed PHAR renamed to tar for which the binary content has been altered without updating its signature' => [ + self::FIXTURES_DIR.DIRECTORY_SEPARATOR.'corrupted-phar-altered-binary.tar', + '/^Could not create a PharData instance for the file ".+"\. The archive signature is broken\.$/', + ]; + + yield 'signed PHAR renamed to tar for which an included file content has been altered without updating its signature' => [ + self::FIXTURES_DIR.DIRECTORY_SEPARATOR.'corrupted-phar-altered-included-file.tar', + '/^Could not create a PharData instance for the file ".+"\. The archive signature is broken\.$/', + ]; } } From c59c55cbde8b5e03c910b6fff3fc495eae034383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Sat, 1 Apr 2023 14:27:53 +0200 Subject: [PATCH 3/8] fix --- src/Phar/PharFactory.php | 31 +++++++++++++++++++++++++++++++ tests/Phar/PharFactoryTest.php | 16 ++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/Phar/PharFactory.php b/src/Phar/PharFactory.php index 7533209e1..ede413167 100644 --- a/src/Phar/PharFactory.php +++ b/src/Phar/PharFactory.php @@ -31,6 +31,37 @@ private function __construct() { } + /** + * @throws InvalidPhar + */ + public static function create(string $file): Phar|PharData + { + if (!Path::isLocal($file)) { + // This is needed as otherwise Phar::__construct() does correctly bail out on a URL + // path, but not on other non-local variants, e.g. FTPS, which case it may fail still + // but after a timeout, which is too slow. + throw InvalidPhar::fileNotLocal($file); + } + + if (!file_exists($file)) { + // We need to check this case since the goal of this factory is to instantiate an existing + // PHAR, not create a new one. + throw InvalidPhar::fileNotFound($file); + } + + try { + return new Phar($file); + } catch (Throwable $cannotCreatePhar) { + // Continue + } + + try { + return new PharData($file); + } catch (Throwable) { + throw InvalidPhar::forPhar($file, $cannotCreatePhar); + } + } + /** * @throws InvalidPhar */ diff --git a/tests/Phar/PharFactoryTest.php b/tests/Phar/PharFactoryTest.php index 757a2cc93..f65aef066 100644 --- a/tests/Phar/PharFactoryTest.php +++ b/tests/Phar/PharFactoryTest.php @@ -52,6 +52,16 @@ public function test_it_can_create_phar_data_instance(string $file): void self::assertSame(PharData::class, $pharData::class); } + /** + * @dataProvider validPharAndPharDataProvider + */ + public function test_it_can_create_phar_or_phar_data_instance(string $file): void + { + PharFactory::create($file); + + $this->addToAssertionCount(1); + } + /** * @dataProvider invalidPharProvider */ @@ -122,6 +132,12 @@ public static function validPharDataProvider(): iterable } } + public static function validPharAndPharDataProvider(): iterable + { + yield from self::validPharProvider(); + yield from self::validPharDataProvider(); + } + public static function invalidPharProvider(): iterable { yield 'URL of a valid PHAR' => [ From 6a191b99b56048420a282dc95342dbaf67bba8c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Sat, 1 Apr 2023 14:44:01 +0200 Subject: [PATCH 4/8] fix --- src/Phar/PharFactory.php | 2 +- src/Pharaoh/InvalidPhar.php | 30 ++++++++++++++++++++------- tests/Console/Command/DiffTest.php | 2 +- tests/Console/Command/ExtractTest.php | 10 ++++----- tests/Phar/PharFactoryTest.php | 28 ++++++++++++------------- 5 files changed, 43 insertions(+), 29 deletions(-) diff --git a/src/Phar/PharFactory.php b/src/Phar/PharFactory.php index ede413167..4232bdf3d 100644 --- a/src/Phar/PharFactory.php +++ b/src/Phar/PharFactory.php @@ -58,7 +58,7 @@ public static function create(string $file): Phar|PharData try { return new PharData($file); } catch (Throwable) { - throw InvalidPhar::forPhar($file, $cannotCreatePhar); + throw InvalidPhar::forPharAndPharData($file, $cannotCreatePhar); } } diff --git a/src/Pharaoh/InvalidPhar.php b/src/Pharaoh/InvalidPhar.php index a5827e835..b5d24d296 100644 --- a/src/Pharaoh/InvalidPhar.php +++ b/src/Pharaoh/InvalidPhar.php @@ -63,19 +63,33 @@ public static function forPharData(string $file, ?Throwable $previous): self ); } + public static function forPharAndPharData(string $file, ?Throwable $previous): self + { + return new self( + self::mapThrowableToErrorMessage($file, $previous, null), + previous: $previous, + ); + } + private static function mapThrowableToErrorMessage( string $file, ?Throwable $throwable, - bool $isPharData, + ?bool $isPharData, ): string { + if (null === $isPharData) { + $pharObject = 'Phar or PharData'; + } else { + $pharObject = $isPharData ? 'PharData' : 'Phar'; + } + $message = $throwable->getMessage(); if ($throwable instanceof UnexpectedValueException) { // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1330 if (str_ends_with($message, 'file extension (or combination) not recognised or the directory does not exist')) { return sprintf( - 'Cannot create a %s instance from the file "%s". The file must have the extension "%s".', - $isPharData ? 'PharData' : 'Phar', + 'Could not create a %s instance for the file "%s". The file must have the extension "%s".', + $pharObject, $file, $isPharData ? '.zip", ".tar", ".tar.bz2" or ".tar.gz' : '.phar', ); @@ -87,8 +101,8 @@ private static function mapThrowableToErrorMessage( preg_match('/^internal corruption of phar \".+\" \((?.+)\)$/', $message, $matches); return sprintf( - 'Cannot create a %s instance from the file "%s". The archive is corrupted: %s.', - $isPharData ? 'PharData' : 'Phar', + 'Could not create a %s instance for the file "%s". The archive is corrupted: %s.', + $pharObject, $file, ucfirst($matches['reason']), ); @@ -100,7 +114,7 @@ private static function mapThrowableToErrorMessage( if (str_contains($message, ' openssl signature ')) { return sprintf( 'Could not create a %s instance for the file "%s". The OpenSSL signature could not be read or verified.', - $isPharData ? 'PharData' : 'Phar', + $pharObject, $file, ); } @@ -115,7 +129,7 @@ private static function mapThrowableToErrorMessage( ) { return sprintf( 'Could not create a %s instance for the file "%s". The archive signature is broken.', - $isPharData ? 'PharData' : 'Phar', + $pharObject, $file, ); } @@ -123,7 +137,7 @@ private static function mapThrowableToErrorMessage( return sprintf( 'Could not create a %s instance for the file "%s": %s', - $isPharData ? 'PharData' : 'Phar', + $pharObject, $file, $message, ); diff --git a/tests/Console/Command/DiffTest.php b/tests/Console/Command/DiffTest.php index d952073c2..76ad45aab 100644 --- a/tests/Console/Command/DiffTest.php +++ b/tests/Console/Command/DiffTest.php @@ -210,7 +210,7 @@ public function test_it_cannot_compare_a_non_phar_files(): void ], ); - $expected = '/^Could not check the PHARs: Could not create a Phar or PharData instance for the file ".*"\.$/'; + $expected = '/^Could not check the PHARs: Cannot create a Phar instance from the file .+$/'; self::assertMatchesRegularExpression($expected, $this->commandTester->getDisplay(true)); self::assertSame(1, $this->commandTester->getStatusCode()); diff --git a/tests/Console/Command/ExtractTest.php b/tests/Console/Command/ExtractTest.php index f4233a1ed..9c3a3a156 100644 --- a/tests/Console/Command/ExtractTest.php +++ b/tests/Console/Command/ExtractTest.php @@ -245,31 +245,31 @@ public static function invalidPharPath(): iterable yield 'not a valid PHAR with the PHAR extension' => [ self::FIXTURES.'/invalid.phar', InvalidPhar::class, - '/^Could not create a Phar or PharData instance for the file/', + '/^Could not create a Phar instance for the file/', ]; yield 'not a valid PHAR without the PHAR extension' => [ self::FIXTURES.'/invalid', InvalidPhar::class, - '/^Could not create a Phar or PharData instance for the file .+$/', + '/^Could not create a Phar instance for the file/', ]; yield 'corrupted PHAR (was valid; got tempered with)' => [ self::FIXTURES.'/corrupted.phar', InvalidPhar::class, - '/^Could not create a Phar or PharData instance for the file .+$/', + '/^Could not create a Phar instance for the file/', ]; yield 'OpenSSL signed PHAR without a pubkey' => [ self::FIXTURES.'/openssl-no-pubkey.phar', InvalidPhar::class, - '/^Could not create a Phar or PharData instance for the file .+$/', + '/^Could not create a Phar instance for the file/', ]; yield 'OpenSSL signed PHAR with incorrect pubkey' => [ self::FIXTURES.'/incorrect-key-openssl.phar', InvalidPhar::class, - '/^Could not create a Phar or PharData instance for the file .+$/', + '/^Could not create a Phar instance for the file/', ]; } diff --git a/tests/Phar/PharFactoryTest.php b/tests/Phar/PharFactoryTest.php index f65aef066..60af7cc8e 100644 --- a/tests/Phar/PharFactoryTest.php +++ b/tests/Phar/PharFactoryTest.php @@ -142,17 +142,17 @@ public static function invalidPharProvider(): iterable { yield 'URL of a valid PHAR' => [ 'https://github.com/box-project/box/releases/download/4.3.8/box.phar', - '/^Cannot create a Phar or PharData instance for the file path ".+"\. PHAR objects can only be created from local files\.$/', + '/^Could not create a Phar or PharData instance for the file path ".+"\. PHAR objects can only be created from local files\.$/', ]; yield 'FTPS URL of a valid PHAR' => [ 'ftps://github.com/box-project/box/releases/download/4.3.8/box.phar', - '/^Cannot create a Phar or PharData instance for the file path ".+"\. PHAR objects can only be created from local files\.$/', + '/^Could not create a Phar or PharData instance for the file path ".+"\. PHAR objects can only be created from local files\.$/', ]; yield 'local stream' => [ 'php://stdout', - '/^Cannot create a Phar or PharData instance for the file path ".+"\. PHAR objects can only be created from local files\.$/', + '/^Could not create a Phar or PharData instance for the file path ".+"\. PHAR objects can only be created from local files\.$/', ]; yield 'non existent file with a valid PHAR name' => [ @@ -162,12 +162,12 @@ public static function invalidPharProvider(): iterable yield 'non-compressed binary file (empty PDF)' => [ self::FIXTURES_DIR.'/empty-pdf.pdf', - '/^Cannot create a Phar instance from the file ".+"\. The file must have the extension "\.phar"\.$/', + '/^Could not create a Phar instance for the file ".+"\. The file must have the extension "\.phar"\.$/', ]; yield 'non-compressed empty file' => [ self::FIXTURES_DIR.'/empty-file.phar', - '/^Cannot create a Phar instance from the file ".+"\. The archive is corrupted: Truncated entry\.$/', + '/^Could not create a Phar instance for the file ".+"\. The archive is corrupted: Truncated entry\.$/', ]; $validPharDatasWithoutPharExtension = [ @@ -180,13 +180,13 @@ public static function invalidPharProvider(): iterable foreach ($validPharDatasWithoutPharExtension as $validPharDataWithoutPharExtension) { yield $validPharDataWithoutPharExtension => [ self::FIXTURES_DIR.DIRECTORY_SEPARATOR.$validPharDataWithoutPharExtension, - '/^Cannot create a Phar instance from the file ".+"\. The file must have the extension "\.phar"\.$/', + '/^Could not create a Phar instance for the file ".+"\. The file must have the extension "\.phar"\.$/', ]; } yield 'PHAR without the __HALT_COMPILER(); ?> token' => [ self::FIXTURES_DIR.DIRECTORY_SEPARATOR.'corruted-phar-no-halt-compiler.phar', - '/^Cannot create a Phar instance from the file ".+"\. The archive is corrupted: __HALT_COMPILER\(\); not found\.$/', + '/^Could not create a Phar instance for the file ".+"\. The archive is corrupted: __HALT_COMPILER\(\); not found\.$/', ]; yield 'OpenSSL signed PHAR without its pubkey' => [ @@ -226,23 +226,23 @@ public static function invalidPharDataProvider(): iterable foreach (self::validPharProvider() as $label => [$file]) { yield 'valid PHAR; '.$label => [ $file, - '/^Cannot create a PharData instance from the file ".+"\. The file must have the extension "\.zip", "\.tar", "\.tar\.bz2" or "\.tar\.gz"\.$/', + '/^Could not create a PharData instance for the file ".+"\. The file must have the extension "\.zip", "\.tar", "\.tar\.bz2" or "\.tar\.gz"\.$/', ]; } yield 'URL of a valid tar' => [ 'https://github.com/box-project/box/releases/download/4.3.8/box.tar', - '/^Cannot create a Phar or PharData instance for the file path ".+"\. PHAR objects can only be created from local files\.$/', + '/^Could not create a Phar or PharData instance for the file path ".+"\. PHAR objects can only be created from local files\.$/', ]; yield 'FTPS URL of a valid PHAR' => [ 'ftps://github.com/box-project/box/releases/download/4.3.8/box.tar', - '/^Cannot create a Phar or PharData instance for the file path ".+"\. PHAR objects can only be created from local files\.$/', + '/^Could not create a Phar or PharData instance for the file path ".+"\. PHAR objects can only be created from local files\.$/', ]; yield 'local stream' => [ 'php://stdout', - '/^Cannot create a Phar or PharData instance for the file path ".+"\. PHAR objects can only be created from local files\.$/', + '/^Could not create a Phar or PharData instance for the file path ".+"\. PHAR objects can only be created from local files\.$/', ]; yield 'non existent file with a valid PharData name' => [ @@ -252,17 +252,17 @@ public static function invalidPharDataProvider(): iterable yield 'corrupted ZIP file' => [ self::FIXTURES_DIR.DIRECTORY_SEPARATOR.'corrupted-simple.zip', - '/^Cannot create a PharData instance from the file ".+"\. The archive is corrupted: __HALT_COMPILER\(\); not found\.$/', + '/^Could not create a PharData instance for the file ".+"\. The archive is corrupted: __HALT_COMPILER\(\); not found\.$/', ]; yield 'non-compressed binary file (empty PDF)' => [ self::FIXTURES_DIR.'/empty-pdf.pdf', - '/^Cannot create a PharData instance from the file ".+"\. The archive is corrupted: __HALT_COMPILER\(\); not found\.$/', + '/^Could not create a PharData instance for the file ".+"\. The archive is corrupted: __HALT_COMPILER\(\); not found\.$/', ]; yield 'non-compressed empty file' => [ self::FIXTURES_DIR.'/empty-file.zip', - '/^Cannot create a PharData instance from the file ".+"\. The archive is corrupted: Truncated entry\.$/', + '/^Could not create a PharData instance for the file ".+"\. The archive is corrupted: Truncated entry\.$/', ]; yield 'OpenSSL signed PHAR renamed to tar without its pubkey' => [ From c74679f4ebb6b9eaa91142a1cfd681f93f0e79a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Sat, 1 Apr 2023 14:45:23 +0200 Subject: [PATCH 5/8] fix --- src/Pharaoh/InvalidPhar.php | 2 +- tests/Console/Command/DiffTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Pharaoh/InvalidPhar.php b/src/Pharaoh/InvalidPhar.php index b5d24d296..024b4acd7 100644 --- a/src/Pharaoh/InvalidPhar.php +++ b/src/Pharaoh/InvalidPhar.php @@ -31,7 +31,7 @@ public static function fileNotLocal(string $file): self // https://github.com/php/php-src/blob/930db2b2d315b2acc917706cf76bed8b09f94b79/ext/phar/phar.c#L1328 return new self( sprintf( - 'Cannot create a Phar or PharData instance for the file path "%s". PHAR objects can only be created from local files.', + 'Could not create a Phar or PharData instance for the file path "%s". PHAR objects can only be created from local files.', $file, ), ); diff --git a/tests/Console/Command/DiffTest.php b/tests/Console/Command/DiffTest.php index 76ad45aab..fe52a627d 100644 --- a/tests/Console/Command/DiffTest.php +++ b/tests/Console/Command/DiffTest.php @@ -210,7 +210,7 @@ public function test_it_cannot_compare_a_non_phar_files(): void ], ); - $expected = '/^Could not check the PHARs: Cannot create a Phar instance from the file .+$/'; + $expected = '/^Could not check the PHARs: Could not create a Phar instance for the file .+$/'; self::assertMatchesRegularExpression($expected, $this->commandTester->getDisplay(true)); self::assertSame(1, $this->commandTester->getStatusCode()); From a44f2e5fd70bcb58200de576aea720319b4fbb86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Sat, 1 Apr 2023 14:49:36 +0200 Subject: [PATCH 6/8] fix --- src/Pharaoh/Pharaoh.php | 2 +- tests/Pharaoh/PharaohTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Pharaoh/Pharaoh.php b/src/Pharaoh/Pharaoh.php index a822a004c..010153a5d 100644 --- a/src/Pharaoh/Pharaoh.php +++ b/src/Pharaoh/Pharaoh.php @@ -250,7 +250,7 @@ private static function createPhar(string $file, string $tmpFile): Phar|PharData try { return new PharData($tmpFile); } catch (UnexpectedValueException) { - throw InvalidPhar::forPhar($file, $cannotCreatePhar); + throw InvalidPhar::forPharAndPharData($file, $cannotCreatePhar); } } diff --git a/tests/Pharaoh/PharaohTest.php b/tests/Pharaoh/PharaohTest.php index f040f891b..65eefc56b 100644 --- a/tests/Pharaoh/PharaohTest.php +++ b/tests/Pharaoh/PharaohTest.php @@ -147,7 +147,7 @@ public function test_it_throws_an_error_when_a_phar_cannot_be_created(): void self::fail(); } catch (InvalidPhar $exception) { self::assertMatchesRegularExpression( - '/^Could not create a Phar or PharData instance for the file ".*"\.$/', + '/^Could not create a Phar or PharData instance for the file /', $exception->getMessage(), ); self::assertNotNull($exception->getPrevious()); From a2b9f5163303ddecdcaeb9172acc7ea2933d35f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Sat, 1 Apr 2023 15:18:20 +0200 Subject: [PATCH 7/8] fix --- tests/Phar/PharFactoryTest.php | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/tests/Phar/PharFactoryTest.php b/tests/Phar/PharFactoryTest.php index 60af7cc8e..f6342e651 100644 --- a/tests/Phar/PharFactoryTest.php +++ b/tests/Phar/PharFactoryTest.php @@ -18,7 +18,9 @@ use Phar; use PharData; use PHPUnit\Framework\TestCase; +use function extension_loaded; use const DIRECTORY_SEPARATOR; +use const PHP_OS_FAMILY; /** * @covers \KevinGH\Box\Phar\PharFactory @@ -97,12 +99,18 @@ public static function validPharProvider(): iterable $tarVariants = [ 'simple.zip.phar', 'simple.tar.phar', - 'simple.tar.bz2.phar', 'simple.tar.gz.phar', ]; - foreach ($tarVariants as $tarVariant) { - yield $tarVariant => [self::FIXTURES_DIR.DIRECTORY_SEPARATOR.$tarVariant]; + if (extension_loaded('bz2')) { + $tarVariants[] = 'simple.tar.bz2.phar'; + } + + if ('Darwin' === PHP_OS_FAMILY) { + // On Linux the following would fail with "is not a phar archive. Use PharData::__construct() for a standard zip or tar archive" + foreach ($tarVariants as $tarVariant) { + yield $tarVariant => [self::FIXTURES_DIR.DIRECTORY_SEPARATOR.$tarVariant]; + } } $signedPhars = [ @@ -123,10 +131,13 @@ public static function validPharDataProvider(): iterable $data = [ 'simple tar archive' => 'simple.tar', 'simple ZIP archive' => 'simple.zip', - 'simple BZ2 archive' => 'simple.tar.bz2', 'simple GZ archive' => 'simple.tar.gz', ]; + if (extension_loaded('bz2')) { + $data['simple BZ2 archive'] = 'simple.tar.bz2'; + } + foreach ($data as $label => $fileName) { yield $label => [self::FIXTURES_DIR.DIRECTORY_SEPARATOR.$fileName]; } @@ -173,10 +184,13 @@ public static function invalidPharProvider(): iterable $validPharDatasWithoutPharExtension = [ 'simple.zip', 'simple.tar', - 'simple.tar.bz2', 'simple.tar.gz', ]; + if (extension_loaded('bz2')) { + $validPharDatasWithoutPharExtension[] = 'simple.tar.bz2'; + } + foreach ($validPharDatasWithoutPharExtension as $validPharDataWithoutPharExtension) { yield $validPharDataWithoutPharExtension => [ self::FIXTURES_DIR.DIRECTORY_SEPARATOR.$validPharDataWithoutPharExtension, From f15fb3aa2ff3b79b275f4cd74222193b4a1c8edf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Sat, 1 Apr 2023 15:22:24 +0200 Subject: [PATCH 8/8] fix --- tests/Console/Command/DiffTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Console/Command/DiffTest.php b/tests/Console/Command/DiffTest.php index fe52a627d..b011d7d0f 100644 --- a/tests/Console/Command/DiffTest.php +++ b/tests/Console/Command/DiffTest.php @@ -210,7 +210,7 @@ public function test_it_cannot_compare_a_non_phar_files(): void ], ); - $expected = '/^Could not check the PHARs: Could not create a Phar instance for the file .+$/'; + $expected = '/^Could not check the PHARs: Could not create a Phar or PharData instance for the file .+$/'; self::assertMatchesRegularExpression($expected, $this->commandTester->getDisplay(true)); self::assertSame(1, $this->commandTester->getStatusCode());