mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-14 08:58:46 +00:00
8148023: File.createTempFile is not adhering to the contract regarding file name lengths
Truncate the prefix, suffix, random characters per the specification Reviewed-by: rriggs
This commit is contained in:
parent
a717e4a14b
commit
2cae845615
@ -114,6 +114,7 @@ SUNWprivate_1.1 {
|
||||
Java_java_io_UnixFileSystem_getBooleanAttributes0;
|
||||
Java_java_io_UnixFileSystem_getLastModifiedTime;
|
||||
Java_java_io_UnixFileSystem_getLength;
|
||||
Java_java_io_UnixFileSystem_getNameMax0;
|
||||
Java_java_io_UnixFileSystem_getSpace;
|
||||
Java_java_io_UnixFileSystem_initIDs;
|
||||
Java_java_io_UnixFileSystem_list;
|
||||
|
||||
@ -1903,20 +1903,72 @@ public class File
|
||||
|
||||
// file name generation
|
||||
private static final SecureRandom random = new SecureRandom();
|
||||
private static int shortenSubName(int subNameLength, int excess,
|
||||
int nameMin) {
|
||||
int newLength = Math.max(nameMin, subNameLength - excess);
|
||||
if (newLength < subNameLength) {
|
||||
return newLength;
|
||||
}
|
||||
return subNameLength;
|
||||
}
|
||||
static File generateFile(String prefix, String suffix, File dir)
|
||||
throws IOException
|
||||
{
|
||||
long n = random.nextLong();
|
||||
String nus = Long.toUnsignedString(n);
|
||||
|
||||
// Use only the file name from the supplied prefix
|
||||
prefix = (new File(prefix)).getName();
|
||||
String name = prefix + Long.toUnsignedString(n) + suffix;
|
||||
|
||||
int prefixLength = prefix.length();
|
||||
int nusLength = nus.length();
|
||||
int suffixLength = suffix.length();;
|
||||
|
||||
String name;
|
||||
int nameMax = fs.getNameMax(dir.getPath());
|
||||
int excess = prefixLength + nusLength + suffixLength - nameMax;
|
||||
if (excess <= 0) {
|
||||
name = prefix + nus + suffix;
|
||||
} else {
|
||||
// Name exceeds the maximum path component length: shorten it
|
||||
|
||||
// Attempt to shorten the prefix length to no less then 3
|
||||
prefixLength = shortenSubName(prefixLength, excess, 3);
|
||||
excess = prefixLength + nusLength + suffixLength - nameMax;
|
||||
|
||||
if (excess > 0) {
|
||||
// Attempt to shorten the suffix length to no less than
|
||||
// 0 or 4 depending on whether it begins with a dot ('.')
|
||||
suffixLength = shortenSubName(suffixLength, excess,
|
||||
suffix.indexOf(".") == 0 ? 4 : 0);
|
||||
suffixLength = shortenSubName(suffixLength, excess, 3);
|
||||
excess = prefixLength + nusLength + suffixLength - nameMax;
|
||||
}
|
||||
|
||||
if (excess > 0 && excess <= nusLength - 5) {
|
||||
// Attempt to shorten the random character string length
|
||||
// to no less than 5
|
||||
nusLength = shortenSubName(nusLength, excess, 5);
|
||||
}
|
||||
|
||||
StringBuilder sb =
|
||||
new StringBuilder(prefixLength + nusLength + suffixLength);
|
||||
sb.append(prefixLength < prefix.length() ?
|
||||
prefix.substring(0, prefixLength) : prefix);
|
||||
sb.append(nusLength < nus.length() ?
|
||||
nus.substring(0, nusLength) : nus);
|
||||
sb.append(suffixLength < suffix.length() ?
|
||||
suffix.substring(0, suffixLength) : suffix);
|
||||
name = sb.toString();
|
||||
}
|
||||
|
||||
File f = new File(dir, name);
|
||||
if (!name.equals(f.getName()) || f.isInvalid()) {
|
||||
if (System.getSecurityManager() != null)
|
||||
throw new IOException("Unable to create temporary file");
|
||||
else
|
||||
throw new IOException("Unable to create temporary file, " + f);
|
||||
throw new IOException("Unable to create temporary file, "
|
||||
+ name);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -212,6 +212,13 @@ abstract class FileSystem {
|
||||
|
||||
/* -- Basic infrastructure -- */
|
||||
|
||||
/**
|
||||
* Retrieve the maximum length of a component of a file path.
|
||||
*
|
||||
* @return The maximum length of a file path component.
|
||||
*/
|
||||
public abstract int getNameMax(String path);
|
||||
|
||||
/**
|
||||
* Compare two abstract pathnames lexicographically.
|
||||
*/
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -299,6 +299,16 @@ class UnixFileSystem extends FileSystem {
|
||||
|
||||
/* -- Basic infrastructure -- */
|
||||
|
||||
private native long getNameMax0(String path);
|
||||
|
||||
public int getNameMax(String path) {
|
||||
long nameMax = getNameMax0(path);
|
||||
if (nameMax > Integer.MAX_VALUE) {
|
||||
nameMax = Integer.MAX_VALUE;
|
||||
}
|
||||
return (int)nameMax;
|
||||
}
|
||||
|
||||
public int compare(File f1, File f2) {
|
||||
return f1.getPath().compareTo(f2.getPath());
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,6 +23,7 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
@ -38,6 +39,10 @@
|
||||
#include <dlfcn.h>
|
||||
#include <limits.h>
|
||||
|
||||
#if defined(__solaris__) && !defined(NAME_MAX)
|
||||
#define NAME_MAX MAXNAMLEN
|
||||
#endif
|
||||
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
#include "jlong.h"
|
||||
@ -487,3 +492,14 @@ Java_java_io_UnixFileSystem_getSpace(JNIEnv *env, jobject this,
|
||||
} END_PLATFORM_STRING(env, path);
|
||||
return rv;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_java_io_UnixFileSystem_getNameMax0(JNIEnv *env, jobject this,
|
||||
jstring pathname)
|
||||
{
|
||||
jlong length = -1;
|
||||
WITH_PLATFORM_STRING(env, pathname, path) {
|
||||
length = (jlong)pathconf(path, _PC_NAME_MAX);
|
||||
} END_PLATFORM_STRING(env, path);
|
||||
return length != -1 ? length : (jlong)NAME_MAX;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,6 +25,8 @@
|
||||
|
||||
package java.io;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
@ -627,6 +629,27 @@ class WinNTFileSystem extends FileSystem {
|
||||
|
||||
/* -- Basic infrastructure -- */
|
||||
|
||||
// Obtain maximum file component length from GetVolumeInformation which
|
||||
// expects the path to be null or a root component ending in a backslash
|
||||
private native int getNameMax0(String path);
|
||||
|
||||
public int getNameMax(String path) {
|
||||
String s = null;
|
||||
if (path != null) {
|
||||
File f = new File(path);
|
||||
if (f.isAbsolute()) {
|
||||
Path root = f.toPath().getRoot();
|
||||
if (root != null) {
|
||||
s = root.toString();
|
||||
if (!s.endsWith("\\")) {
|
||||
s = s + "\\";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return getNameMax0(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(File f1, File f2) {
|
||||
return f1.getPath().compareToIgnoreCase(f2.getPath());
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -887,3 +887,42 @@ Java_java_io_WinNTFileSystem_getSpace0(JNIEnv *env, jobject this,
|
||||
free(pathbuf);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// pathname is expected to be either null or to contain the root
|
||||
// of the path terminated by a backslash
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_java_io_WinNTFileSystem_getNameMax0(JNIEnv *env, jobject this,
|
||||
jstring pathname)
|
||||
{
|
||||
BOOL res = 0;
|
||||
DWORD maxComponentLength;
|
||||
|
||||
if (pathname == NULL) {
|
||||
res = GetVolumeInformationW(NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
&maxComponentLength,
|
||||
NULL,
|
||||
NULL,
|
||||
0);
|
||||
} else {
|
||||
WITH_UNICODE_STRING(env, pathname, path) {
|
||||
res = GetVolumeInformationW(path,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
&maxComponentLength,
|
||||
NULL,
|
||||
NULL,
|
||||
0);
|
||||
} END_UNICODE_STRING(env, path);
|
||||
}
|
||||
|
||||
if (res == 0) {
|
||||
JNU_ThrowIOExceptionWithLastError(env,
|
||||
"Could not get maximum component length");
|
||||
}
|
||||
|
||||
return (jint)maxComponentLength;
|
||||
}
|
||||
|
||||
72
jdk/test/java/io/File/createTempFile/NameTooLong.java
Normal file
72
jdk/test/java/io/File/createTempFile/NameTooLong.java
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8148023
|
||||
* @summary Verify that createTempFile() will not fail for long component names.
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class NameTooLong {
|
||||
public static void main(String[] args) {
|
||||
String[][] prefixSuffix = new String[][] {
|
||||
new String[] {"1234567890123456789012345678901234567xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx89012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890","txt"},
|
||||
new String[] {"prefix","1234567890123456789012345678901234567xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx89012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890.txt"},
|
||||
new String[] {"prefix",".txt1234567890123456789012345678901234567xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx89012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"}
|
||||
};
|
||||
|
||||
int failures = 0;
|
||||
int index = 0;
|
||||
for (String[] ps : prefixSuffix) {
|
||||
File f;
|
||||
try {
|
||||
f = File.createTempFile(ps[0], ps[1]);
|
||||
String s = f.toPath().getFileName().toString();
|
||||
if (!s.startsWith(ps[0].substring(0, 3))) {
|
||||
System.err.printf("%s did not start with %s%n", s,
|
||||
ps[0].substring(0, 3));
|
||||
failures++;
|
||||
}
|
||||
if (ps[1].startsWith(".")
|
||||
&& !s.contains(ps[1].substring(0, 4))) {
|
||||
System.err.printf("%s did not contain %s%n", s,
|
||||
ps[1].substring(0, 4));;
|
||||
failures++;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
failures++;
|
||||
System.err.println();
|
||||
e.printStackTrace();
|
||||
System.err.println();
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
if (failures != 0) {
|
||||
throw new RuntimeException("Test failed!");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user