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.
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.