8234185: Cleanup usage of canonicalize function between libjava, hotspot and libinstrument

Reviewed-by: dholmes, alanb, sspitsyn
This commit is contained in:
Christoph Langer 2019-12-06 14:13:10 +01:00
parent b8dbdd1232
commit 547e472c42
9 changed files with 54 additions and 81 deletions

View File

@ -75,6 +75,8 @@
// Entry point in java.dll for path canonicalization
typedef int (*canonicalize_fn_t)(const char *orig, char *out, int len);
static canonicalize_fn_t CanonicalizeEntry = NULL;
// Entry points in zip.dll for loading zip/jar file entries
@ -980,7 +982,7 @@ void ClassLoader::load_java_library() {
vm_exit_during_initialization("Unable to load java library", NULL);
}
CanonicalizeEntry = CAST_TO_FN_PTR(canonicalize_fn_t, dll_lookup(javalib_handle, "Canonicalize", NULL));
CanonicalizeEntry = CAST_TO_FN_PTR(canonicalize_fn_t, dll_lookup(javalib_handle, "JDK_Canonicalize", NULL));
}
void ClassLoader::load_zip_library() {
@ -1643,13 +1645,12 @@ void ClassLoader::classLoader_init2(TRAPS) {
bool ClassLoader::get_canonical_path(const char* orig, char* out, int len) {
assert(orig != NULL && out != NULL && len > 0, "bad arguments");
JavaThread* THREAD = JavaThread::current();
JNIEnv* env = THREAD->jni_environment();
ResourceMark rm(THREAD);
// os::native_path writes into orig_copy
char* orig_copy = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, strlen(orig)+1);
strcpy(orig_copy, orig);
if ((CanonicalizeEntry)(env, os::native_path(orig_copy), out, len) < 0) {
if ((CanonicalizeEntry)(os::native_path(orig_copy), out, len) < 0) {
return false;
}
return true;

View File

@ -1103,14 +1103,6 @@ typedef struct {
JVM_ACC_STRICT | \
JVM_ACC_SYNTHETIC)
/*
* This is the function defined in libjava.so to perform path
* canonicalization. VM call this function before opening jar files
* to load system classes.
*
*/
typedef int (*canonicalize_fn_t)(JNIEnv *env, char *orig, char *out, int len);
/*************************************************************************
PART 3: I/O and Network Support

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2019, 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
@ -45,6 +45,14 @@ extern "C" {
JNIEXPORT void
JDK_GetVersionInfo0(jdk_version_info* info, size_t info_size);
/*
* Export the platform dependent path canonicalization so that
* the VM can find it when loading system classes.
* This function is also used by the instrumentation agent.
*/
JNIEXPORT int
JDK_Canonicalize(const char *orig, char *out, int len);
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */

View File

@ -934,20 +934,6 @@ JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str)
free((void *)str);
}
/*
* Export the platform dependent path canonicalization so that
* VM can find it when loading system classes.
* This function is also used by the instrumentation agent.
*/
extern int canonicalize(char *path, const char *out, int len);
JNIEXPORT int
Canonicalize(JNIEnv *unused, char *orig, char *out, int len)
{
/* canonicalize an already natived path */
return canonicalize(orig, out, len);
}
JNIEXPORT jclass JNICALL
JNU_ClassString(JNIEnv *env)
{

View File

@ -45,6 +45,7 @@
#include "jni.h"
#include "jni_util.h"
#include "jlong.h"
#include "jdk_util.h"
#include "io_util.h"
#include "io_util_md.h"
#include "java_io_FileSystem.h"
@ -91,8 +92,6 @@ Java_java_io_UnixFileSystem_initIDs(JNIEnv *env, jclass cls)
/* -- Path operations -- */
extern int canonicalize(char *path, const char *out, int len);
JNIEXPORT jstring JNICALL
Java_java_io_UnixFileSystem_canonicalize0(JNIEnv *env, jobject this,
jstring pathname)
@ -101,7 +100,7 @@ Java_java_io_UnixFileSystem_canonicalize0(JNIEnv *env, jobject this,
WITH_PLATFORM_STRING(env, pathname, path) {
char canonicalPath[PATH_MAX];
if (canonicalize((char *)path,
if (JDK_Canonicalize((char *)path,
canonicalPath, PATH_MAX) < 0) {
JNU_ThrowIOExceptionWithLastError(env, "Bad pathname");
} else {

View File

@ -37,6 +37,7 @@
#include <alloca.h>
#endif
#include "jdk_util.h"
/* Note: The comments in this file use the terminology
defined in the java.io.File class */
@ -186,33 +187,32 @@ collapse(char *path)
work, though once that's done we still must collapse any remaining "." and
".." names by hand. */
int
canonicalize(char *original, char *resolved, int len)
JNIEXPORT int
JDK_Canonicalize(const char *orig, char *out, int len)
{
if (len < PATH_MAX) {
errno = EINVAL;
return -1;
}
if (strlen(original) > PATH_MAX) {
if (strlen(orig) > PATH_MAX) {
errno = ENAMETOOLONG;
return -1;
}
/* First try realpath() on the entire path */
if (realpath(original, resolved)) {
if (realpath(orig, out)) {
/* That worked, so return it */
collapse(resolved);
collapse(out);
return 0;
}
else {
} else {
/* Something's bogus in the original path, so remove names from the end
until either some subpath works or we run out of names */
char *p, *end, *r = NULL;
char path[PATH_MAX + 1];
// strlen(original) <= PATH_MAX, see above
strncpy(path, original, PATH_MAX);
// strlen(orig) <= PATH_MAX, see above
strncpy(path, orig, PATH_MAX);
// append null for == case
path[PATH_MAX] = '\0';
end = path + strlen(path);
@ -225,21 +225,19 @@ canonicalize(char *original, char *resolved, int len)
/* Try realpath() on this subpath */
*p = '\0';
r = realpath(path, resolved);
r = realpath(path, out);
*p = (p == end) ? '\0' : '/';
if (r != NULL) {
/* The subpath has a canonical path */
break;
}
else if (errno == ENOENT || errno == ENOTDIR || errno == EACCES) {
} else if (errno == ENOENT || errno == ENOTDIR || errno == EACCES) {
/* If the lookup of a particular subpath fails because the file
does not exist, because it is of the wrong type, or because
access is denied, then remove its last name and try again.
Other I/O problems cause an error return. */
continue;
}
else {
} else {
return -1;
}
}
@ -259,13 +257,11 @@ canonicalize(char *original, char *resolved, int len)
strcpy(r + rn, p);
collapse(r);
return 0;
}
else {
} else {
/* Nothing resolved, so just return the original path */
strcpy(resolved, path);
collapse(resolved);
strcpy(out, path);
collapse(out);
return 0;
}
}
}

View File

@ -37,9 +37,12 @@
#include <windows.h>
#include <winbase.h>
#include <errno.h>
#include "io_util_md.h"
#undef DEBUG_PATH /* Define this to debug path code */
/* We should also include jdk_util.h here, for the prototype of JDK_Canonicalize.
This isn't possible though because canonicalize_md.c is as well used in
different contexts within Oracle.
*/
#include "io_util_md.h"
/* Copy bytes to dst, not going past dend; return dst + number of bytes copied,
or NULL if dend would have been exceeded. If first != '\0', copy that byte
@ -138,10 +141,6 @@ lastErrorReportable()
|| (errval == ERROR_NETWORK_ACCESS_DENIED)) {
return 0;
}
#ifdef DEBUG_PATH
jio_fprintf(stderr, "canonicalize: errval %d\n", errval);
#endif
return 1;
}
@ -326,32 +325,32 @@ wcanonicalizeWithPrefix(WCHAR *canonicalPrefix, WCHAR *pathWithCanonicalPrefix,
}
/* Non-Wide character version of canonicalize.
Converts to whchar and delegates to wcanonicalize. */
int
canonicalize(char* orig_path, char* result, int size) {
Converts to wchar and delegates to wcanonicalize. */
JNIEXPORT int
JDK_Canonicalize(const char *orig, char *out, int len) {
wchar_t* wpath = NULL;
wchar_t* wresult = NULL;
size_t conv;
size_t path_len = strlen(orig_path);
size_t path_len = strlen(orig);
int ret = -1;
if ((wpath = (wchar_t*) malloc(sizeof(wchar_t) * (path_len + 1))) == NULL) {
goto finish;
}
if (mbstowcs_s(&conv, wpath, path_len + 1, orig_path, path_len) != 0) {
if (mbstowcs_s(&conv, wpath, path_len + 1, orig, path_len) != 0) {
goto finish;
}
if ((wresult = (wchar_t*) malloc(sizeof(wchar_t) * size)) == NULL) {
if ((wresult = (wchar_t*) malloc(sizeof(wchar_t) * len)) == NULL) {
goto finish;
}
if (wcanonicalize(wpath, wresult, size) != 0) {
if (wcanonicalize(wpath, wresult, len) != 0) {
goto finish;
}
if (wcstombs_s(&conv, result, (size_t) size, wresult, (size_t) (size - 1)) != 0) {
if (wcstombs_s(&conv, out, (size_t) len, wresult, (size_t) (len - 1)) != 0) {
goto finish;
}
@ -365,15 +364,14 @@ finish:
return ret;
}
/* The appropriate location of getPrefixed() should be io_util_md.c, but
java.lang.instrument package has hardwired canonicalize_md.c into their
dll, to avoid complicate solution such as including io_util_md.c into
that package, as a workaround we put this method here.
/* The appropriate location of getPrefixed() is io_util_md.c, but it is
also used in a non-OpenJDK context within Oracle. There, canonicalize_md.c
is already pulled in and compiled, so to avoid more complicated solutions
we keep this method here.
*/
/* copy \\?\ or \\?\UNC\ to the front of path*/
__declspec(dllexport) WCHAR*
/* copy \\?\ or \\?\UNC\ to the front of path */
JNIEXPORT WCHAR*
getPrefixed(const WCHAR* path, int pathlen) {
WCHAR* pathbuf = (WCHAR*)malloc((pathlen + 10) * sizeof (WCHAR));
if (pathbuf != 0) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2019, 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
@ -38,7 +38,7 @@
*/
WCHAR* pathToNTPath(JNIEnv *env, jstring path, jboolean throwFNFE);
WCHAR* fileToNTPath(JNIEnv *env, jobject file, jfieldID id);
__declspec(dllexport) WCHAR* getPrefixed(const WCHAR* path, int pathlen);
JNIEXPORT WCHAR* getPrefixed(const WCHAR* path, int pathlen);
WCHAR* currentDir(int di);
int currentDirLength(const WCHAR* path, int pathlen);
int handleAvailable(FD fd, jlong *pbytes);

View File

@ -32,6 +32,8 @@
#include "jni.h"
#include "jdk_util.h"
#include "Utilities.h"
#include "JPLISAssert.h"
#include "JPLISAgent.h"
@ -776,14 +778,6 @@ appendClassPath( JPLISAgent* agent,
jplis_assert((void*)res != (void*)NULL); \
}
/**
* Convert a pathname to canonical form.
* This method is exported from libjava.
*/
extern int
Canonicalize(JNIEnv *unused, char *orig, char *out, int len);
/*
* This function takes the value of the Boot-Class-Path attribute,
* splits it into the individual path segments, and then combines it
@ -904,8 +898,7 @@ appendBootClassPath( JPLISAgent* agent,
char* resolved;
if (!haveBasePath) {
/* Use NULL as the JNIEnv since we know that Canonicalize does not use it. */
if (Canonicalize(NULL, (char*)jarfile, canonicalPath, sizeof(canonicalPath)) != 0) {
if (JDK_Canonicalize((char*)jarfile, canonicalPath, sizeof(canonicalPath)) != 0) {
fprintf(stderr, "WARNING: unable to canonicalize %s\n", jarfile);
free(path);
continue;