8194251: Deadlock between UsageTracker and System.getProperty() when using a malformed security policy

Disable localization of error messages produced during policy file parsing

Reviewed-by: mchung, mullan
This commit is contained in:
Adam Petcher 2018-02-07 09:06:43 -05:00
parent 999168d66b
commit 683817de43
6 changed files with 126 additions and 64 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2018, 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
@ -580,8 +580,8 @@ public class PolicyFile extends java.security.Policy {
k.add(policy);
return k;
});
Object[] source = {policy, pe.getLocalizedMessage()};
System.err.println(LocalizedMessage.getMessage
Object[] source = {policy, pe.getNonlocalizedMessage()};
System.err.println(LocalizedMessage.getNonlocalized
(POLICY + ".error.parsing.policy.message", source));
if (debug != null) {
pe.printStackTrace();
@ -808,14 +808,14 @@ public class PolicyFile extends java.security.Policy {
Object[] source = {pe.permission,
ite.getTargetException().toString()};
System.err.println(
LocalizedMessage.getMessage(
LocalizedMessage.getNonlocalized(
POLICY + ".error.adding.Permission.perm.message",
source));
} catch (Exception e) {
Object[] source = {pe.permission,
e.toString()};
System.err.println(
LocalizedMessage.getMessage(
LocalizedMessage.getNonlocalized(
POLICY + ".error.adding.Permission.perm.message",
source));
}
@ -826,7 +826,7 @@ public class PolicyFile extends java.security.Policy {
} catch (Exception e) {
Object[] source = {e.toString()};
System.err.println(
LocalizedMessage.getMessage(
LocalizedMessage.getNonlocalized(
POLICY + ".error.adding.Entry.message",
source));
}
@ -1803,7 +1803,7 @@ public class PolicyFile extends java.security.Policy {
if (colonIndex == -1) {
Object[] source = {pe.name};
throw new Exception(
LocalizedMessage.getMessage(
LocalizedMessage.getNonlocalized(
"alias.name.not.provided.pe.name.",
source));
}
@ -1811,7 +1811,7 @@ public class PolicyFile extends java.security.Policy {
if ((suffix = getDN(suffix, keystore)) == null) {
Object[] source = {value.substring(colonIndex+1)};
throw new Exception(
LocalizedMessage.getMessage(
LocalizedMessage.getNonlocalized(
"unable.to.perform.substitution.on.alias.suffix",
source));
}
@ -1821,7 +1821,7 @@ public class PolicyFile extends java.security.Policy {
} else {
Object[] source = {prefix};
throw new Exception(
LocalizedMessage.getMessage(
LocalizedMessage.getNonlocalized(
"substitution.value.prefix.unsupported",
source));
}
@ -2037,7 +2037,7 @@ public class PolicyFile extends java.security.Policy {
super(type);
if (type == null) {
throw new NullPointerException
(LocalizedMessage.getMessage("type.can.t.be.null"));
(LocalizedMessage.getNonlocalized("type.can.t.be.null"));
}
this.type = type;
this.name = name;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2018, 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
@ -205,8 +205,8 @@ public class PolicyParser {
if (!domainEntries.containsKey(domainName)) {
domainEntries.put(domainName, de);
} else {
LocalizedMessage localizedMsg =
new LocalizedMessage("duplicate.keystore.domain.name");
LocalizedMessage localizedMsg = new LocalizedMessage(
"duplicate.keystore.domain.name");
Object[] source = {domainName};
String msg = "duplicate keystore domain name: " +
domainName;
@ -220,7 +220,7 @@ public class PolicyParser {
}
if (keyStoreUrlString == null && storePassURL != null) {
throw new ParsingException(LocalizedMessage.getMessage
throw new ParsingException(LocalizedMessage.getNonlocalized
("keystorePasswordURL.can.not.be.specified.without.also.specifying.keystore"));
}
}
@ -362,7 +362,7 @@ public class PolicyParser {
keyStoreType = match("quoted string");
} else {
throw new ParsingException(st.lineno(),
LocalizedMessage.getMessage("expected.keystore.type"));
LocalizedMessage.getNonlocalized("expected.keystore.type"));
}
// parse keystore provider
@ -375,7 +375,7 @@ public class PolicyParser {
keyStoreProvider = match("quoted string");
} else {
throw new ParsingException(st.lineno(),
LocalizedMessage.getMessage("expected.keystore.provider"));
LocalizedMessage.getNonlocalized("expected.keystore.provider"));
}
}
@ -425,7 +425,7 @@ public class PolicyParser {
if (e.codeBase != null)
throw new ParsingException(
st.lineno(),
LocalizedMessage.getMessage
LocalizedMessage.getNonlocalized
("multiple.Codebase.expressions"));
e.codeBase = match("quoted string");
peekAndMatch(",");
@ -433,7 +433,7 @@ public class PolicyParser {
if (e.signedBy != null)
throw new ParsingException(
st.lineno(),
LocalizedMessage.getMessage
LocalizedMessage.getNonlocalized
("multiple.SignedBy.expressions"));
e.signedBy = match("quoted string");
@ -452,7 +452,7 @@ public class PolicyParser {
if (actr <= cctr)
throw new ParsingException(
st.lineno(),
LocalizedMessage.getMessage
LocalizedMessage.getNonlocalized
("SignedBy.has.empty.alias"));
peekAndMatch(",");
@ -495,7 +495,7 @@ public class PolicyParser {
}
throw new ParsingException
(st.lineno(),
LocalizedMessage.getMessage
LocalizedMessage.getNonlocalized
("can.not.specify.Principal.with.a.wildcard.class.without.a.wildcard.name"));
}
}
@ -532,7 +532,7 @@ public class PolicyParser {
} else {
throw new ParsingException(st.lineno(),
LocalizedMessage.getMessage
LocalizedMessage.getNonlocalized
("expected.codeBase.or.SignedBy.or.Principal"));
}
}
@ -556,7 +556,7 @@ public class PolicyParser {
} else {
throw new
ParsingException(st.lineno(),
LocalizedMessage.getMessage
LocalizedMessage.getNonlocalized
("expected.permission.entry"));
}
}
@ -733,7 +733,7 @@ public class PolicyParser {
switch (lookahead) {
case StreamTokenizer.TT_NUMBER:
throw new ParsingException(st.lineno(), expect,
LocalizedMessage.getMessage("number.") +
LocalizedMessage.getNonlocalized("number.") +
String.valueOf(st.nval));
case StreamTokenizer.TT_EOF:
LocalizedMessage localizedMsg = new LocalizedMessage
@ -826,10 +826,10 @@ public class PolicyParser {
switch (lookahead) {
case StreamTokenizer.TT_NUMBER:
throw new ParsingException(st.lineno(), ";",
LocalizedMessage.getMessage("number.") +
LocalizedMessage.getNonlocalized("number.") +
String.valueOf(st.nval));
case StreamTokenizer.TT_EOF:
throw new ParsingException(LocalizedMessage.getMessage
throw new ParsingException(LocalizedMessage.getNonlocalized
("expected.read.end.of.file."));
default:
lookahead = st.nextToken();
@ -987,7 +987,7 @@ public class PolicyParser {
*/
public PrincipalEntry(String principalClass, String principalName) {
if (principalClass == null || principalName == null)
throw new NullPointerException(LocalizedMessage.getMessage
throw new NullPointerException(LocalizedMessage.getNonlocalized
("null.principalClass.or.principalName"));
this.principalClass = principalClass;
this.principalName = principalName;
@ -1339,8 +1339,6 @@ public class PolicyParser {
public ParsingException(int line, String msg) {
super("line " + line + ": " + msg);
// don't call form.format unless getLocalizedMessage is called
// to avoid unnecessary permission checks
localizedMsg = new LocalizedMessage("line.number.msg");
source = new Object[] {line, msg};
}
@ -1348,16 +1346,14 @@ public class PolicyParser {
public ParsingException(int line, String expect, String actual) {
super("line " + line + ": expected [" + expect +
"], found [" + actual + "]");
// don't call form.format unless getLocalizedMessage is called
// to avoid unnecessary permission checks
localizedMsg = new LocalizedMessage
("line.number.expected.expect.found.actual.");
source = new Object[] {line, expect, actual};
}
@Override
public String getLocalizedMessage() {
return i18nMessage != null ? i18nMessage : localizedMsg.format(source);
public String getNonlocalizedMessage() {
return i18nMessage != null ? i18nMessage :
localizedMsg.formatNonlocalized(source);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, 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
@ -42,7 +42,7 @@ package sun.security.util;
public class LocalizedMessage {
private static final Resources resources = new Resources();
private static final Resources RESOURCES = new Resources();
private final String key;
@ -59,16 +59,28 @@ public class LocalizedMessage {
/**
* Return a localized string corresponding to the key stored in this
* object, formatted with the provided arguments. When the VM is booted,
* this method will obtain the correct localized message and format it
* using java.text.MessageFormat. Otherwise, a non-localized string is
* returned, and the formatting is performed by simplified formatting code.
* object, formatted with the provided arguments. This method should only
* be called when the VM is booted and all resources needed to obtain
* and format the localized message are loaded (or can be loaded).
*
* @param arguments The arguments that should be placed in the message
* @return A formatted message string
*/
public String format(Object... arguments) {
return getMessage(key, arguments);
public String formatLocalized(Object... arguments) {
return getLocalized(key, arguments);
}
/**
* Return a non-localized string corresponding to the key stored in this
* object, formatted with the provided arguments. All strings are obtained
* from sun.security.util.Resources, and the formatting only supports
* simple positional argument replacement (e.g. {1}).
*
* @param arguments The arguments that should be placed in the message
* @return A formatted message string
*/
public String formatNonlocalized(Object... arguments) {
return getNonlocalized(key, arguments);
}
/**
@ -81,10 +93,10 @@ public class LocalizedMessage {
* @param arguments The arguments that should be placed in the message
* @return A formatted message string
*/
public static String getMessageUnbooted(String key,
Object... arguments) {
public static String getNonlocalized(String key,
Object... arguments) {
String value = resources.getString(key);
String value = RESOURCES.getString(key);
if (arguments == null || arguments.length == 0) {
return value;
}
@ -110,8 +122,7 @@ public class LocalizedMessage {
try {
int index = Integer.parseInt(indexStr);
sb.append(arguments[index]);
}
catch(NumberFormatException e) {
} catch (NumberFormatException e) {
// argument index is not an integer
throw new RuntimeException("not an integer: " + indexStr);
}
@ -123,29 +134,22 @@ public class LocalizedMessage {
/**
* Return a localized string corresponding to the provided key, and
* formatted with the provided arguments. When the VM is booted, this
* method will obtain the correct localized message and format it using
* java.text.MessageFormat. Otherwise, a non-localized string is returned,
* and the formatting is performed by simplified formatting code.
* formatted with the provided arguments. This method should only be
* called when the VM is booted and all resources needed to obtain
* and format the localized message are loaded (or can be loaded).
*
* @param key The key of the desired string in the security resource bundle
* @param arguments The arguments that should be placed in the message
* @return A formatted message string
*/
public static String getMessage(String key,
Object... arguments) {
public static String getLocalized(String key, Object... arguments) {
if (jdk.internal.misc.VM.isBooted()) {
// Localization and formatting resources are available
String value = ResourcesMgr.getString(key);
if (arguments == null) {
return value;
}
java.text.MessageFormat form = new java.text.MessageFormat(value);
return form.format(arguments);
} else {
return getMessageUnbooted(key, arguments);
String value = ResourcesMgr.getString(key);
if (arguments == null) {
return value;
}
java.text.MessageFormat form = new java.text.MessageFormat(value);
return form.format(arguments);
}
}