99
1010namespace Facebook\HackCodegen ;
1111
12+ use namespace HH\Lib\{C , Keyset , Regex , Str , Vec} ;
13+
1214abstract class SignedSourceBase {
1315
1416 const TOKEN = ' <<SignedSource::*O*zOeWoEQle#+L!plEphiEmie@I>>' ;
@@ -23,8 +25,10 @@ abstract class SignedSourceBase {
2325 return $file_data ;
2426 }
2527
26- public static function getPattern (): string {
27- return ' /@' . static :: getTokenName(). ' (?:SignedSource<<([a-f0-9]{32})>>)/' ;
28+ public static function getPattern (
29+ ): Regex \Pattern <shape(' token_name' => string , ' signature' => string , ...) > {
30+ return
31+ re "/ @(?<token_name>\\ S+ ) (?:SignedSource<<(?<signature>[a-f0-9] {32} )>>)/" ;
2832 }
2933
3034 /**
@@ -68,7 +72,10 @@ abstract class SignedSourceBase {
6872 *
6973 */
7074 public static function isSigned (string $file_data ): bool {
71- return (bool )\preg_match (static :: getPattern(), $file_data );
75+ return C \any (
76+ Regex \every_match ($file_data , static :: getPattern()),
77+ $match ==> $match [' token_name' ] === static :: getTokenName(),
78+ );
7279 }
7380
7481 /**
@@ -80,15 +87,25 @@ abstract class SignedSourceBase {
8087 *
8188 */
8289 public static function verifySignature (string $file_data ): bool {
83- $matches = array ();
84- if (! \preg_match (static :: getPattern(), $file_data , & $matches )) {
90+ $signatures =
91+ Regex \every_match ($file_data , static :: getPattern())
92+ |> Vec \filter ($$, $m ==> $m [' token_name' ] === static :: getTokenName())
93+ |> Keyset \map ($$, $m ==> $m [' signature' ]);
94+
95+ if (C \is_empty ($signatures )) {
8596 throw new \Exception (' Can not verify the signature of an unsigned file.' );
97+ } else if (C \count ($signatures ) > 1 ) {
98+ throw new \Exception (' File has multiple different signatures.' );
8699 }
87- $replaced_data =
88- \str_replace (' SignedSource<<' . $matches [1 ]. ' >>' , static :: TOKEN , $file_data );
89100
90- $signature = \md5 (static :: preprocess($replaced_data ));
91- return $signature === $matches [1 ];
101+ $signature = C \onlyx ($signatures );
102+
103+ $expected_signature = $file_data
104+ |> Str \replace ($$, ' SignedSource<<' . $signature . ' >>' , static :: TOKEN )
105+ |> static :: preprocess($$)
106+ |> \md5 ($$);
107+
108+ return $signature === $expected_signature ;
92109 }
93110
94111 /**
0 commit comments