United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6481955 Uncanonicalized absolute filepath with length 248-260 no longer works (win)
JDK-6481955 : Uncanonicalized absolute filepath with length 248-260 no longer works (win)

Details
Type:
Bug
Submit Date:
2006-10-13
Status:
Resolved
Updated Date:
2010-04-02
Project Name:
JDK
Resolved Date:
2006-12-12
Component:
core-libs
OS:
generic
Sub-Component:
java.io
CPU:
generic
Priority:
P2
Resolution:
Fixed
Affected Versions:
5.0u6,6,OpenJDK6
Fixed Versions:
6u1 (b01)

Related Reports
Backport:
Backport:
Backport:
Relates:

Sub Tasks

Description
Between 1.5.0_05 and 1.5.0_06 a length limit on 248 characters
was introduced on relative paths which can cause severe grievances
for people upgrading. Before the "fix" files of length 260 could be used.

import java.io.*;

public class TestPathLength {
	private static String longFilename = "C:\\tmp\\.\\";
	private static String padding = "1234567890123456789012345678901234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890";
	
	public static void main(String[] args) {
		for (int i = 230; i < 260; i++) {
			String tmpName = longFilename + padding.substring(0, i) + ".txt";
			try {
				FileWriter fw = new FileWriter(tmpName);
				fw.close();
			} catch (Exception e) {
				System.out.println("Failed at length: " + tmpName.length());
				break;
			}
		}
	}
}

                                    

Comments
WORK AROUND

Canonicalize the filepath if its length is bigger than 248. For example, 
new File(path).getCanonicalPath().
                                     
2006-10-13
SUGGESTED FIX

--- io_util_md.c	Fri Oct 13 11:53:52 2006
***************
*** 86,91 ****
--- 86,113 ----
      }
  }
  
+ WCHAR* prefixAbpath(const WCHAR* path, int pathlen, int abpathlen) {
+     WCHAR* pathbuf = NULL;
+     WCHAR* abpath = (WCHAR*)malloc(abpathlen * sizeof(WCHAR));
+     if (abpath) {
+         if (_wfullpath(abpath, path, abpathlen)) { 
+ 	    pathbuf = getPrefixed(abpath, abpathlen);
+ 	} else {
+ 	    /* _wfullpath fails if the pathlength exceeds 32k wchar.
+ 	       Instead of doing more fancy things we simply copy the
+ 	       ps into the return buffer, the subsequent win32 API will
+ 	       probably fail with FileNotFoundException, which is expected
+ 	    */
+ 	    pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR));
+ 	    if (pathbuf != 0) {
+ 	        wcscpy(pathbuf, path);
+ 	    }
+ 	}
+ 	free(abpath);
+     }
+     return pathbuf;
+ }
+ 
  /* If this returns NULL then an exception is pending */
  WCHAR* 
  pathToNTPath(JNIEnv *env, jstring path, jboolean throwFNFE) {
***************
*** 102,108 ****
                  (ps[0] == L'\\' && ps[1] == L'\\' ||   //UNC
                   ps[1] == L':' && ps[2] == L'\\')) {   //absolute
                   if (pathlen > max_path - 1) {
!                      pathbuf = getPrefixed(ps, pathlen);
                   } else {
                       pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR));
                       if (pathbuf != 0) {
--- 124,130 ----
                  (ps[0] == L'\\' && ps[1] == L'\\' ||   //UNC
                   ps[1] == L':' && ps[2] == L'\\')) {   //absolute
                   if (pathlen > max_path - 1) {
! 		     pathbuf = prefixAbpath(ps, pathlen, pathlen);
                   } else {
                       pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR));
                       if (pathbuf != 0) {
***************
*** 126,148 ****
                  int dirlen = currentDirLength(ps, pathlen);
                  if (dirlen + pathlen + 1 > max_path - 1) {
                      int abpathlen = dirlen + pathlen + 10; 
!                     abpath = (WCHAR*)malloc(abpathlen * sizeof(WCHAR));
!                     if (abpath) {
!                         if (_wfullpath(abpath, ps, abpathlen)) { 
!                             pathbuf = getPrefixed(abpath, abpathlen);
!                         } else {
! 			    /* _wfullpath fails if the pathlength exceeds 32k wchar.
!                                Instead of doing more fancy things we simply copy the
!                                ps into the return buffer, the subsequent win32 API will
!                                probably fail with FileNotFoundException, which is expected
!                              */
!                             pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR));
!                             if (pathbuf != 0) {
!                                 wcscpy(pathbuf, ps);
!                             }
!                         }
!                         free(abpath);
!                     }
                  } else {
                      pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR));
                      if (pathbuf != 0) {
--- 148,154 ----
                  int dirlen = currentDirLength(ps, pathlen);
                  if (dirlen + pathlen + 1 > max_path - 1) {
                      int abpathlen = dirlen + pathlen + 10; 
!                     pathbuf = prefixAbpath(ps, pathlen, abpathlen);
                  } else {
                      pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR));
                      if (pathbuf != 0) {
                                     
2006-10-13
EVALUATION

Regression introduced with the fix for #4403166. The implementation has a lopehole
when dealing with a un-canonicalized absolute filepath (means it's in absolute form
but has relative components, such as "../" or "./" in its path). As specified by
the Windows API, the "\\?\" prefix does not work with a relative path, obviously
this also includes the "relative path component". Invoking the _wfullpath to
"canonicalize" the path before adding the prefix to solve this problem. See suggested
fix.

The fix need go back to 5.0u and 6.0u asap.
                                     
2006-10-13



Hardware and Software, Engineered to Work Together