Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fix for JRUBY-4760: File.open throws Errno::ENOENT when file inside j…

…ar is accessed using ".." (doubledot) in the path
  • Loading branch information...
commit 343db568f6a49747d750792f332e9083e0dbf942 1 parent 854f255
@headius headius authored
View
24 src/org/jruby/RubyFile.java
@@ -48,6 +48,8 @@
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
@@ -1662,6 +1664,28 @@ public static IRubyObject unlink(ThreadContext context, IRubyObject recv, IRubyO
return runtime.newFixnum(args.length);
}
+ public static ZipEntry getFileEntry(ZipFile zf, String path) throws IOException {
+ ZipEntry entry = zf.getEntry(path);
+ if (entry == null) {
+ // try canonicalizing the path to eliminate . and .. (JRUBY-4760)
+ entry = zf.getEntry(new File("/" + path).getCanonicalPath().substring(1));
+ }
+ return entry;
+ }
+
+ public static ZipEntry getDirOrFileEntry(ZipFile zf, String path) throws IOException {
+ ZipEntry entry = zf.getEntry(path + "/"); // first try as directory
+ if (entry == null) {
+ // try canonicalizing the path to eliminate . and .. (JRUBY-4760)
+ entry = zf.getEntry(new File("/" + path + "/").getCanonicalPath().substring(1));
+ if (entry == null) {
+ // try as file
+ entry = getFileEntry(zf, path);
+ }
+ }
+ return entry;
+ }
+
/**
* Extract a timeval (an array of 2 longs: seconds and microseconds from epoch) from
* an IRubyObject.
View
2  src/org/jruby/RubyFileStat.java
@@ -124,7 +124,7 @@ private void setup(String filename, boolean lstat) {
try {
ZipFile zipFile = new ZipFile(zipfilename);
- ZipEntry zipEntry = zipFile.getEntry(zipFileEntry);
+ ZipEntry zipEntry = RubyFile.getFileEntry(zipFile, zipFileEntry);
if (zipEntry == null) {
throw getRuntime().newErrnoENOENTError("invalid jar/file URL: " + filename);
View
6 src/org/jruby/RubyFileTest.java
@@ -30,6 +30,7 @@
***** END LICENSE BLOCK *****/
package org.jruby;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.jar.JarFile;
@@ -339,10 +340,7 @@ private static ZipEntry file_in_archive(IRubyObject path) {
String after = file.substring(bang + 2);
try {
JarFile jf = new JarFile(jar);
- ZipEntry entry = jf.getEntry(after + "/"); // first try as directory
- if (entry == null) {
- entry = jf.getEntry(after); // next as regular file
- }
+ ZipEntry entry = RubyFile.getDirOrFileEntry(jf, after);
return entry;
} catch (Exception e) {
}
View
6 src/org/jruby/util/Dir.java
@@ -34,7 +34,9 @@
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
import org.jruby.RubyEncoding;
+import org.jruby.RubyFile;
import org.jruby.ext.posix.JavaSecuredFile;
import org.jruby.platform.Platform;
@@ -582,8 +584,8 @@ private static int glob_helper(String cwd, byte[] bytes, int begin, int end, int
JarFile jf = new JarFile(st);
if (jar.startsWith("/")) jar = jar.substring(1);
- if (jf.getEntry(jar + "/") != null) jar = jar + "/";
- if (jf.getEntry(jar) != null) {
+ ZipEntry entry = RubyFile.getDirOrFileEntry(jf, jar);
+ if (entry != null) {
status = func.call(bytes, begin, end, arg);
}
} catch(Exception e) {}
View
7 src/org/jruby/util/io/ChannelDescriptor.java
@@ -49,6 +49,7 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
+import org.jruby.RubyFile;
import org.jruby.RubyIO;
import org.jruby.ext.posix.POSIX;
@@ -627,13 +628,13 @@ public static ChannelDescriptor open(String cwd, String path, ModeFlags flags, i
}
JarFile jf = new JarFile(filePath);
- ZipEntry zf = jf.getEntry(internalPath);
+ ZipEntry entry = RubyFile.getFileEntry(jf, internalPath);
- if(zf == null) {
+ if (entry == null) {
throw new FileNotFoundException(path);
}
- InputStream is = jf.getInputStream(zf);
+ InputStream is = jf.getInputStream(entry);
// FIXME: don't use RubyIO for this
return new ChannelDescriptor(Channels.newChannel(is), RubyIO.getNewFileno(), flags, new FileDescriptor());
} else {
Please sign in to comment.
Something went wrong with that request. Please try again.