25
25
import java .util .Enumeration ;
26
26
import java .util .Iterator ;
27
27
import java .util .zip .ZipEntry ;
28
+ import java .util .zip .CRC32 ;
28
29
import java .util .HashMap ;
29
30
30
31
import okio .BufferedSink ;
@@ -100,7 +101,7 @@ private void downloadFile(DownloadTaskParams param) throws IOException {
100
101
if (UpdateContext .DEBUG ) {
101
102
Log .d ("react-native-update" , "Progress " + received + "/" + contentLength );
102
103
}
103
-
104
+
104
105
int percentage = (int )(received * 100.0 / contentLength + 0.5 );
105
106
if (percentage > currentPercentage ) {
106
107
currentPercentage = percentage ;
@@ -198,6 +199,10 @@ private byte[] readFile(File file) throws IOException {
198
199
return fout .toByteArray ();
199
200
}
200
201
202
+ private String getCRC32AsDecimal (long crc32Value ) {
203
+ return String .valueOf (crc32Value & 0xFFFFFFFFL );
204
+ }
205
+
201
206
private void copyFilesWithBlacklist (String current , File from , File to , JSONObject blackList ) throws IOException {
202
207
File [] files = from .listFiles ();
203
208
for (File file : files ) {
@@ -247,14 +252,19 @@ private void doFullPatch(DownloadTaskParams param) throws IOException {
247
252
}
248
253
}
249
254
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 {
251
256
SafeZipFile zipFile = new SafeZipFile (new File (context .getPackageResourcePath ()));
252
257
Enumeration <? extends ZipEntry > entries = zipFile .entries ();
253
258
while (entries .hasMoreElements ()) {
254
259
ZipEntry ze = entries .nextElement ();
255
260
256
261
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
+ }
258
268
if (targets != null ) {
259
269
File lastTarget = null ;
260
270
for (File target : targets ) {
@@ -279,6 +289,7 @@ private void doPatchFromApk(DownloadTaskParams param) throws IOException, JSONEx
279
289
removeDirectory (param .unzipDirectory );
280
290
param .unzipDirectory .mkdirs ();
281
291
HashMap <String , ArrayList <File >> copyList = new HashMap <String , ArrayList <File >>();
292
+ HashMap <String , ArrayList <File >> copiesv2List = new HashMap <String , ArrayList <File >>();
282
293
283
294
boolean foundDiff = false ;
284
295
boolean foundBundlePatch = false ;
@@ -297,7 +308,9 @@ private void doPatchFromApk(DownloadTaskParams param) throws IOException, JSONEx
297
308
JSONObject obj = (JSONObject )new JSONTokener (json ).nextValue ();
298
309
299
310
JSONObject copies = obj .getJSONObject ("copies" );
311
+ JSONObject copiesv2 = obj .getJSONObject ("copiesv2" );
300
312
Iterator <?> keys = copies .keys ();
313
+ Iterator <?> keys2 = copiesv2 .keys ();
301
314
while ( keys .hasNext () ) {
302
315
String to = (String )keys .next ();
303
316
String from = copies .getString (to );
@@ -321,6 +334,30 @@ private void doPatchFromApk(DownloadTaskParams param) throws IOException, JSONEx
321
334
}
322
335
target .add (toFile );
323
336
}
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
+ }
324
361
continue ;
325
362
}
326
363
if (fn .equals ("index.bundlejs.patch" )) {
@@ -348,7 +385,7 @@ private void doPatchFromApk(DownloadTaskParams param) throws IOException, JSONEx
348
385
throw new Error ("bundle patch not found" );
349
386
}
350
387
351
- copyFromResource (copyList );
388
+ copyFromResource (copyList , copiesv2List );
352
389
353
390
if (UpdateContext .DEBUG ) {
354
391
Log .d ("react-native-update" , "Unzip finished" );
0 commit comments