2525import java .util .Enumeration ;
2626import java .util .Iterator ;
2727import java .util .zip .ZipEntry ;
28+ import java .util .zip .CRC32 ;
2829import java .util .HashMap ;
2930
3031import okio .BufferedSink ;
@@ -100,7 +101,7 @@ private void downloadFile(DownloadTaskParams param) throws IOException {
100101 if (UpdateContext .DEBUG ) {
101102 Log .d ("react-native-update" , "Progress " + received + "/" + contentLength );
102103 }
103-
104+
104105 int percentage = (int )(received * 100.0 / contentLength + 0.5 );
105106 if (percentage > currentPercentage ) {
106107 currentPercentage = percentage ;
@@ -198,6 +199,10 @@ private byte[] readFile(File file) throws IOException {
198199 return fout .toByteArray ();
199200 }
200201
202+ private String getCRC32AsDecimal (long crc32Value ) {
203+ return String .valueOf (crc32Value & 0xFFFFFFFFL );
204+ }
205+
201206 private void copyFilesWithBlacklist (String current , File from , File to , JSONObject blackList ) throws IOException {
202207 File [] files = from .listFiles ();
203208 for (File file : files ) {
@@ -247,14 +252,19 @@ private void doFullPatch(DownloadTaskParams param) throws IOException {
247252 }
248253 }
249254
250- private void copyFromResource (HashMap <String , ArrayList <File > > resToCopy ) throws IOException {
255+ private void copyFromResource (HashMap <String , ArrayList <File > > resToCopy , HashMap < String , ArrayList < File >> resToCopy2 ) throws IOException {
251256 SafeZipFile zipFile = new SafeZipFile (new File (context .getPackageResourcePath ()));
252257 Enumeration <? extends ZipEntry > entries = zipFile .entries ();
253258 while (entries .hasMoreElements ()) {
254259 ZipEntry ze = entries .nextElement ();
255260
256261 String fn = ze .getName ();
257- ArrayList <File > targets = resToCopy .get (fn );
262+ long zipCrc32 = ze .getCrc ();
263+ String crc32Decimal = getCRC32AsDecimal (zipCrc32 );
264+ ArrayList <File > targets = resToCopy2 .get (crc32Decimal );
265+ if (targets ==null || targets .isEmpty ()){
266+ targets = resToCopy .get (fn );
267+ }
258268 if (targets != null ) {
259269 File lastTarget = null ;
260270 for (File target : targets ) {
@@ -279,6 +289,7 @@ private void doPatchFromApk(DownloadTaskParams param) throws IOException, JSONEx
279289 removeDirectory (param .unzipDirectory );
280290 param .unzipDirectory .mkdirs ();
281291 HashMap <String , ArrayList <File >> copyList = new HashMap <String , ArrayList <File >>();
292+ HashMap <String , ArrayList <File >> copiesv2List = new HashMap <String , ArrayList <File >>();
282293
283294 boolean foundDiff = false ;
284295 boolean foundBundlePatch = false ;
@@ -297,7 +308,9 @@ private void doPatchFromApk(DownloadTaskParams param) throws IOException, JSONEx
297308 JSONObject obj = (JSONObject )new JSONTokener (json ).nextValue ();
298309
299310 JSONObject copies = obj .getJSONObject ("copies" );
311+ JSONObject copiesv2 = obj .getJSONObject ("copiesv2" );
300312 Iterator <?> keys = copies .keys ();
313+ Iterator <?> keys2 = copiesv2 .keys ();
301314 while ( keys .hasNext () ) {
302315 String to = (String )keys .next ();
303316 String from = copies .getString (to );
@@ -321,6 +334,30 @@ private void doPatchFromApk(DownloadTaskParams param) throws IOException, JSONEx
321334 }
322335 target .add (toFile );
323336 }
337+
338+ while ( keys2 .hasNext () ) {
339+ String from = (String )keys2 .next ();
340+ String to = copiesv2 .getString (from );
341+ if (from .isEmpty ()) {
342+ from = to ;
343+ }
344+ ArrayList <File > target = null ;
345+ if (!copiesv2List .containsKey (from )) {
346+ target = new ArrayList <File >();
347+ copiesv2List .put (from , target );
348+ } else {
349+ target = copiesv2List .get ((from ));
350+ }
351+ File toFile = new File (param .unzipDirectory , to );
352+
353+ // Fixing a Zip Path Traversal Vulnerability
354+ // https://support.google.com/faqs/answer/9294009
355+ String canonicalPath = toFile .getCanonicalPath ();
356+ if (!canonicalPath .startsWith (param .unzipDirectory .getCanonicalPath () + File .separator )) {
357+ throw new SecurityException ("Illegal name: " + to );
358+ }
359+ target .add (toFile );
360+ }
324361 continue ;
325362 }
326363 if (fn .equals ("index.bundlejs.patch" )) {
@@ -348,7 +385,7 @@ private void doPatchFromApk(DownloadTaskParams param) throws IOException, JSONEx
348385 throw new Error ("bundle patch not found" );
349386 }
350387
351- copyFromResource (copyList );
388+ copyFromResource (copyList , copiesv2List );
352389
353390 if (UpdateContext .DEBUG ) {
354391 Log .d ("react-native-update" , "Unzip finished" );
0 commit comments