diff --git a/java/change-notes/2021-06-08-spring-propertyvalues.md b/java/change-notes/2021-06-08-spring-propertyvalues.md new file mode 100644 index 00000000000..3e7ae540109 --- /dev/null +++ b/java/change-notes/2021-06-08-spring-propertyvalues.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added additional taint steps modeling the Spring classes `PropertyValue`, `PropertyValues` and `MutablePropertyValues`. (`org.springframework.beans.*`). diff --git a/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll index 8214c43c84b..f1a17c05723 100644 --- a/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll @@ -87,6 +87,7 @@ private module Frameworks { private import semmle.code.java.frameworks.spring.SpringHttp private import semmle.code.java.frameworks.spring.SpringUtil private import semmle.code.java.frameworks.spring.SpringWebClient + private import semmle.code.java.frameworks.spring.SpringBeans private import semmle.code.java.security.ResponseSplitting private import semmle.code.java.security.InformationLeak private import semmle.code.java.security.XSS diff --git a/java/ql/src/semmle/code/java/frameworks/spring/Spring.qll b/java/ql/src/semmle/code/java/frameworks/spring/Spring.qll index 2b4ad64b1f6..8a80e6a43d4 100644 --- a/java/ql/src/semmle/code/java/frameworks/spring/Spring.qll +++ b/java/ql/src/semmle/code/java/frameworks/spring/Spring.qll @@ -6,6 +6,7 @@ import semmle.code.java.frameworks.spring.SpringAttribute import semmle.code.java.frameworks.spring.SpringAutowire import semmle.code.java.frameworks.spring.SpringBean import semmle.code.java.frameworks.spring.SpringBeanFile +import semmle.code.java.frameworks.spring.SpringBeans import semmle.code.java.frameworks.spring.SpringBeanRefType import semmle.code.java.frameworks.spring.SpringComponentScan import semmle.code.java.frameworks.spring.SpringConstructorArg diff --git a/java/ql/src/semmle/code/java/frameworks/spring/SpringBeans.qll b/java/ql/src/semmle/code/java/frameworks/spring/SpringBeans.qll new file mode 100644 index 00000000000..7833f5668db --- /dev/null +++ b/java/ql/src/semmle/code/java/frameworks/spring/SpringBeans.qll @@ -0,0 +1,44 @@ +/** + * Provides classes and predicates for working with Spring classes and interfaces from + * `org.springframework.beans`. + */ + +import java +private import semmle.code.java.dataflow.ExternalFlow + +/** + * Provides models for the `org.springframework.beans` package. + */ +private class FlowSummaries extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.springframework.beans;PropertyValue;false;PropertyValue;(String,Object);;Argument[0];MapKey of Argument[-1];value", + "org.springframework.beans;PropertyValue;false;PropertyValue;(String,Object);;Argument[1];MapValue of Argument[-1];value", + "org.springframework.beans;PropertyValue;false;PropertyValue;(PropertyValue);;Argument[0];Argument[-1];value", + "org.springframework.beans;PropertyValue;false;PropertyValue;(PropertyValue,Object);;MapKey of Argument[0];MapKey of Argument[-1];value", + "org.springframework.beans;PropertyValue;false;PropertyValue;(PropertyValue,Object);;Argument[1];MapValue of Argument[-1];value", + "org.springframework.beans;PropertyValue;false;getName;;;MapKey of Argument[-1];ReturnValue;value", + "org.springframework.beans;PropertyValue;false;getValue;;;MapValue of Argument[-1];ReturnValue;value", + "org.springframework.beans;PropertyValues;true;getPropertyValue;;;Element of Argument[-1];ReturnValue;value", + "org.springframework.beans;PropertyValues;true;getPropertyValues;;;Element of Argument[-1];ArrayElement of ReturnValue;value", + "org.springframework.beans;MutablePropertyValues;true;add;(String,Object);;Argument[0];MapKey of Element of Argument[-1];value", + "org.springframework.beans;MutablePropertyValues;true;add;(String,Object);;Argument[-1];ReturnValue;value", + "org.springframework.beans;MutablePropertyValues;true;add;(String,Object);;Argument[1];MapValue of Element of Argument[-1];value", + "org.springframework.beans;MutablePropertyValues;true;addPropertyValue;(PropertyValue);;Argument[0];Element of Argument[-1];value", + "org.springframework.beans;MutablePropertyValues;true;addPropertyValue;(PropertyValue);;Argument[-1];ReturnValue;value", + "org.springframework.beans;MutablePropertyValues;true;addPropertyValue;(String,Object);;Argument[0];MapKey of Element of Argument[-1];value", + "org.springframework.beans;MutablePropertyValues;true;addPropertyValue;(String,Object);;Argument[1];MapValue of Element of Argument[-1];value", + "org.springframework.beans;MutablePropertyValues;true;addPropertyValues;(Map);;MapKey of Argument[0];MapKey of Element of Argument[-1];value", + "org.springframework.beans;MutablePropertyValues;true;addPropertyValues;(Map);;MapValue of Argument[0];MapValue of Element of Argument[-1];value", + "org.springframework.beans;MutablePropertyValues;true;addPropertyValues;(Map);;Argument[-1];ReturnValue;value", + "org.springframework.beans;MutablePropertyValues;true;addPropertyValues;(PropertyValues);;Element of Argument[0];Element of Argument[-1];value", + "org.springframework.beans;MutablePropertyValues;true;addPropertyValues;(PropertyValues);;Argument[-1];ReturnValue;value", + "org.springframework.beans;MutablePropertyValues;true;get;;;MapValue of Element of Argument[-1];ReturnValue;value", + "org.springframework.beans;MutablePropertyValues;true;getPropertyValue;;;Element of Argument[-1];ReturnValue;value", + "org.springframework.beans;MutablePropertyValues;true;getPropertyValueList;;;Element of Argument[-1];Element of ReturnValue;value", + "org.springframework.beans;MutablePropertyValues;true;getPropertyValues;;;Element of Argument[-1];ArrayElement of ReturnValue;value", + "org.springframework.beans;MutablePropertyValues;true;setPropertyValueAt;;;Argument[0];Element of Argument[-1];value" + ] + } +} diff --git a/java/ql/test/library-tests/frameworks/spring/beans/Test.java b/java/ql/test/library-tests/frameworks/spring/beans/Test.java new file mode 100644 index 00000000000..945dfffc144 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/spring/beans/Test.java @@ -0,0 +1,299 @@ +package generatedtest; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.PropertyValue; +import org.springframework.beans.PropertyValues; + + +public class Test { + Object getMapKey(PropertyValue container) { + return container.getName(); + } + + Object getMapValue(PropertyValue container) { + return container.getValue(); + } + + PropertyValue getElement(Iterable container) { + return container.iterator().next(); + } + + PropertyValue getArrayElement(PropertyValue[] container) { + return container[0]; + } + + PropertyValue newWithMapKey(String element) { + return new PropertyValue(element, null); + } + + PropertyValue newWithMapValue(String element) { + return new PropertyValue("", element); + } + + MutablePropertyValues newWithElement(PropertyValue element) { + MutablePropertyValues pv = new MutablePropertyValues(); + pv.addPropertyValue(element); + return pv; + } + + String source() { + return null; + } + + void sink(Object o) {} + + public void test() { + // @formatter:off + // "org.springframework.beans;PropertyValue;false;;(String,Object);;Argument[0];MapKey of Argument[-1];value", + { + PropertyValue v = new PropertyValue((String) source(), null); + sink(getMapKey(v)); // $hasValueFlow + sink(getMapValue(v)); // Safe + } + // "org.springframework.beans;PropertyValue;false;;(String,Object);;Argument[1];MapValue of Argument[-1];value", + { + PropertyValue v = new PropertyValue("", source()); + sink(getMapKey(v)); // Safe + sink(getMapValue(v)); // $hasValueFlow + } + // "org.springframework.beans;PropertyValue;false;;(PropertyValue);;Argument[0];Argument[-1];value", + { + PropertyValue v1 = new PropertyValue((String) source(), null); + PropertyValue v2 = new PropertyValue(v1); + sink(getMapKey(v2)); // $hasValueFlow + sink(getMapValue(v2)); // Safe + + PropertyValue v3 = new PropertyValue("safe", source()); + PropertyValue v4 = new PropertyValue(v3); + sink(getMapKey(v4)); // Safe + sink(getMapValue(v4)); // $hasValueFlow + } + // "org.springframework.beans;PropertyValue;false;;(PropertyValue,Object);;MapKey of Argument[0];MapKey of Argument[-1];value", + { + PropertyValue v1 = new PropertyValue((String) source(), source()); + PropertyValue v2 = new PropertyValue(v1, null); + sink(getMapKey(v2)); // $hasValueFlow + sink(getMapValue(v2)); // Safe + } + // "org.springframework.beans;PropertyValue;false;PropertyValue;(PropertyValue,Object);;Argument[1];MapValue of Argument[-1];value", + { + PropertyValue v1 = new PropertyValue("safe", null); + PropertyValue v2 = new PropertyValue(v1, source()); + sink(getMapKey(v2)); // Safe + sink(getMapValue(v2)); // $hasValueFlow + } + // "org.springframework.beans;PropertyValue;false;getName;;;MapKey of Argument[-1];ReturnValue;value", + { + PropertyValue v = new PropertyValue((String) source(), null); + sink(v.getName()); // $hasValueFlow + sink(v.getValue()); // Safe + } + // "org.springframework.beans;PropertyValue;false;getValue;;;MapValue of Argument[-1];ReturnValue;value", + { + PropertyValue v = new PropertyValue("safe", source()); + sink(v.getName()); // Safe + sink(v.getValue()); // $hasValueFlow + } + // "org.springframework.beans;PropertyValues;true;getPropertyValue;;;Element of Argument[-1];ReturnValue;value", + { + PropertyValues pv = newWithElement(newWithMapValue(source())); + sink(pv.getPropertyValue("safe").getValue()); // $hasValueFlow + } + // "org.springframework.beans;PropertyValues;true;getPropertyValues;;;Element of Argument[-1];ArrayElement of ReturnValue;value", + { + PropertyValues pv = newWithElement(newWithMapValue(source())); + PropertyValue[] vs = pv.getPropertyValues(); + sink(getMapKey(getArrayElement(vs))); // Safe + sink(getMapValue(getArrayElement(vs))); // $hasValueFlow + } + // "org.springframework.beans;MutablePropertyValues;true;add;(String,Object);;Argument[0];MapKey of Element of Argument[-1];value", + { + MutablePropertyValues pv = new MutablePropertyValues(); + pv.add((String) source(), null); + sink(getMapKey(getElement(pv))); // $hasValueFlow + sink(getMapValue(getElement(pv))); // Safe + } + // "org.springframework.beans;MutablePropertyValues;true;add;(String,Object);;Argument[-1];ReturnValue;value", + { + MutablePropertyValues pv = new MutablePropertyValues(); + sink(getMapKey(getElement(pv.add(source(), null)))); // $hasValueFlow + sink(getMapValue(getElement(pv.add(source(), null)))); // Safe + } + { + MutablePropertyValues pv = new MutablePropertyValues(); + sink(getMapKey(getElement(pv.add("safe", source())))); // Safe + sink(getMapValue(getElement(pv.add("safe", source())))); // $hasValueFlow + } + // "org.springframework.beans;MutablePropertyValues;true;add;(String,Object);;Argument[1];MapValue of Element of Argument[-1];value", + { + MutablePropertyValues pv = new MutablePropertyValues(); + pv.add("safe", source()); + sink(getMapKey(getElement(pv))); // Safe + sink(getMapValue(getElement(pv))); // $hasValueFlow + } + // "org.springframework.beans;MutablePropertyValues;true;addPropertyValue;(PropertyValue);;Argument[0];Element of Argument[-1];value", + { + MutablePropertyValues pv1 = new MutablePropertyValues(); + PropertyValue v1 = newWithMapKey(source()); + pv1.addPropertyValue(v1); + sink(getMapKey(getElement(pv1))); // $hasValueFlow + sink(getMapValue(getElement(pv1))); // Safe + + MutablePropertyValues pv2 = new MutablePropertyValues(); + PropertyValue v2 = newWithMapValue(source()); + pv2.addPropertyValue(v2); + sink(getMapKey(getElement(pv2))); // Safe + sink(getMapValue(getElement(pv2))); // $hasValueFlow + } + // "org.springframework.beans;MutablePropertyValues;true;addPropertyValue;(PropertyValue);;Argument[-1];ReturnValue;value", + { + MutablePropertyValues pv1 = new MutablePropertyValues(); + PropertyValue v1 = newWithMapKey(source()); + PropertyValues pv2 = pv1.addPropertyValue(v1); + sink(getMapKey(getElement(pv2))); // $hasValueFlow + sink(getMapValue(getElement(pv2))); // Safe + + MutablePropertyValues pv3 = new MutablePropertyValues(); + PropertyValue v2 = newWithMapValue(source()); + PropertyValues pv4 = pv3.addPropertyValue(v2); + sink(getMapKey(getElement(pv4))); // Safe + sink(getMapValue(getElement(pv4))); // $hasValueFlow + } + // "org.springframework.beans;MutablePropertyValues;true;addPropertyValue;(String,Object);;Argument[0];MapKey of Element of Argument[-1];value", + { + MutablePropertyValues pv = new MutablePropertyValues(); + pv.addPropertyValue((String)source(), null); + sink(getMapKey(getElement(pv))); // $hasValueFlow + sink(getMapValue(getElement(pv))); // Safe + } + // "org.springframework.beans;MutablePropertyValues;true;addPropertyValue;(String,Object);;Argument[1];MapValue of Element of Argument[-1];value", + { + MutablePropertyValues pv = new MutablePropertyValues(); + pv.addPropertyValue("safe", source()); + sink(getMapKey(getElement(pv))); // Safe + sink(getMapValue(getElement(pv))); // $hasValueFlow + } + // "org.springframework.beans;MutablePropertyValues;true;addPropertyValues;(Map);;MapKey of Argument[0];MapKey of Element of Argument[-1];value", + { + MutablePropertyValues pv = new MutablePropertyValues(); + Map values = new HashMap(); + values.put(source(), null); + pv.addPropertyValues(values); + sink(getMapKey(getElement(pv))); // $hasValueFlow + sink(getMapValue(getElement(pv))); // Safe + } + // "org.springframework.beans;MutablePropertyValues;true;addPropertyValues;(Map);;MapValue of Argument[0];MapValue of Element of Argument[-1];value", + { + MutablePropertyValues pv = new MutablePropertyValues(); + Map values = new HashMap(); + values.put("", source()); + pv.addPropertyValues(values); + sink(getMapKey(getElement(pv))); // Safe + sink(getMapValue(getElement(pv))); // $hasValueFlow + } + // "org.springframework.beans;MutablePropertyValues;true;addPropertyValues;(Map);;Argument[-1];ReturnValue;value", + { + MutablePropertyValues pv = new MutablePropertyValues(); + Map values = new HashMap(); + values.put("", source()); + PropertyValues pv2 = pv.addPropertyValues(values); + sink(getMapKey(getElement(pv2))); // Safe + sink(getMapValue(getElement(pv2))); // $hasValueFlow + } + { + MutablePropertyValues pv = new MutablePropertyValues(); + Map values = new HashMap(); + values.put(source(), null); + PropertyValues pv2 = pv.addPropertyValues(values); + sink(getMapKey(getElement(pv2))); // $hasValueFlow + sink(getMapValue(getElement(pv2))); // Safe + } + // "org.springframework.beans;MutablePropertyValues;true;addPropertyValues;(PropertyValues);;Element of Argument[0];Element of Argument[-1];value", + { + MutablePropertyValues pv = new MutablePropertyValues(); + PropertyValues values = newWithElement(newWithMapKey(source())); + pv.addPropertyValues(values); + sink(getMapKey(getElement(pv))); // $hasValueFlow + sink(getMapValue(getElement(pv))); // Safe + } + { + MutablePropertyValues pv = new MutablePropertyValues(); + PropertyValues values = newWithElement(newWithMapValue(source())); + pv.addPropertyValues(values); + sink(getMapKey(getElement(pv))); // Safe + sink(getMapValue(getElement(pv))); // $hasValueFlow + } + // "org.springframework.beans;MutablePropertyValues;true;addPropertyValues;(PropertyValues);;Argument[-1];ReturnValue;value", + { + MutablePropertyValues pv = new MutablePropertyValues(); + PropertyValues values = newWithElement(newWithMapKey(source())); + PropertyValues pv2 = pv.addPropertyValues(values); + sink(getMapKey(getElement(pv2))); // $hasValueFlow + sink(getMapValue(getElement(pv2))); // Safe + } + { + MutablePropertyValues pv = new MutablePropertyValues(); + PropertyValues values = newWithElement(newWithMapValue(source())); + PropertyValues pv2 = pv.addPropertyValues(values); + sink(getMapKey(getElement(pv2))); // Safe + sink(getMapValue(getElement(pv2))); // $hasValueFlow + } + // "org.springframework.beans;MutablePropertyValues;true;get;;;MapValue of Element of Argument[-1];ReturnValue;value", + { + MutablePropertyValues pv = newWithElement(newWithMapValue(source())); + sink(pv.get("something")); // $hasValueFlow + } + // "org.springframework.beans;MutablePropertyValues;true;getPropertyValue;;;Element of Argument[-1];ReturnValue;value", + { + MutablePropertyValues pv1 = newWithElement(newWithMapKey(source())); + sink(pv1.getPropertyValue("something").getName()); // $hasValueFlow + sink(pv1.getPropertyValue("something").getValue()); // Safe + + MutablePropertyValues pv2 = newWithElement(newWithMapValue(source())); + sink(pv2.getPropertyValue("something").getName()); // Safe + sink(pv2.getPropertyValue("something").getValue()); // $hasValueFlow + } + // "org.springframework.beans;MutablePropertyValues;true;getPropertyValueList;;;Element of Argument[-1];Element of ReturnValue;value", + { + MutablePropertyValues pv1 = newWithElement(newWithMapKey(source())); + List pvl1 = pv1.getPropertyValueList(); + sink(getMapKey(getElement(pvl1))); // $hasValueFlow + sink(getMapValue(getElement(pvl1))); // Safe + + MutablePropertyValues pv2 = newWithElement(newWithMapValue(source())); + List pvl2 = pv2.getPropertyValueList(); + sink(getMapKey(getElement(pvl2))); // Safe + sink(getMapValue(getElement(pvl2))); // $hasValueFlow + } + // "org.springframework.beans;MutablePropertyValues;true;getPropertyValues;;;Element of Argument[-1];ArrayElement of ReturnValue;value", + { + MutablePropertyValues pv1 = newWithElement(newWithMapKey(source())); + PropertyValue[] pvl1 = pv1.getPropertyValues(); + sink(getMapKey(getArrayElement(pvl1))); // $hasValueFlow + sink(getMapValue(getArrayElement(pvl1))); // Safe + + MutablePropertyValues pv2 = newWithElement(newWithMapValue(source())); + PropertyValue[] pvl2 = pv2.getPropertyValues(); + sink(getMapKey(getArrayElement(pvl2))); // Safe + sink(getMapValue(getArrayElement(pvl2))); // $hasValueFlow + } + // "org.springframework.beans;MutablePropertyValues;true;setPropertyValueAt;;;Argument[0];Element of Argument[-1];value" + { + MutablePropertyValues pv1 = new MutablePropertyValues(); + PropertyValue v1 = newWithMapKey(source()); + pv1.setPropertyValueAt(v1, 0); + sink(getMapKey(getElement(pv1))); // $hasValueFlow + sink(getMapValue(getElement(pv1))); // Safe + + MutablePropertyValues pv2 = new MutablePropertyValues(); + PropertyValue v2 = newWithMapValue(source()); + pv2.setPropertyValueAt(v2, 0); + sink(getMapKey(getElement(pv2))); // Safe + sink(getMapValue(getElement(pv2))); // $hasValueFlow + } + // @formatter:on + } +} diff --git a/java/ql/test/library-tests/frameworks/spring/beans/options b/java/ql/test/library-tests/frameworks/spring/beans/options new file mode 100644 index 00000000000..0c6ef357b21 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/spring/beans/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.3.8 \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/spring/beans/test.expected b/java/ql/test/library-tests/frameworks/spring/beans/test.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/frameworks/spring/beans/test.ql b/java/ql/test/library-tests/frameworks/spring/beans/test.ql new file mode 100644 index 00000000000..912675470e1 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/spring/beans/test.ql @@ -0,0 +1,52 @@ +import java +import semmle.code.java.dataflow.ExternalFlow +import semmle.code.java.dataflow.TaintTracking +import TestUtilities.InlineExpectationsTest + +class ValueFlowConf extends DataFlow::Configuration { + ValueFlowConf() { this = "qltest:valueFlowConf" } + + override predicate isSource(DataFlow::Node n) { + n.asExpr().(MethodAccess).getMethod().hasName("source") + } + + override predicate isSink(DataFlow::Node n) { + n.asExpr().(Argument).getCall().getCallee().hasName("sink") + } +} + +class TaintFlowConf extends TaintTracking::Configuration { + TaintFlowConf() { this = "qltest:taintFlowConf" } + + override predicate isSource(DataFlow::Node n) { + n.asExpr().(MethodAccess).getMethod().hasName("source") + } + + override predicate isSink(DataFlow::Node n) { + n.asExpr().(Argument).getCall().getCallee().hasName("sink") + } +} + +class HasFlowTest extends InlineExpectationsTest { + HasFlowTest() { this = "HasFlowTest" } + + override string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasValueFlow" and + exists(DataFlow::Node src, DataFlow::Node sink, ValueFlowConf conf | conf.hasFlow(src, sink) | + sink.getLocation() = location and + element = sink.toString() and + value = "" + ) + or + tag = "hasTaintFlow" and + exists(DataFlow::Node src, DataFlow::Node sink, TaintFlowConf conf | + conf.hasFlow(src, sink) and not any(ValueFlowConf c).hasFlow(src, sink) + | + sink.getLocation() = location and + element = sink.toString() and + value = "" + ) + } +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/beans/MutablePropertyValues.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/beans/MutablePropertyValues.java new file mode 100644 index 00000000000..fed50425d90 --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/beans/MutablePropertyValues.java @@ -0,0 +1,135 @@ +/* + * Copyright 2002-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package org.springframework.beans; + +import java.io.Serializable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Spliterator; +import java.util.stream.Stream; +import org.springframework.lang.Nullable; + +public class MutablePropertyValues implements PropertyValues, Serializable { + public MutablePropertyValues() {} + + public MutablePropertyValues(@Nullable PropertyValues original) {} + + public MutablePropertyValues(@Nullable Map original) {} + + public MutablePropertyValues(@Nullable List propertyValueList) {} + + public List getPropertyValueList() { + return null; + } + + public int size() { + return 0; + } + + public MutablePropertyValues addPropertyValues(@Nullable PropertyValues other) { + return null; + } + + public MutablePropertyValues addPropertyValues(@Nullable Map other) { + return null; + } + + public MutablePropertyValues addPropertyValue(PropertyValue pv) { + return null; + } + + public void addPropertyValue(String propertyName, Object propertyValue) {} + + public MutablePropertyValues add(String propertyName, @Nullable Object propertyValue) { + return null; + } + + public void setPropertyValueAt(PropertyValue pv, int i) {} + + public void removePropertyValue(PropertyValue pv) {} + + public void removePropertyValue(String propertyName) {} + + @Override + public Iterator iterator() { + return null; + } + + @Override + public Spliterator spliterator() { + return null; + } + + @Override + public Stream stream() { + return null; + } + + @Override + public PropertyValue[] getPropertyValues() { + return null; + } + + @Override + public PropertyValue getPropertyValue(String propertyName) { + return null; + } + + public Object get(String propertyName) { + return null; + } + + @Override + public PropertyValues changesSince(PropertyValues old) { + return null; + } + + @Override + public boolean contains(String propertyName) { + return false; + } + + @Override + public boolean isEmpty() { + return false; + } + + public void registerProcessedProperty(String propertyName) {} + + public void clearProcessedProperty(String propertyName) {} + + public void setConverted() {} + + public boolean isConverted() { + return false; + } + + @Override + public boolean equals(@Nullable Object other) { + return false; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public String toString() { + return null; + } + +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/beans/PropertyValue.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/beans/PropertyValue.java new file mode 100644 index 00000000000..2787aa04f17 --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/beans/PropertyValue.java @@ -0,0 +1,70 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package org.springframework.beans; + +import java.io.Serializable; +import org.springframework.lang.Nullable; + +public class PropertyValue implements Serializable { + public PropertyValue(String name, @Nullable Object value) {} + + public PropertyValue(PropertyValue original) {} + + public PropertyValue(PropertyValue original, @Nullable Object newValue) {} + + public String getName() { + return null; + } + + public Object getValue() { + return null; + } + + public PropertyValue getOriginalPropertyValue() { + return null; + } + + public void setOptional(boolean optional) {} + + public boolean isOptional() { + return false; + } + + public synchronized boolean isConverted() { + return false; + } + + public synchronized void setConvertedValue(@Nullable Object value) {} + + public synchronized Object getConvertedValue() { + return null; + } + + @Override + public boolean equals(@Nullable Object other) { + return false; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public String toString() { + return null; + } + +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/beans/PropertyValues.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/beans/PropertyValues.java new file mode 100644 index 00000000000..9d5b1f51ec3 --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/beans/PropertyValues.java @@ -0,0 +1,46 @@ +/* + * Copyright 2002-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package org.springframework.beans; + +import java.util.Iterator; +import java.util.Spliterator; +import java.util.stream.Stream; + +public interface PropertyValues extends Iterable { + @Override + default Iterator iterator() { + return null; + } + + @Override + default Spliterator spliterator() { + return null; + } + + default Stream stream() { + return null; + } + + PropertyValue[] getPropertyValues(); + + PropertyValue getPropertyValue(String propertyName); + + PropertyValues changesSince(PropertyValues old); + + boolean contains(String propertyName); + + boolean isEmpty(); + +}