From f1332640d4b2dc251662d9ce92559672eeda6718 Mon Sep 17 00:00:00 2001
From: Erik Joelsson <erikj@openjdk.org>
Date: Wed, 5 Feb 2020 09:33:25 -0800
Subject: [PATCH] 8238225: Issues reported after replacing symlink at
 Contents/MacOS/libjli.dylib with binary

Reviewed-by: clanger, alanb, ihse
---
 .../macosx/native/libjli/java_md_macosx.m     | 20 ++++++++++++--
 test/jdk/tools/launcher/JliLaunchTest.java    | 26 ++++++++++++++++---
 2 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/src/java.base/macosx/native/libjli/java_md_macosx.m b/src/java.base/macosx/native/libjli/java_md_macosx.m
index 9f71cb99a19..0ecfc903b7b 100644
--- a/src/java.base/macosx/native/libjli/java_md_macosx.m
+++ b/src/java.base/macosx/native/libjli/java_md_macosx.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2020, 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
@@ -515,11 +515,27 @@ GetJREPath(char *path, jint pathsize, jboolean speculative)
     }
 
     size_t indexOfLastPathComponent = pathLen - sizeOfLastPathComponent;
-    if (0 == strncmp(realPathToSelf + indexOfLastPathComponent, lastPathComponent, sizeOfLastPathComponent - 1)) {
+    if (0 == strncmp(realPathToSelf + indexOfLastPathComponent, lastPathComponent, sizeOfLastPathComponent)) {
         realPathToSelf[indexOfLastPathComponent + 1] = '\0';
         return JNI_TRUE;
     }
 
+    // If libjli.dylib is loaded from a macos bundle MacOS dir, find the JRE dir
+    // in ../Home.
+    const char altLastPathComponent[] = "/MacOS/libjli.dylib";
+    size_t sizeOfAltLastPathComponent = sizeof(altLastPathComponent) - 1;
+    if (pathLen < sizeOfLastPathComponent) {
+        return JNI_FALSE;
+    }
+
+    size_t indexOfAltLastPathComponent = pathLen - sizeOfAltLastPathComponent;
+    if (0 == strncmp(realPathToSelf + indexOfAltLastPathComponent, altLastPathComponent, sizeOfAltLastPathComponent)) {
+        JLI_Snprintf(realPathToSelf + indexOfAltLastPathComponent, sizeOfAltLastPathComponent, "%s", "/Home");
+        if (access(realPathToSelf, F_OK) == 0) {
+            return JNI_TRUE;
+        }
+    }
+
     if (!speculative)
       JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL);
     return JNI_FALSE;
diff --git a/test/jdk/tools/launcher/JliLaunchTest.java b/test/jdk/tools/launcher/JliLaunchTest.java
index 4ab0549b96e..367b3994407 100644
--- a/test/jdk/tools/launcher/JliLaunchTest.java
+++ b/test/jdk/tools/launcher/JliLaunchTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2020, 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
@@ -24,7 +24,7 @@
 
 /**
  * @test
- * @bug 8213362
+ * @bug 8213362 8238225
  * @comment Test JLI_Launch for tools distributed outside JDK
  * @library /test/lib
  * @run main/native JliLaunchTest
@@ -56,6 +56,26 @@ public class JliLaunchTest {
 
         OutputAnalyzer outputf = new OutputAnalyzer(pb.start());
         outputf.shouldHaveExitValue(0);
+
+        if (Platform.isOSX()) {
+            Path javaHome = Paths.get(Utils.TEST_JDK);
+            if (javaHome.getFileName().toString().equals("Home")) {
+                // To exercise this test path you need to make sure the JDK under test is
+                // the MacOS bundle and not the simple jdk image. This can currently be
+                // achieved by running something like this (from the build output dir):
+                // $ make test-only TEST=test/jdk/tools/launcher/JliLaunchTest.java \
+                //     JDK_IMAGE_DIR=$PWD/images/jdk-bundle/jdk-15.jdk/Contents/Home
+                System.out.println("MacOS bundle distribution detected, also testing Contents/MacOS/libjli.dylib");
+                String macosDir = javaHome.getParent().resolve("MacOS").toString();
+                ProcessBuilder pb2 = new ProcessBuilder(launcher.toString(), "--version");
+                env = pb2.environment();
+                env.compute(pathEnvVar, (k, v) -> (v == null) ? macosDir : macosDir + File.pathSeparator + v);
+
+                OutputAnalyzer output2 = new OutputAnalyzer(pb2.start());
+                output2.shouldHaveExitValue(0);
+            } else {
+                System.out.println("Not a MacOS bundle distribution, not testing Contents/MacOS/libjli.dylib");
+            }
+        }
     }
 }
-