JDK-8194154 : System property user.dir should not be changed
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.io
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2017-12-25
  • Updated: 2022-08-02
  • Resolved: 2018-02-21
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 Other
11 b02Fixed openjdk8u342Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
if user defines -Duser.dir like "/home/a/b/c/", 
new File("./a").getCanonicalPath
will crash in processing double '/'
Comments
A pull request was submitted for review. URL: https://git.openjdk.java.net/jdk8u-dev/pull/8 Date: 2022-03-17 09:04:07 +0000
17-03-2022

[8u review] https://mail.openjdk.java.net/pipermail/jdk8u-dev/2022-January/014497.html
18-01-2022

URL: http://hg.openjdk.java.net/jdk/jdk/rev/847a988152b8 User: minqi Date: 2018-02-21 22:28:52 +0000
21-02-2018

The real reason, for why File.getCanonicalPath() will fail after "user.dir" property changed is, in File.java: public String getCanonicalPath() throws IOException { if (isInvalid()) { throw new IOException("Invalid file path"); } return fs.canonicalize(fs.resolve(this)); } It passed this File to FileSystem.resolve(File): public String resolve(File f) { if (isAbsolute(f)) return f.getPath(); return resolve(System.getProperty("user.dir"), f.getPath()); } resolve function requires the two strings are normalized, but here passed a raw string got from property user.dir directly.
15-02-2018

