summaryrefslogtreecommitdiffstats
path: root/tzdata
diff options
context:
space:
mode:
authorNeil Fuller <nfuller@google.com>2015-08-05 19:59:32 +0100
committerNeil Fuller <nfuller@google.com>2015-08-05 19:59:32 +0100
commite9a8e16980a5733852a829c48ed38497cff610b1 (patch)
tree0614dfdd0d5b2e53e6b963d47eb34e710095f2ca /tzdata
parent6b37f0bb40c3789833a9fd02c321d68354c6ecaf (diff)
downloadlibcore-e9a8e16980a5733852a829c48ed38497cff610b1.zip
libcore-e9a8e16980a5733852a829c48ed38497cff610b1.tar.gz
libcore-e9a8e16980a5733852a829c48ed38497cff610b1.tar.bz2
Fix FileUtilsTest.testCreateSubFile for Android One devices
createSubFile() was assuming that java.io.tmpdir did not itself contain symlink. Generally true, but not for Android One devices. Previously the createSubFile() would have tolerated a name parameter that directly referenced a symlink that pointed outside of the parent dir (though not if the symlink was actually dereferenced). This is unnecessarily lenient and making it stricter makes the code simpler. This fixes the FileUtils code and fixes/adds more cases to the FileUtilsTest to confirm it all works as intended when existing files and directories are present. This change only affects the TzDataBundleInstaller which is only executed in the event of an over-the-air timezone data update. Bug: 22836194 Change-Id: I05666c7387d469e79309a6fb0eeafba7e2a3299b
Diffstat (limited to 'tzdata')
-rw-r--r--tzdata/update/src/main/libcore/tzdata/update/ConfigBundle.java2
-rw-r--r--tzdata/update/src/main/libcore/tzdata/update/FileUtils.java30
-rw-r--r--tzdata/update/src/test/libcore/tzdata/update/FileUtilsTest.java29
3 files changed, 31 insertions, 30 deletions
diff --git a/tzdata/update/src/main/libcore/tzdata/update/ConfigBundle.java b/tzdata/update/src/main/libcore/tzdata/update/ConfigBundle.java
index 6e2ff9d..b497c85 100644
--- a/tzdata/update/src/main/libcore/tzdata/update/ConfigBundle.java
+++ b/tzdata/update/src/main/libcore/tzdata/update/ConfigBundle.java
@@ -72,6 +72,8 @@ public final class ConfigBundle {
// Validate the entry name: make sure the unpacked file will exist beneath the
// targetDir.
String name = entry.getName();
+ // Note, we assume that nothing will quickly insert a symlink after createSubFile()
+ // that might invalidate the guarantees about name existing beneath targetDir.
File entryFile = FileUtils.createSubFile(targetDir, name);
if (entry.isDirectory()) {
diff --git a/tzdata/update/src/main/libcore/tzdata/update/FileUtils.java b/tzdata/update/src/main/libcore/tzdata/update/FileUtils.java
index 8b7da78..652b786 100644
--- a/tzdata/update/src/main/libcore/tzdata/update/FileUtils.java
+++ b/tzdata/update/src/main/libcore/tzdata/update/FileUtils.java
@@ -37,19 +37,18 @@ public final class FileUtils {
/**
* Creates a new {@link java.io.File} from the {@code parentDir} and {@code name}, but only if
- * the
- * resulting file would exist beneath {@code parentDir}. Useful if {@code name} could contain
- * "/../" or symlinks. The returned object has an absolute path.
+ * the resulting file would exist beneath {@code parentDir}. Useful if {@code name} could
+ * contain "/../" or symlinks. The returned object has a canonicalized path.
*
- * @throws java.io.IOException
- * if the file would not exist beneath {@code parentDir}
+ * @throws java.io.IOException if the file would not exist beneath {@code parentDir}
*/
public static File createSubFile(File parentDir, String name) throws IOException {
// The subFile must exist beneath parentDir. If name contains "/../" this may not be the
// case so we check.
- File subFile = canonicalizeDirPath(new File(parentDir, name));
+ File subFile = new File(parentDir, name).getCanonicalFile();
if (!subFile.getPath().startsWith(parentDir.getCanonicalPath())) {
- throw new IOException(name + " must exist beneath " + parentDir);
+ throw new IOException(name + " must exist beneath " + parentDir +
+ ". Canonicalized subpath: " + subFile);
}
return subFile;
}
@@ -61,8 +60,8 @@ public final class FileUtils {
* directories explicitly created will have their permissions set; existing directories are
* untouched.
*
- * @throws IOException
- * if the directory or one of its parents did not already exist and could not be created
+ * @throws IOException if the directory or one of its parents did not already exist and could
+ * not be created
*/
public static void ensureDirectoriesExist(File dir, boolean makeWorldReadable)
throws IOException {
@@ -87,14 +86,6 @@ public final class FileUtils {
}
}
- /**
- * Returns a file with all symlinks and relative paths such as "/../" resolved <em>except</em>
- * for the base name (the last element of the path). Useful for detecting symlinks.
- */
- public static File canonicalizeDirPath(File file) throws IOException {
- return new File(file.getParentFile().getCanonicalFile(), file.getName());
- }
-
public static void makeDirectoryWorldAccessible(File directory) throws IOException {
if (!directory.isDirectory()) {
throw new IOException(directory + " must be a directory");
@@ -150,7 +141,10 @@ public final class FileUtils {
}
public static boolean isSymlink(File file) throws IOException {
- return !file.getCanonicalPath().equals(canonicalizeDirPath(file).getPath());
+ String baseName = file.getName();
+ String canonicalPathExceptBaseName =
+ new File(file.getParentFile().getCanonicalFile(), baseName).getPath();
+ return !file.getCanonicalPath().equals(canonicalPathExceptBaseName);
}
public static void deleteRecursive(File toDelete) throws IOException {
diff --git a/tzdata/update/src/test/libcore/tzdata/update/FileUtilsTest.java b/tzdata/update/src/test/libcore/tzdata/update/FileUtilsTest.java
index ce02bfe..d002820 100644
--- a/tzdata/update/src/test/libcore/tzdata/update/FileUtilsTest.java
+++ b/tzdata/update/src/test/libcore/tzdata/update/FileUtilsTest.java
@@ -113,21 +113,30 @@ public class FileUtilsTest extends TestCase {
}
public void testCreateSubFile() throws Exception {
- File dir1 = createTempDir();
- File subFile = FileUtils.createSubFile(dir1, "file");
- assertFileCanonicalEquals(new File(dir1, "file"), subFile);
+ File dir1 = createTempDir().getCanonicalFile();
+
+ File actualSubFile = FileUtils.createSubFile(dir1, "file");
+ assertEquals(new File(dir1, "file"), actualSubFile);
+
+ File existingSubFile = createRegularFile(dir1, "file");
+ actualSubFile = FileUtils.createSubFile(dir1, "file");
+ assertEquals(existingSubFile, actualSubFile);
+
+ File existingSubDir = createDir(dir1, "subdir");
+ actualSubFile = FileUtils.createSubFile(dir1, "subdir");
+ assertEquals(existingSubDir, actualSubFile);
assertCreateSubFileThrows(dir1, "../file");
assertCreateSubFileThrows(dir1, "../../file");
assertCreateSubFileThrows(dir1, "../otherdir/file");
- File dir2 = createTempDir();
- File dir2Subdir = createDir(dir2, "dir2Subdir");
- File expectedSymlinkToDir2 = createSymlink(dir2Subdir, dir1, "symlinkToDir2");
+ File dir2 = createTempDir().getCanonicalFile();
+ createSymlink(dir2, dir1, "symlinkToDir2");
+ assertCreateSubFileThrows(dir1, "symlinkToDir2");
- File actualSymlinkToDir2 = FileUtils.createSubFile(dir1, "symlinkToDir2");
- assertEquals(expectedSymlinkToDir2, actualSymlinkToDir2);
+ assertCreateSubFileThrows(dir1, "symlinkToDir2/fileInSymlinkedDir");
+ createRegularFile(dir1, "symlinkToDir2/fileInSymlinkedDir");
assertCreateSubFileThrows(dir1, "symlinkToDir2/fileInSymlinkedDir");
}
@@ -295,10 +304,6 @@ public class FileUtilsTest extends TestCase {
(sb.st_mode & mask) == mask);
}
- private static void assertFileCanonicalEquals(File expected, File actual) throws IOException {
- assertEquals(expected.getCanonicalFile(), actual.getCanonicalFile());
- }
-
private File createTempDir() {
final String tempPrefix = getClass().getSimpleName();
File tempDir = IoUtils.createTemporaryDirectory(tempPrefix);