Skip to content

Commit 610155b

Browse files
authored
Merge pull request from GHSA-269g-pwp5-87pp
When running on Java 7 or later, temporary directories are now created Using Java’s NIO API which restricts permissions to owner-only by default.
1 parent b6cfd1e commit 610155b

File tree

2 files changed

+78
-2
lines changed

2 files changed

+78
-2
lines changed

src/main/java/org/junit/rules/TemporaryFolder.java

+42-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
import java.io.File;
66
import java.io.IOException;
7+
import java.lang.reflect.Array;
8+
import java.lang.reflect.InvocationTargetException;
9+
import java.lang.reflect.Method;
710

811
import org.junit.Rule;
912

@@ -229,7 +232,45 @@ public File newFolder() throws IOException {
229232
return createTemporaryFolderIn(getRoot());
230233
}
231234

232-
private File createTemporaryFolderIn(File parentFolder) throws IOException {
235+
private static File createTemporaryFolderIn(File parentFolder) throws IOException {
236+
try {
237+
return createTemporaryFolderWithNioApi(parentFolder);
238+
} catch (ClassNotFoundException ignore) {
239+
// Fallback for Java 5 and 6
240+
return createTemporaryFolderWithFileApi(parentFolder);
241+
} catch (InvocationTargetException e) {
242+
Throwable cause = e.getCause();
243+
if (cause instanceof IOException) {
244+
throw (IOException) cause;
245+
}
246+
if (cause instanceof RuntimeException) {
247+
throw (RuntimeException) cause;
248+
}
249+
IOException exception = new IOException("Failed to create temporary folder in " + parentFolder);
250+
exception.initCause(cause);
251+
throw exception;
252+
} catch (Exception e) {
253+
throw new RuntimeException("Failed to create temporary folder in " + parentFolder, e);
254+
}
255+
}
256+
257+
private static File createTemporaryFolderWithNioApi(File parentFolder) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
258+
Class<?> filesClass = Class.forName("java.nio.file.Files");
259+
Object fileAttributeArray = Array.newInstance(Class.forName("java.nio.file.attribute.FileAttribute"), 0);
260+
Class<?> pathClass = Class.forName("java.nio.file.Path");
261+
Object tempDir;
262+
if (parentFolder != null) {
263+
Method createTempDirectoryMethod = filesClass.getDeclaredMethod("createTempDirectory", pathClass, String.class, fileAttributeArray.getClass());
264+
Object parentPath = File.class.getDeclaredMethod("toPath").invoke(parentFolder);
265+
tempDir = createTempDirectoryMethod.invoke(null, parentPath, TMP_PREFIX, fileAttributeArray);
266+
} else {
267+
Method createTempDirectoryMethod = filesClass.getDeclaredMethod("createTempDirectory", String.class, fileAttributeArray.getClass());
268+
tempDir = createTempDirectoryMethod.invoke(null, TMP_PREFIX, fileAttributeArray);
269+
}
270+
return (File) pathClass.getDeclaredMethod("toFile").invoke(tempDir);
271+
}
272+
273+
private static File createTemporaryFolderWithFileApi(File parentFolder) throws IOException {
233274
File createdFolder = null;
234275
for (int i = 0; i < TEMP_DIR_ATTEMPTS; ++i) {
235276
// Use createTempFile to get a suitable folder name.

src/test/java/org/junit/rules/TempFolderRuleTest.java

+36-1
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,28 @@
33
import static org.hamcrest.CoreMatchers.hasItem;
44
import static org.hamcrest.MatcherAssert.assertThat;
55
import static org.hamcrest.core.IsNot.not;
6+
import static org.junit.Assert.assertEquals;
67
import static org.junit.Assert.assertFalse;
78
import static org.junit.Assert.assertTrue;
9+
import static org.junit.Assume.assumeTrue;
810
import static org.junit.experimental.results.PrintableResult.testResult;
911
import static org.junit.experimental.results.ResultMatchers.failureCountIs;
1012
import static org.junit.experimental.results.ResultMatchers.isSuccessful;
1113

1214
import java.io.File;
1315
import java.io.IOException;
16+
import java.lang.reflect.Array;
17+
import java.lang.reflect.InvocationTargetException;
1418
import java.lang.reflect.Method;
1519
import java.util.Arrays;
20+
import java.util.Set;
21+
import java.util.SortedSet;
22+
import java.util.TreeSet;
1623

1724
import org.junit.After;
25+
import org.junit.AssumptionViolatedException;
1826
import org.junit.Rule;
1927
import org.junit.Test;
20-
import org.junit.rules.TemporaryFolder;
2128

2229
public class TempFolderRuleTest {
2330
private static File[] createdFiles = new File[20];
@@ -182,6 +189,34 @@ public void recursiveDeleteFolderWithZeroElements() throws IOException {
182189
assertFalse(folder.getRoot().exists());
183190
}
184191

192+
@Test
193+
public void tempFolderIsOnlyAccessibleByOwner() throws IOException {
194+
TemporaryFolder folder = new TemporaryFolder();
195+
folder.create();
196+
197+
Set<String> expectedPermissions = new TreeSet<String>(Arrays.asList("OWNER_READ", "OWNER_WRITE", "OWNER_EXECUTE"));
198+
Set<String> actualPermissions = getPosixFilePermissions(folder.getRoot());
199+
assertEquals(expectedPermissions, actualPermissions);
200+
}
201+
202+
private Set<String> getPosixFilePermissions(File root) {
203+
try {
204+
Class<?> pathClass = Class.forName("java.nio.file.Path");
205+
Object linkOptionArray = Array.newInstance(Class.forName("java.nio.file.LinkOption"), 0);
206+
Class<?> filesClass = Class.forName("java.nio.file.Files");
207+
Object path = File.class.getDeclaredMethod("toPath").invoke(root);
208+
Method posixFilePermissionsMethod = filesClass.getDeclaredMethod("getPosixFilePermissions", pathClass, linkOptionArray.getClass());
209+
Set<?> permissions = (Set<?>) posixFilePermissionsMethod.invoke(null, path, linkOptionArray);
210+
SortedSet<String> convertedPermissions = new TreeSet<String>();
211+
for (Object item : permissions) {
212+
convertedPermissions.add(item.toString());
213+
}
214+
return convertedPermissions;
215+
} catch (Exception e) {
216+
throw new AssumptionViolatedException("Test requires at least Java 1.7", e);
217+
}
218+
}
219+
185220
public static class NameClashes {
186221
@Rule
187222
public TemporaryFolder folder = new TemporaryFolder();

0 commit comments

Comments
 (0)