mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8243592: Subject$SecureSet::addAll should not call contains(null)
Reviewed-by: mullan
This commit is contained in:
parent
e2353cc324
commit
fc1b24e4e8
2 changed files with 99 additions and 42 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -203,18 +203,20 @@ public final class Subject implements java.io.Serializable {
|
||||||
* Sets.
|
* Sets.
|
||||||
*/
|
*/
|
||||||
public Subject(boolean readOnly, Set<? extends Principal> principals,
|
public Subject(boolean readOnly, Set<? extends Principal> principals,
|
||||||
Set<?> pubCredentials, Set<?> privCredentials)
|
Set<?> pubCredentials, Set<?> privCredentials) {
|
||||||
{
|
LinkedList<Principal> principalList
|
||||||
collectionNullClean(principals);
|
= collectionNullClean(principals);
|
||||||
collectionNullClean(pubCredentials);
|
LinkedList<Object> pubCredsList
|
||||||
collectionNullClean(privCredentials);
|
= collectionNullClean(pubCredentials);
|
||||||
|
LinkedList<Object> privCredsList
|
||||||
|
= collectionNullClean(privCredentials);
|
||||||
|
|
||||||
this.principals = Collections.synchronizedSet(new SecureSet<>
|
this.principals = Collections.synchronizedSet(
|
||||||
(this, PRINCIPAL_SET, principals));
|
new SecureSet<>(this, PRINCIPAL_SET, principalList));
|
||||||
this.pubCredentials = Collections.synchronizedSet(new SecureSet<>
|
this.pubCredentials = Collections.synchronizedSet(
|
||||||
(this, PUB_CREDENTIAL_SET, pubCredentials));
|
new SecureSet<>(this, PUB_CREDENTIAL_SET, pubCredsList));
|
||||||
this.privCredentials = Collections.synchronizedSet(new SecureSet<>
|
this.privCredentials = Collections.synchronizedSet(
|
||||||
(this, PRIV_CREDENTIAL_SET, privCredentials));
|
new SecureSet<>(this, PRIV_CREDENTIAL_SET, privCredsList));
|
||||||
this.readOnly = readOnly;
|
this.readOnly = readOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -975,8 +977,9 @@ public final class Subject implements java.io.Serializable {
|
||||||
|
|
||||||
// Rewrap the principals into a SecureSet
|
// Rewrap the principals into a SecureSet
|
||||||
try {
|
try {
|
||||||
|
LinkedList<Principal> principalList = collectionNullClean(inputPrincs);
|
||||||
principals = Collections.synchronizedSet(new SecureSet<>
|
principals = Collections.synchronizedSet(new SecureSet<>
|
||||||
(this, PRINCIPAL_SET, inputPrincs));
|
(this, PRINCIPAL_SET, principalList));
|
||||||
} catch (NullPointerException npe) {
|
} catch (NullPointerException npe) {
|
||||||
// Sometimes people deserialize the principals set only.
|
// Sometimes people deserialize the principals set only.
|
||||||
// Subject is not accessible, so just don't fail.
|
// Subject is not accessible, so just don't fail.
|
||||||
|
@ -1001,26 +1004,18 @@ public final class Subject implements java.io.Serializable {
|
||||||
* @throws NullPointerException if the specified collection is either
|
* @throws NullPointerException if the specified collection is either
|
||||||
* {@code null} or contains a {@code null} element
|
* {@code null} or contains a {@code null} element
|
||||||
*/
|
*/
|
||||||
private static void collectionNullClean(Collection<?> coll) {
|
private static <E> LinkedList<E> collectionNullClean(
|
||||||
boolean hasNullElements = false;
|
Collection<? extends E> coll) {
|
||||||
|
|
||||||
Objects.requireNonNull(coll,
|
Objects.requireNonNull(coll,
|
||||||
ResourcesMgr.getString("invalid.null.input.s."));
|
ResourcesMgr.getString("invalid.null.input.s."));
|
||||||
|
|
||||||
try {
|
LinkedList<E> output = new LinkedList<>();
|
||||||
hasNullElements = coll.contains(null);
|
for (E e : coll) {
|
||||||
} catch (NullPointerException npe) {
|
output.add(Objects.requireNonNull(e,
|
||||||
// A null-hostile collection may choose to throw
|
ResourcesMgr.getString("invalid.null.input.s.")));
|
||||||
// NullPointerException if contains(null) is called on it
|
|
||||||
// rather than returning false.
|
|
||||||
// If this happens we know the collection is null-clean.
|
|
||||||
hasNullElements = false;
|
|
||||||
} finally {
|
|
||||||
if (hasNullElements) {
|
|
||||||
throw new NullPointerException
|
|
||||||
(ResourcesMgr.getString("invalid.null.input.s."));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1066,10 +1061,10 @@ public final class Subject implements java.io.Serializable {
|
||||||
this.elements = new LinkedList<E>();
|
this.elements = new LinkedList<E>();
|
||||||
}
|
}
|
||||||
|
|
||||||
SecureSet(Subject subject, int which, Set<? extends E> set) {
|
SecureSet(Subject subject, int which, LinkedList<E> list) {
|
||||||
this.subject = subject;
|
this.subject = subject;
|
||||||
this.which = which;
|
this.which = which;
|
||||||
this.elements = new LinkedList<E>(set);
|
this.elements = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size() {
|
public int size() {
|
||||||
|
@ -1242,7 +1237,7 @@ public final class Subject implements java.io.Serializable {
|
||||||
public boolean addAll(Collection<? extends E> c) {
|
public boolean addAll(Collection<? extends E> c) {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
|
|
||||||
collectionNullClean(c);
|
c = collectionNullClean(c);
|
||||||
|
|
||||||
for (E item : c) {
|
for (E item : c) {
|
||||||
result |= this.add(item);
|
result |= this.add(item);
|
||||||
|
@ -1252,7 +1247,7 @@ public final class Subject implements java.io.Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean removeAll(Collection<?> c) {
|
public boolean removeAll(Collection<?> c) {
|
||||||
collectionNullClean(c);
|
c = collectionNullClean(c);
|
||||||
|
|
||||||
boolean modified = false;
|
boolean modified = false;
|
||||||
final Iterator<E> e = iterator();
|
final Iterator<E> e = iterator();
|
||||||
|
@ -1282,7 +1277,7 @@ public final class Subject implements java.io.Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsAll(Collection<?> c) {
|
public boolean containsAll(Collection<?> c) {
|
||||||
collectionNullClean(c);
|
c = collectionNullClean(c);
|
||||||
|
|
||||||
for (Object item : c) {
|
for (Object item : c) {
|
||||||
if (this.contains(item) == false) {
|
if (this.contains(item) == false) {
|
||||||
|
@ -1294,7 +1289,7 @@ public final class Subject implements java.io.Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean retainAll(Collection<?> c) {
|
public boolean retainAll(Collection<?> c) {
|
||||||
collectionNullClean(c);
|
c = collectionNullClean(c);
|
||||||
|
|
||||||
boolean modified = false;
|
boolean modified = false;
|
||||||
final Iterator<E> e = iterator();
|
final Iterator<E> e = iterator();
|
||||||
|
@ -1443,13 +1438,7 @@ public final class Subject implements java.io.Serializable {
|
||||||
|
|
||||||
LinkedList<E> tmp = (LinkedList<E>) fields.get("elements", null);
|
LinkedList<E> tmp = (LinkedList<E>) fields.get("elements", null);
|
||||||
|
|
||||||
Subject.collectionNullClean(tmp);
|
elements = Subject.collectionNullClean(tmp);
|
||||||
|
|
||||||
if (tmp.getClass() != LinkedList.class) {
|
|
||||||
elements = new LinkedList<E>(tmp);
|
|
||||||
} else {
|
|
||||||
elements = tmp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
68
test/jdk/javax/security/auth/Subject/UnreliableContains.java
Normal file
68
test/jdk/javax/security/auth/Subject/UnreliableContains.java
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 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
|
||||||
|
* 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 8243592
|
||||||
|
* @summary Subject$SecureSet::addAll should not call contains(null)
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javax.security.auth.Subject;
|
||||||
|
import java.security.Principal;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class UnreliableContains {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
MySet<Principal> set = new MySet<>();
|
||||||
|
set.add(null);
|
||||||
|
Subject s = null;
|
||||||
|
try {
|
||||||
|
s = new Subject(false, set, Collections.emptySet(),
|
||||||
|
Collections.emptySet());
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
// The correct exit
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Suppose NPE was not caught. At least null was not added?
|
||||||
|
for (Principal p : s.getPrincipals()) {
|
||||||
|
Objects.requireNonNull(p);
|
||||||
|
}
|
||||||
|
// Still must fail. We don't want this Subject created
|
||||||
|
throw new RuntimeException("Fail");
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a Map that implements contains(null) differently
|
||||||
|
static class MySet<E> extends HashSet<E> {
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
if (o == null) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return super.contains(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue