@@ -387,35 +387,43 @@ object IO {
387387 preserveLastModified : Boolean = true
388388 ): Set [File ] = {
389389 createDirectory(toDirectory)
390- zipInputStream(from)(zipInput => extract(zipInput, toDirectory, filter, preserveLastModified))
390+ zipInputStream(from)(zipInput =>
391+ extract(zipInput, toDirectory.toPath, filter, preserveLastModified)
392+ )
391393 }
392394
393395 private def extract (
394396 from : ZipInputStream ,
395- toDirectory : File ,
397+ toDirectory : NioPath ,
396398 filter : NameFilter ,
397399 preserveLastModified : Boolean
398400 ) = {
399- val set = new HashSet [File ]
401+ val set = new HashSet [NioPath ]
402+ val canonicalDirPath = toDirectory.normalize().toString
403+ def validateExtractPath (name : String , target : NioPath ): Unit =
404+ if (! target.normalize().toString.startsWith(canonicalDirPath)) {
405+ throw new RuntimeException (s " Entry ( $name) is outside of the target directory " )
406+ }
400407 @ tailrec def next (): Unit = {
401408 val entry = from.getNextEntry
402409 if (entry == null )
403410 ()
404411 else {
405412 val name = entry.getName
406413 if (filter.accept(name)) {
407- val target = new File (toDirectory, name)
414+ val target = toDirectory.resolve(name)
415+ validateExtractPath(name, target)
408416 // log.debug("Extracting zip entry '" + name + "' to '" + target + "'")
409417 if (entry.isDirectory)
410- createDirectory(target)
418+ createDirectory(target.toFile )
411419 else {
412420 set += target
413421 translate(" Error extracting zip entry '" + name + " ' to '" + target + " ': " ) {
414- fileOutputStream(false )(target)(out => transfer(from, out))
422+ fileOutputStream(false )(target.toFile )(out => transfer(from, out))
415423 }
416424 }
417425 if (preserveLastModified)
418- setModifiedTimeOrFalse(target, entry.getTime)
426+ setModifiedTimeOrFalse(target.toFile , entry.getTime)
419427 } else {
420428 // log.debug("Ignoring zip entry '" + name + "'")
421429 }
@@ -424,7 +432,7 @@ object IO {
424432 }
425433 }
426434 next()
427- Set () ++ set
435+ ( Set () ++ set).map(_.toFile)
428436 }
429437
430438 // TODO: provide a better API to download things.
0 commit comments