Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NPE protection on WebInfConfiguration.deconfigure() #5481

Merged
merged 5 commits into from
Oct 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
62 changes: 62 additions & 0 deletions jetty-io/src/test/java/org/eclipse/jetty/io/IOTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
Expand All @@ -41,12 +42,15 @@
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.IO;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.api.extension.ExtendWith;

Expand Down Expand Up @@ -449,6 +453,64 @@ public void testGatherWrite() throws Exception
}
}

@Test
public void testDeleteNull()
{
assertFalse(IO.delete(null));
}

@Test
public void testDeleteNonExistentFile(TestInfo testInfo)
{
File dir = MavenTestingUtils.getTargetTestingDir(testInfo.getDisplayName());
FS.ensureEmpty(dir);
File noFile = new File(dir, "nada");
assertFalse(IO.delete(noFile));
}

@Test
public void testIsEmptyNull()
{
assertTrue(IO.isEmptyDir(null));
}

@Test
public void testIsEmptyDoesNotExist(TestInfo testInfo)
{
File dir = MavenTestingUtils.getTargetTestingDir(testInfo.getDisplayName());
FS.ensureEmpty(dir);
File noFile = new File(dir, "nada");
assertTrue(IO.isEmptyDir(noFile));
}

@Test
public void testIsEmptyExistButAsFile(TestInfo testInfo) throws IOException
{
File dir = MavenTestingUtils.getTargetTestingDir(testInfo.getDisplayName());
FS.ensureEmpty(dir);
File file = new File(dir, "nada");
FS.touch(file);
assertFalse(IO.isEmptyDir(file));
}

@Test
public void testIsEmptyExistAndIsEmpty(TestInfo testInfo)
{
File dir = MavenTestingUtils.getTargetTestingDir(testInfo.getDisplayName());
FS.ensureEmpty(dir);
assertTrue(IO.isEmptyDir(dir));
}

@Test
public void testIsEmptyExistAndHasContent(TestInfo testInfo) throws IOException
{
File dir = MavenTestingUtils.getTargetTestingDir(testInfo.getDisplayName());
FS.ensureEmpty(dir);
File file = new File(dir, "nada");
FS.touch(file);
assertFalse(IO.isEmptyDir(dir));
}

@Test
public void testSelectorWakeup() throws Exception
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.util.PathWatcher;
import org.eclipse.jetty.util.Scanner;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.resource.Resource;
Expand Down Expand Up @@ -559,7 +558,12 @@ public void configureWebApplication() throws Exception
File target = new File(project.getBuild().getDirectory());
File tmp = new File(target, "tmp");
if (!tmp.exists())
tmp.mkdirs();
{
if (!tmp.mkdirs())
{
throw new MojoFailureException("Unable to create temp directory: " + tmp);
}
}
webApp.setTempDirectory(tmp);
}

Expand Down
26 changes: 25 additions & 1 deletion jetty-util/src/main/java/org/eclipse/jetty/util/IO.java
Original file line number Diff line number Diff line change
Expand Up @@ -361,10 +361,13 @@ public static String toString(Reader in)
* This delete will recursively delete directories - BE CAREFUL
*
* @param file The file (or directory) to be deleted.
* @return true if anything was deleted. (note: this does not mean that all content in a directory was deleted)
* @return true if file was deleted, or directory referenced was deleted.
* false if file doesn't exist, or was null.
*/
public static boolean delete(File file)
{
if (file == null)
return false;
if (!file.exists())
return false;
if (file.isDirectory())
Expand All @@ -378,6 +381,27 @@ public static boolean delete(File file)
return file.delete();
}

/**
* Test if directory is empty.
*
* @param dir the directory
* @return true if directory is null, doesn't exist, or has no content.
* false if not a directory, or has contents
*/
public static boolean isEmptyDir(File dir)
{
if (dir == null)
return true;
if (!dir.exists())
return true;
if (!dir.isDirectory())
return false;
String[] list = dir.list();
if (list == null)
return true;
return list.length <= 0;
}

/**
* Closes an arbitrary closable, and logs exceptions at ignore level
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -354,10 +354,12 @@ public void configure(WebAppContext context) throws Exception
@Override
public void deconfigure(WebAppContext context) throws Exception
{
//if we're not persisting the temp dir contents delete it
if (!context.isPersistTempDirectory())
File tempDirectory = context.getTempDirectory();

// if we're not persisting the temp dir contents delete it
if (!context.isPersistTempDirectory() && !IO.isEmptyDir(tempDirectory))
{
IO.delete(context.getTempDirectory());
IO.delete(tempDirectory);
}

//if it wasn't explicitly configured by the user, then unset it
Expand Down Expand Up @@ -504,13 +506,15 @@ public void makeTempDirectory(File parent, WebAppContext context)
//if it is to be persisted, make sure it will be the same name
//by not using File.createTempFile, which appends random digits
tmpDir = new File(parent, temp);
configureTempDirectory(tmpDir, context);
gregw marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
//ensure file will always be unique by appending random digits
// ensure dir will always be unique by having classlib generate random path name
tmpDir = Files.createTempDirectory(parent.toPath(), temp).toFile();
tmpDir.deleteOnExit();
ensureTempDirUsable(tmpDir);
janbartel marked this conversation as resolved.
Show resolved Hide resolved
}
configureTempDirectory(tmpDir, context);

if (LOG.isDebugEnabled())
LOG.debug("Set temp dir " + tmpDir);
Expand All @@ -522,21 +526,30 @@ public void configureTempDirectory(File dir, WebAppContext context)
if (dir == null)
throw new IllegalArgumentException("Null temp dir");

//if dir exists and we don't want it persisted, delete it
if (dir.exists() && !context.isPersistTempDirectory())
// if dir exists and we don't want it persisted, delete it
if (!context.isPersistTempDirectory() && dir.exists() && !IO.delete(dir))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how hard is it to check if it is empty or not. if it is empty, it would be good to avoid deleting it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not to terrible to check if empty.
Let me try.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been implemented and is available in this PR.

{
if (!IO.delete(dir))
throw new IllegalStateException("Failed to delete temp dir " + dir);
throw new IllegalStateException("Failed to delete temp dir " + dir);
}

//if it doesn't exist make it
// if it doesn't exist make it
janbartel marked this conversation as resolved.
Show resolved Hide resolved
if (!dir.exists())
gregw marked this conversation as resolved.
Show resolved Hide resolved
dir.mkdirs();
{
if (!dir.mkdirs())
{
throw new IllegalStateException("Unable to create temp dir " + dir);
}
}

if (!context.isPersistTempDirectory())
dir.deleteOnExit();

//is it useable
ensureTempDirUsable(dir);
}

private void ensureTempDirUsable(File dir)
{
// is it useable
janbartel marked this conversation as resolved.
Show resolved Hide resolved
if (!dir.canWrite() || !dir.isDirectory())
throw new IllegalStateException("Temp dir " + dir + " not useable: writeable=" + dir.canWrite() + ", dir=" + dir.isDirectory());
}
Expand Down