"/home/a/b/c//./a" will be split into 7 sub strings, the real number should be 6. In collapsible(char* names): while (*p) { if (*p == '/') { p++; break; } p++; } Since we have "//" in the string, it should check if *p is a '/' again before 'break'. Same check should be done in splitNames(char *names, char **ix): while (*p) { if (*p == '/') { *p++ = '\0'; break; } p++; } So the fix should be: diff -r 0454688cc319 src/java.base/unix/native/libjava/canonicalize_md.c --- a/src/java.base/unix/native/libjava/canonicalize_md.c Fri Feb 02 10:32:59 2018 -0800 +++ b/src/java.base/unix/native/libjava/canonicalize_md.c Tue Feb 06 00:15:09 2018 +0000 @@ -62,6 +62,7 @@ while (*p) { if (*p == '/') { p++; + if (*p == '/') continue; break; } p++; @@ -85,6 +86,7 @@ while (*p) { if (*p == '/') { *p++ = '\0'; + if (*p == '/') continue; break; } p++;
06-02-2018

This test failed with djk8+ (up to current develop ws) import java.io.*; import java.util.Properties; import java.lang.reflect.Field; public class ParseCanonicalPath { public static void main(String[] args) throws Exception { String osName = System.getProperty("os.name"); if (osName == null || !osName.startsWith("Linux")) { // skip test on non linux platform return; } Field f = System.class.getDeclaredField("props"); f.setAccessible(true); Properties p = (Properties) f.get(null); p.setProperty("user.dir", "/home/a/b/c/"); System.out.println(new File("./a").getCanonicalPath()); } } Partial hs_err output: # # A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc=0x00007f0b343226ce, pid=1044, tid=1045 # # JRE version: OpenJDK Runtime Environment (10.0) (build 10-internal+0-adhoc.yuminqi.submit) # Java VM: OpenJDK 64-Bit Server VM (10-internal+0-adhoc.yuminqi.submit, mixed mode, tiered, compressed oops, g1 gc, linux-amd64) # Problematic frame: # C [libjava.so+0x186ce] collapse+0xfe # # Core dump will be written. Default location: /cloud/data/corefile/core-%e-%p-%t-%h # # If you would like to submit a bug report, please visit: # http://bugreport.java.com/bugreport/crash.jsp # The crash happened outside the Java Virtual Machine in native code. # See problematic frame for where to report the bug. # --------------- S U M M A R Y ------------ Command Line: ParseCanonicalPath Host: Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz, 32 cores, 125G, Alibaba Group Enterprise Linux Server release 7.2 (Paladin) Time: Mon Feb 5 05:09:07 2018 UTC elapsed time: 0 seconds (0d 0h 0m 0s) --------------- T H R E A D --------------- Current thread (0x00007f0b3000f800): JavaThread "main" [_thread_in_native, id=1045, stack(0x00007f0b37156000,0x00007f0b37257000)] Stack: [0x00007f0b37156000,0x00007f0b37257000], sp=0x00007f0b37253720, free space=1013k Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code) C [libjava.so+0x186ce] collapse+0xfe C [libjava.so+0x18a60] canonicalize+0x1f0 C [libjava.so+0x176aa] Java_java_io_UnixFileSystem_canonicalize0+0x4a j java.io.UnixFileSystem.canonicalize0(Ljava/lang/String;)Ljava/lang/String;+0 java.base@10-internal j java.io.UnixFileSystem.canonicalize(Ljava/lang/String;)Ljava/lang/String;+140 java.base@10-internal j java.io.File.getCanonicalPath()Ljava/lang/String;+27 java.base@10-internal j ParseCanonicalPath.main([Ljava/lang/String;)V+63 v ~StubRoutines::call_stub V [libjvm.so+0x82d6e5] JavaCalls::call_helper(JavaValue*, methodHandle const&, JavaCallArguments*, Thread*)+0x3f5 V [libjvm.so+0x83da3d] jni_invoke_static(JNIEnv_*, JavaValue*, _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, Thread*) [clone .isra.176]+0x21d V [libjvm.so+0x850bbb] jni_CallStaticVoidMethod+0x16b C [libjli.so+0x45d4] JavaMain+0x9c4 Java frames: (J=compiled Java code, j=interpreted, Vv=VM code) j java.io.UnixFileSystem.canonicalize0(Ljava/lang/String;)Ljava/lang/String;+0 java.base@10-internal j java.io.UnixFileSystem.canonicalize(Ljava/lang/String;)Ljava/lang/String;+140 java.base@10-internal j java.io.File.getCanonicalPath()Ljava/lang/String;+27 java.base@10-internal j ParseCanonicalPath.main([Ljava/lang/String;)V+63 v ~StubRoutines::call_stub siginfo: si_signo: 11 (SIGSEGV), si_code: 1 (SEGV_MAPERR), si_addr: 0x0000000000000000 Register to memory mapping: RAX=0x0000000000000006 is an unknown value RBX=0x0000000000000007 is an unknown value RCX=0x0000000000000000 is an unknown value RDX=0x00007f0b37253750 is pointing into the stack for thread: 0x00007f0b3000f800 RSP=0x00007f0b37253720 is pointing into the stack for thread: 0x00007f0b3000f800 RBP=0x00007f0b37253790 is pointing into the stack for thread: 0x00007f0b3000f800 RSI=0x00007f0b37254810 is pointing into the stack for thread: 0x00007f0b3000f800 RDI=0x00007f0b37254800 is pointing into the stack for thread: 0x00007f0b3000f800 R8 =0x00007f0b37254800 is pointing into the stack for thread: 0x00007f0b3000f800 R9 =0x0000000000000011 is an unknown value R10= [error occurred during error reporting (printing register info), id 0xb] Registers: RAX=0x0000000000000006, RBX=0x0000000000000007, RCX=0x0000000000000000, RDX=0x00007f0b37253750 RSP=0x00007f0b37253720, RBP=0x00007f0b37253790, RSI=0x00007f0b37254810, RDI=0x00007f0b37254800 R8 =0x00007f0b37254800, R9 =0x0000000000000011, R10=0x00000000ffffffe0, R11=0x00007f0b365b6b40 R12=0x00007f0b37254801, R13=0x00007f0b37253720, R14=0x00007f0b372537b0, R15=0x00007f0b372537b6 RIP=0x00007f0b343226ce, EFLAGS=0x0000000000010297, CSGSFS=0x0000000000000033, ERR=0x0000000000000004 TRAPNO=0x000000000000000e Top of Stack: (sp=0x00007f0b37253720) 0x00007f0b37253720: 00007f0b37254801 00007f0b37254806 0x00007f0b37253730: 00007f0b37254808 00007f0b3725480a 0x00007f0b37253740: 00007f0b3725480c 00007f0b3725480f 0x00007f0b37253750: 0000000000000000 0000000000000000 Instructions: (pc=0x00007f0b343226ce) 0x00007f0b343226ae: 66 90 48 63 d0 49 8d 54 d5 00 eb 11 66 0f 1f 44 0x00007f0b343226be: 00 00 83 c0 01 48 83 c2 08 39 d8 7d 75 48 8b 0a 0x00007f0b343226ce: 80 39 2e 75 ed 0f b6 71 01 40 84 f6 0f 84 68 01 0x00007f0b343226de: 00 00 40 80 fe 2e 75 da 80 79 02 00 75 d4 39 d8 --------------- P R O C E S S --------------- Threads class SMR info: _java_thread_list=0x00007f0b30506d60, length=22, elements={ 0x00007f0b3000f800, 0x00007f0b3044f000, 0x00007f0b30451000, 0x00007f0b3045a800, 0x00007f0b30465000, 0x00007f0b30467000, 0x00007f0b30469800, 0x00007f0b3046b800, 0x00007f0b3046d800, 0x00007f0b3046f800, 0x00007f0b3047b800, 0x00007f0b3047d800, 0x00007f0b3047f800, 0x00007f0b30482000, 0x00007f0b30484000, 0x00007f0b30486000, 0x00007f0b30488000, 0x00007f0b3048a000, 0x00007f0b3048c000, 0x00007f0b3048d800, 0x00007f0b304f7000, 0x00007f0b30505800 } Java Threads: ( => current thread ) =>0x00007f0b3000f800 JavaThread "main" [_thread_in_native, id=1045, stack(0x00007f0b37156000,0x00007f0b37257000)] 0x00007f0b3044f000 JavaThread "Reference Handler" daemon [_thread_blocked, id=1101, stack(0x00007f0a228f1000,0x00007f0a229f2000)] 0x00007f0b30451000 JavaThread "Finalizer" daemon [_thread_blocked, id=1102, stack(0x00007f0a227f0000,0x00007f0a228f1000)] 0x00007f0b3045a800 JavaThread "Signal Dispatcher" daemon [_thread_blocked, id=1103, stack(0x00007f0a226ef000,0x00007f0a227f0000)] 0x00007f0b30465000 JavaThread "C2 CompilerThread0" daemon [_thread_blocked, id=1104, stack(0x00007f0a225ee000,0x00007f0a226ef000)] 0x00007f0b30467000 JavaThread "C2 CompilerThread1" daemon [_thread_blocked, id=1105, stack(0x00007f0a224ed000,0x00007f0a225ee000)] 0x00007f0b30469800 JavaThread "C2 CompilerThread2" daemon [_thread_blocked, id=1106, stack(0x00007f0a223ec000,0x00007f0a224ed000)] 0x00007f0b3046b800 JavaThread "C2 CompilerThread3" daemon [_thread_blocked, id=1107, stack(0x00007f0a222eb000,0x00007f0a223ec000)] .... live debug showed (not the coredump of above): #9 <signal handler called> #10 collapse (path=path@entry=0x7f6da1539800 "/home") at /home/yumin.qi/ws/openjdk/submit/src/java.base/unix/native/libjava/canonicalize_md.c:147 #11 0x00007f6d9e607a60 in canonicalize (original=original@entry=0x7f6d9852cdc0 "/home/a/b/c//./a", resolved=resolved@entry=0x7f6da1539800 "/home", len=len@entry=4096) at /home/yumin.qi/ws/openjdk/submit/src/java.base/unix/native/libjava/canonicalize_md.c:261 #12 0x00007f6d9e6066aa in Java_java_io_UnixFileSystem_canonicalize0 (env=0x7f6d9800fa00, this=<optimized out>, pathname=0x7f6da153a8a8) at /home/yumin.qi/ws/openjdk/submit/src/java.base/unix/native/libjava/UnixFileSystem_md.c:103 #13 0x00007f6d7fb30870 in ?? () #14 0x00007f6cb8ff81af in ?? () #15 0x00007f6da153a8b0 in ?? () #16 0x00007f6da153a840 in ?? () #17 0x0000000000000000 in ?? () here, path of argument passed to collapse(char* path) is "/home". Somehow the collapsible(names), names is "home" returns 6? it should return 0 instead.
05-02-2018

Right, it's not supported to change the value of user.dir on the command line or in a running VM. At the same time, it would be useful to get more information into the bug report on what the crash is.
28-12-2017

This bug report needs more details than "crash". It's probably a bad idea to set the user.dir system property. Normally one should let java startup set it automatically. None of this should be Linux-specific. All APIs on Posix systems should treat a sequence of more than one '/' equivalently to exactly one.
27-12-2017