diff options
author | Thomas Watson | 2017-07-27 17:30:07 +0000 |
---|---|---|
committer | Thomas Watson | 2017-08-11 13:23:07 +0000 |
commit | 2c8c788dacedb082584bd9854bed71dd7d6bcac0 (patch) | |
tree | 6dbc16351f31a6940763541d3f65096f119e144a | |
parent | 6a31629a6dfa73f19b646f7f98e65749aabd8810 (diff) | |
download | rt.equinox.framework-2c8c788dacedb082584bd9854bed71dd7d6bcac0.tar.gz rt.equinox.framework-2c8c788dacedb082584bd9854bed71dd7d6bcac0.tar.xz rt.equinox.framework-2c8c788dacedb082584bd9854bed71dd7d6bcac0.zip |
Bug 520281 - NPE possible if null values are used to match against a
filter
Change-Id: Id7faf62585006ff6b3350e07de214d611267db75
Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
9 files changed, 135 insertions, 32 deletions
diff --git a/bundles/org.eclipse.osgi.tests/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi.tests/META-INF/MANIFEST.MF index 9fc3c16dd..659cdd24f 100644 --- a/bundles/org.eclipse.osgi.tests/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.osgi.tests/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Core OSGi Tests Bundle-SymbolicName: org.eclipse.osgi.tests;singleton:=true -Bundle-Version: 3.12.0.qualifier +Bundle-Version: 3.12.1.qualifier Bundle-Vendor: Eclipse.org Bundle-Localization: plugin Require-Bundle: diff --git a/bundles/org.eclipse.osgi.tests/pom.xml b/bundles/org.eclipse.osgi.tests/pom.xml index f9d6d9387..5d57bec5a 100644 --- a/bundles/org.eclipse.osgi.tests/pom.xml +++ b/bundles/org.eclipse.osgi.tests/pom.xml @@ -19,7 +19,7 @@ </parent> <groupId>org.eclipse.osgi</groupId> <artifactId>org.eclipse.osgi.tests</artifactId> - <version>3.12.0-SNAPSHOT</version> + <version>3.12.1-SNAPSHOT</version> <packaging>eclipse-test-plugin</packaging> <properties> diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/filter/FilterTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/filter/FilterTests.java index 95d4d5687..62dc32e7c 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/filter/FilterTests.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/filter/FilterTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2015 IBM Corporation and others. + * Copyright (c) 2008, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -14,6 +14,7 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; import junit.framework.*; +import org.eclipse.osgi.tests.util.MapDictionary; import org.osgi.framework.*; public abstract class FilterTests extends TestCase { @@ -343,6 +344,21 @@ public abstract class FilterTests extends TestCase { assertFalse("does match filter", f1.match(new DictionaryServiceReference(hash))); } + public void testNullValueMatch() throws InvalidSyntaxException { + Dictionary<String, Object> nullProps = new MapDictionary<String, Object>(); + nullProps.put("test.null", null); + nullProps.put("test.non.null", "v1"); + assertFalse(createFilter("(test.null=*)").match(nullProps)); + assertTrue(createFilter("(&(!(test.null=*))(test.non.null=v1))").match(nullProps)); + } + + public void testNullKeyMatch() throws InvalidSyntaxException { + Dictionary<String, Object> nullProps = new MapDictionary<String, Object>(); + nullProps.put(null, "null.v1"); + nullProps.put("test.non.null", "v1"); + assertTrue(createFilter("(test.non.null=v1)").match(nullProps)); + } + public static class SampleComparable implements Comparable { private int value = -1; diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/serviceregistry/ServiceRegistryTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/serviceregistry/ServiceRegistryTests.java index 5de8e206b..81e2af168 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/serviceregistry/ServiceRegistryTests.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/serviceregistry/ServiceRegistryTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2014 IBM Corporation and others. + * Copyright (c) 2008, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.osgi.tests.serviceregistry; +import java.util.Dictionary; import java.util.Hashtable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -17,6 +18,7 @@ import junit.framework.Test; import junit.framework.TestSuite; import org.eclipse.osgi.tests.OSGiTestsActivator; import org.eclipse.osgi.tests.bundles.AbstractBundleTests; +import org.eclipse.osgi.tests.util.MapDictionary; import org.osgi.framework.*; public class ServiceRegistryTests extends AbstractBundleTests { @@ -523,6 +525,35 @@ public class ServiceRegistryTests extends AbstractBundleTests { } + public void testNullValue() throws InvalidSyntaxException { + ServiceRegistration reg = null; + try { + Dictionary<String, Object> nullProps = new MapDictionary<String, Object>(); + nullProps.put("test.null", null); + nullProps.put("test.non.null", "v1"); + reg = OSGiTestsActivator.getContext().registerService(Object.class, new Object(), nullProps); + assertFalse(OSGiTestsActivator.getContext().createFilter("(test.null=*)").match(reg.getReference())); + assertTrue(OSGiTestsActivator.getContext().createFilter("(&(!(test.null=*))(test.non.null=v1))").match(reg.getReference())); + } finally { + if (reg != null) + reg.unregister(); + } + } + + public void testNullKey() throws InvalidSyntaxException { + ServiceRegistration reg = null; + try { + Dictionary<String, Object> nullProps = new MapDictionary<String, Object>(); + nullProps.put(null, "null.v1"); + nullProps.put("test.non.null", "v1"); + reg = OSGiTestsActivator.getContext().registerService(Object.class, new Object(), nullProps); + assertTrue(OSGiTestsActivator.getContext().createFilter("(test.non.null=v1)").match(reg.getReference())); + } finally { + if (reg != null) + reg.unregister(); + } + } + private void clearResults(boolean[] results) { for (int i = 0; i < results.length; i++) results[i] = false; diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/util/MapDictionary.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/util/MapDictionary.java new file mode 100644 index 000000000..d3afdb187 --- /dev/null +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/util/MapDictionary.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ +package org.eclipse.osgi.tests.util; + +import java.util.*; + +public class MapDictionary<K, V> extends Dictionary<K, V> { + Map<K, V> map = new HashMap<K, V>(); + + @Override + public int size() { + return map.size(); + } + + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + + @Override + public Enumeration<K> keys() { + return Collections.enumeration(map.keySet()); + } + + @Override + public Enumeration<V> elements() { + return Collections.enumeration(map.values()); + } + + @Override + public V get(Object key) { + return map.get(key); + } + + @Override + public V put(K key, V value) { + return map.put(key, value); + } + + @Override + public V remove(Object key) { + return map.remove(key); + } + +} diff --git a/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF index 0f7985ae0..0978188c2 100644 --- a/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF @@ -103,7 +103,7 @@ Bundle-Activator: org.eclipse.osgi.internal.framework.SystemBundleActivator Bundle-Description: %systemBundle Bundle-Copyright: %copyright Bundle-Vendor: %eclipse.org -Bundle-Version: 3.12.0.qualifier +Bundle-Version: 3.12.1.qualifier Bundle-Localization: systembundle Bundle-DocUrl: http://www.eclipse.org Eclipse-ExtensibleAPI: true diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/CaseInsensitiveDictionaryMap.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/CaseInsensitiveDictionaryMap.java index 545cc9008..a4700be3e 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/CaseInsensitiveDictionaryMap.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/CaseInsensitiveDictionaryMap.java @@ -59,8 +59,15 @@ public class CaseInsensitiveDictionaryMap<K, V> extends Dictionary<K, V> impleme Enumeration<? extends K> keys = dictionary.keys(); while (keys.hasMoreElements()) { K key = keys.nextElement(); - if (put(key, dictionary.get(key)) != null) { - throw new IllegalArgumentException(NLS.bind(Msg.HEADER_DUPLICATE_KEY_EXCEPTION, key)); + // ignore null keys + if (key != null) { + V value = dictionary.get(key); + // ignore null values + if (value != null) { + if (put(key, value) != null) { + throw new IllegalArgumentException(NLS.bind(Msg.HEADER_DUPLICATE_KEY_EXCEPTION, key)); + } + } } } } @@ -76,8 +83,16 @@ public class CaseInsensitiveDictionaryMap<K, V> extends Dictionary<K, V> impleme this(initialCapacity(map.size())); /* initialize the keys and values */ for (Entry<? extends K, ? extends V> e : map.entrySet()) { - if (put(e.getKey(), e.getValue()) != null) { - throw new IllegalArgumentException(NLS.bind(Msg.HEADER_DUPLICATE_KEY_EXCEPTION, e.getKey())); + K key = e.getKey(); + // ignore null keys + if (key != null) { + V value = e.getValue(); + // ignore null values + if (value != null) { + if (put(key, value) != null) { + throw new IllegalArgumentException(NLS.bind(Msg.HEADER_DUPLICATE_KEY_EXCEPTION, key)); + } + } } } } @@ -112,13 +127,11 @@ public class CaseInsensitiveDictionaryMap<K, V> extends Dictionary<K, V> impleme /** * {@inheritDoc} * <p> - * The key must be non-null. - * <p> * If the key is a String, the key is located in a case-insensitive manner. */ @Override public V get(Object key) { - return map.get(keyWrap(requireNonNull(key))); + return map.get(keyWrap(key)); } /** @@ -173,13 +186,11 @@ public class CaseInsensitiveDictionaryMap<K, V> extends Dictionary<K, V> impleme /** * {@inheritDoc} * <p> - * The key must be non-null. - * <p> * If the key is a String, the key is removed in a case-insensitive manner. */ @Override public V remove(Object key) { - return map.remove(keyWrap(requireNonNull(key))); + return map.remove(keyWrap(key)); } /** @@ -201,23 +212,19 @@ public class CaseInsensitiveDictionaryMap<K, V> extends Dictionary<K, V> impleme /** * {@inheritDoc} * <p> - * The key must be non-null. - * <p> * If the key is a String, the key is located in a case-insensitive manner. */ @Override public boolean containsKey(Object key) { - return map.containsKey(keyWrap(requireNonNull(key))); + return map.containsKey(keyWrap(key)); } /** * {@inheritDoc} - * <p> - * The value must be non-null. */ @Override public boolean containsValue(Object value) { - return map.containsValue(requireNonNull(value)); + return map.containsValue(value); } private transient Set<Entry<K, V>> entrySet = null; @@ -556,7 +563,7 @@ public class CaseInsensitiveDictionaryMap<K, V> extends Dictionary<K, V> impleme @Override public int hashCode() { - return entry.getKey().hashCode() ^ entry.getValue().hashCode(); + return Objects.hashCode(entry.getKey()) ^ Objects.hashCode(entry.getValue()); } @Override @@ -566,13 +573,7 @@ public class CaseInsensitiveDictionaryMap<K, V> extends Dictionary<K, V> impleme Object k1 = entry.getKey(); @SuppressWarnings("unchecked") Object k2 = (other instanceof CaseInsentiveEntry) ? ((CaseInsentiveEntry<K, V>) other).entry.getKey() : other.getKey(); - if ((k1 == k2) || k1.equals(k2)) { - Object v1 = entry.getValue(); - Object v2 = other.getValue(); - if ((v1 == v2) || v1.equals(v2)) { - return true; - } - } + return Objects.equals(k1, k2) && Objects.equals(entry.getValue(), other.getValue()); } return false; } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java index b875b6cf3..b6646d431 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java @@ -54,7 +54,8 @@ class ServiceProperties extends CaseInsensitiveDictionaryMap<String, Object> { Object key = keysEnum.nextElement(); if (key instanceof String) { String header = (String) key; - if (put(header, cloneValue(props.get(header))) != null) { + Object value = cloneValue(props.get(header)); + if (value != null && put(header, value) != null) { throw new IllegalArgumentException(NLS.bind(Msg.HEADER_DUPLICATE_KEY_EXCEPTION, key)); } } @@ -79,7 +80,8 @@ class ServiceProperties extends CaseInsensitiveDictionaryMap<String, Object> { Object key = e.getKey(); if (key instanceof String) { String header = (String) key; - if (put(header, cloneValue(e.getValue())) != null) { + Object value = cloneValue(props.get(header)); + if (value != null && put(header, value) != null) { throw new IllegalArgumentException(NLS.bind(Msg.HEADER_DUPLICATE_KEY_EXCEPTION, key)); } } diff --git a/bundles/org.eclipse.osgi/pom.xml b/bundles/org.eclipse.osgi/pom.xml index 9e6a5f6c6..228ba6028 100644 --- a/bundles/org.eclipse.osgi/pom.xml +++ b/bundles/org.eclipse.osgi/pom.xml @@ -19,7 +19,7 @@ </parent> <groupId>org.eclipse.osgi</groupId> <artifactId>org.eclipse.osgi</artifactId> - <version>3.12.0-SNAPSHOT</version> + <version>3.12.1-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> <build> |