8300038: Make new version of JNU_GetStringPlatformChars which checks for null characters

Reviewed-by: dfuchs, naoto
This commit is contained in:
Michael McMahon 2023-05-25 14:57:29 +00:00
parent 90e57fd5a9
commit e7edf8d145
9 changed files with 187 additions and 25 deletions
src/java.base
test/jdk/java/net/InetAddress

@ -434,7 +434,7 @@ newString8859_1(JNIEnv *env, const char *str)
}
static const char*
getString8859_1Chars(JNIEnv *env, jstring jstr)
getString8859_1Chars(JNIEnv *env, jstring jstr, jboolean strict)
{
int i;
char *result;
@ -453,6 +453,13 @@ getString8859_1Chars(JNIEnv *env, jstring jstr)
for (i=0; i<len; i++) {
jchar unicode = str[i];
if (strict && unicode == 0) {
(*env)->ReleaseStringCritical(env, jstr, str);
free(result);
JNU_ThrowIllegalArgumentException(env, "NUL character not allowed in platform string");
return 0;
}
if (unicode <= 0x00ff)
result[i] = (char)unicode;
else
@ -502,7 +509,7 @@ newString646_US(JNIEnv *env, const char *str)
}
static const char*
getString646_USChars(JNIEnv *env, jstring jstr)
getString646_USChars(JNIEnv *env, jstring jstr, jboolean strict)
{
int i;
char *result;
@ -521,6 +528,12 @@ getString646_USChars(JNIEnv *env, jstring jstr)
for (i=0; i<len; i++) {
jchar unicode = str[i];
if (strict && unicode == 0) {
(*env)->ReleaseStringCritical(env, jstr, str);
free(result);
JNU_ThrowIllegalArgumentException(env, "NUL character not allowed in platform string");
return 0;
}
if (unicode <= 0x007f )
result[i] = (char)unicode;
else
@ -577,7 +590,7 @@ newStringCp1252(JNIEnv *env, const char *str)
}
static const char*
getStringCp1252Chars(JNIEnv *env, jstring jstr)
getStringCp1252Chars(JNIEnv *env, jstring jstr, jboolean strict)
{
int i;
char *result;
@ -596,6 +609,13 @@ getStringCp1252Chars(JNIEnv *env, jstring jstr)
for (i=0; i<len; i++) {
jchar c = str[i];
if (strict && c == 0) {
(*env)->ReleaseStringCritical(env, jstr, str);
free(result);
JNU_ThrowIllegalArgumentException(env,
"NUL character not allowed in platform string");
return 0;
}
if (c < 256) {
if ((c >= 0x80) && (c <= 0x9f)) {
result[i] = '?';
@ -814,13 +834,22 @@ JNU_NewStringPlatform(JNIEnv *env, const char *str)
return newStringJava(env, str);
}
static const char *
getStringPlatformChars0(JNIEnv *env, jstring jstr, jboolean *isCopy, jboolean);
JNIEXPORT const char *
GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
{
return JNU_GetStringPlatformChars(env, jstr, isCopy);
return getStringPlatformChars0(env, jstr, isCopy, JNI_FALSE);
}
static const char* getStringBytes(JNIEnv *env, jstring jstr) {
JNIEXPORT const char *
GetStringPlatformCharsStrict(JNIEnv *env, jstring jstr, jboolean *isCopy)
{
return getStringPlatformChars0(env, jstr, isCopy, JNI_TRUE);
}
static const char* getStringBytes(JNIEnv *env, jstring jstr, jboolean strict) {
char *result = NULL;
jbyteArray hab = 0;
@ -839,15 +868,25 @@ static const char* getStringBytes(JNIEnv *env, jstring jstr) {
}
(*env)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result);
result[len] = 0; /* NULL-terminate */
if (strict) {
for (int i=0; i<len; i++) {
if (result[i] == 0) {
JNU_ThrowIllegalArgumentException(env,
"NUL character not allowed in platform string");
free(result);
result = 0;
break;
}
}
}
}
(*env)->DeleteLocalRef(env, hab);
}
return result;
}
static const char*
getStringUTF8(JNIEnv *env, jstring jstr)
getStringUTF8(JNIEnv *env, jstring jstr, jboolean strict)
{
int i;
char *result;
@ -858,7 +897,7 @@ getStringUTF8(JNIEnv *env, jstring jstr)
int ri;
jbyte coder = (*env)->GetByteField(env, jstr, String_coder_ID);
if (coder != java_lang_String_LATIN1) {
return getStringBytes(env, jstr);
return getStringBytes(env, jstr, strict);
}
if ((*env)->EnsureLocalCapacity(env, 2) < 0) {
return NULL;
@ -875,6 +914,11 @@ getStringUTF8(JNIEnv *env, jstring jstr)
rlen = len;
// we need two bytes for each latin-1 char above 127 (negative jbytes)
for (i = 0; i < len; i++) {
if (strict && str[i] == 0) {
(*env)->ReleasePrimitiveArrayCritical(env, value, str, 0);
JNU_ThrowIllegalArgumentException(env, "NUL character not allowed in platform string");
return NULL;
}
if (str[i] < 0) {
rlen++;
}
@ -903,24 +947,36 @@ getStringUTF8(JNIEnv *env, jstring jstr)
JNIEXPORT const char * JNICALL
JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
{
return getStringPlatformChars0(env, jstr, isCopy, JNI_FALSE);
}
JNIEXPORT const char * JNICALL
JNU_GetStringPlatformCharsStrict(JNIEnv *env, jstring jstr, jboolean *isCopy)
{
return getStringPlatformChars0(env, jstr, isCopy, JNI_TRUE);
}
static const char *
getStringPlatformChars0(JNIEnv *env, jstring jstr, jboolean *isCopy, jboolean strict)
{
if (isCopy)
*isCopy = JNI_TRUE;
if (fastEncoding == FAST_UTF_8)
return getStringUTF8(env, jstr);
return getStringUTF8(env, jstr, strict);
if (fastEncoding == FAST_8859_1)
return getString8859_1Chars(env, jstr);
return getString8859_1Chars(env, jstr, strict);
if (fastEncoding == FAST_646_US)
return getString646_USChars(env, jstr);
return getString646_USChars(env, jstr, strict);
if (fastEncoding == FAST_CP1252)
return getStringCp1252Chars(env, jstr);
return getStringCp1252Chars(env, jstr, strict);
if (fastEncoding == NO_ENCODING_YET) {
JNU_ThrowInternalError(env, "platform encoding not initialized");
return 0;
} else
return getStringBytes(env, jstr);
return getStringBytes(env, jstr, strict);
}
JNIEXPORT void JNICALL

@ -99,9 +99,28 @@ JNU_ThrowIOExceptionWithMessageAndLastError(JNIEnv *env, const char *message);
JNIEXPORT const char *
GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy);
/* Convert between Java strings and i18n C strings
* Performs additional sanity checks on converted string
* such as presence of null characters which are not allowed.
* NULL may be returned with IllegalArgumentException pending
*/
JNIEXPORT const char *
GetStringPlatformCharsStrict(JNIEnv *env, jstring jstr, jboolean *isCopy);
JNIEXPORT jstring JNICALL
JNU_NewStringPlatform(JNIEnv *env, const char *str);
/* Convert between Java strings and i18n C strings
* Performs additional sanity checks on converted string
* such as presence of null characters which are not allowed.
* NULL may be returned with IllegalArgumentException pending
*/
JNIEXPORT const char * JNICALL
JNU_GetStringPlatformCharsStrict(JNIEnv *env, jstring jstr, jboolean *isCopy);
/* Convert between Java strings and i18n C strings
* Deprecated: Use JNU_GetStringPlatformCharsStrict
*/
JNIEXPORT const char * JNICALL
JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy);

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2023, 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
@ -100,7 +100,7 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
JNU_ThrowNullPointerException(env, "host argument is null");
return NULL;
}
hostname = JNU_GetStringPlatformChars(env, host, NULL);
hostname = JNU_GetStringPlatformCharsStrict(env, host, NULL);
CHECK_NULL_RETURN(hostname, NULL);
// try once, with our static buffer

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2023, 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
@ -219,7 +219,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
JNU_ThrowNullPointerException(env, "host argument is null");
return NULL;
}
hostname = JNU_GetStringPlatformChars(env, host, NULL);
hostname = JNU_GetStringPlatformCharsStrict(env, host, NULL);
CHECK_NULL_RETURN(hostname, NULL);
// try once, with our static buffer

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2023, 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
@ -76,7 +76,7 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
JNU_ThrowNullPointerException(env, "host argument is null");
return NULL;
}
hostname = JNU_GetStringPlatformChars(env, host, NULL);
hostname = JNU_GetStringPlatformCharsStrict(env, host, NULL);
CHECK_NULL_RETURN(hostname, NULL);
// try once, with our static buffer

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2023, 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
@ -71,7 +71,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
JNU_ThrowNullPointerException(env, "host argument is null");
return NULL;
}
hostname = JNU_GetStringPlatformChars(env, host, NULL);
hostname = JNU_GetStringPlatformCharsStrict(env, host, NULL);
CHECK_NULL_RETURN(hostname, NULL);
// try once, with our static buffer

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2023, 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
@ -79,18 +79,18 @@ JNIEXPORT jlong JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_get
SECURITY_STATUS ss = SEC_E_INTERNAL_ERROR;
if (user != 0) {
pUser = JNU_GetStringPlatformChars(env, user, &isCopy);
pUser = JNU_GetStringPlatformCharsStrict(env, user, &isCopy);
if (pUser == NULL)
return 0; // pending Exception
}
if (domain != 0) {
pDomain = JNU_GetStringPlatformChars(env, domain, &isCopy);
pDomain = JNU_GetStringPlatformCharsStrict(env, domain, &isCopy);
if (pDomain == NULL) {
goto cleanup;
}
}
if (password != 0) {
pPassword = JNU_GetStringPlatformChars(env, password, &isCopy);
pPassword = JNU_GetStringPlatformCharsStrict(env, password, &isCopy);
if (pPassword == NULL) {
goto cleanup;
}

@ -0,0 +1,34 @@
/*
* Copyright (c) 2023, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 8300038
* @modules java.base/java.net
* @compile/module=java.base java/net/NullCharInHostname.java
* @summary Make new version of JNU_GetStringPlatformChars which checks for null characters
* @run main/othervm java.base/java.net.NullCharInHostname
* @run main/othervm -Dfile.encoding=COMPAT java.base/java.net.NullCharInHostname
*/
public class NullCharInHostnameDriver { }

@ -0,0 +1,53 @@
/*
* Copyright (c) 2023, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.net;
import java.net.spi.InetAddressResolver.LookupPolicy;
public class NullCharInHostname {
public static void main(String[] args) {
var name = "foo\u0000bar";
System.out.println("file.encoding = " + System.getProperty("file.encoding"));
System.out.println("native.encoding = " + System.getProperty("native.encoding"));
// This should throw IAE as it calls the internal impl
try {
var impl = new Inet6AddressImpl();
var addrs = impl.lookupAllHostAddr(name, LookupPolicy.of(LookupPolicy.IPV4));
} catch (UnknownHostException e0) {
throw new RuntimeException(e0);
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
// This should throw UHE as before and not IAE for compatibility
try {
var addrs = InetAddress.getByName(name);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (UnknownHostException e0) {
e0.printStackTrace();
}
}
}