diff --git a/java/change-notes/2021-05-11-apache-tuples.md b/java/change-notes/2021-05-11-apache-tuples.md new file mode 100644 index 00000000000..2eab20ecd4f --- /dev/null +++ b/java/change-notes/2021-05-11-apache-tuples.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added models for the Apache Commons Lang tuple types (Pair, Triple and their immutable and mutable implementations). This may lead to more results from any query using data-flow analysis where a relevant path uses one of these container types. diff --git a/java/ql/src/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll b/java/ql/src/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll index d28dd2206ac..974982a9c29 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll @@ -70,9 +70,22 @@ predicate summaryElement(DataFlowCallable c, string input, string output, string ) } +private FieldContent parseField(string c) { + External::specSplit(_, c, _) and + exists(string fieldRegex, string package, string className, string fieldName | + fieldRegex = "^Field\\[(.*)\\.([^.]+)\\.([^.]+)\\]$" and + package = c.regexpCapture(fieldRegex, 1) and + className = c.regexpCapture(fieldRegex, 2) and + fieldName = c.regexpCapture(fieldRegex, 3) and + result.getField().hasQualifiedName(package, className, fieldName) + ) +} + /** Gets the summary component for specification component `c`, if any. */ bindingset[c] SummaryComponent interpretComponentSpecific(string c) { + result = SummaryComponent::content(parseField(c)) + or c = "ArrayElement" and result = SummaryComponent::content(any(ArrayContent c0)) or c = "Element" and result = SummaryComponent::content(any(CollectionContent c0)) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll b/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll index 38469bf6b76..bf47d627686 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll @@ -789,3 +789,72 @@ private class ApacheToStringBuilderModel extends SummaryModelCsv { ] } } + +/** + * Value-propagating models for `Pair`, `ImmutablePair` and `MutablePair`. + */ +private class ApachePairModel extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value", + "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];value", + "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];value", + "org.apache.commons.lang3.tuple;ImmutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutablePair;false;left;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutablePair;false;right;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value", + "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;MutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;MutablePair;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutablePair;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutablePair;false;setValue;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of ReturnValue;value", + "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of ReturnValue;value" + ] + } +} + +/** + * Value-propagating models for `Triple`, `ImmutableTriple` and `MutableTriple`. + */ +private class ApacheTripleModel extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value", + "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value", + "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];value", + "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];value", + "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];value", + "org.apache.commons.lang3.tuple;ImmutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value", + "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;MutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;MutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;MutableTriple;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutableTriple;false;setMiddle;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutableTriple;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of ReturnValue;value", + "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of ReturnValue;value", + "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of ReturnValue;value" + ] + } +} diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/PairTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/PairTest.java new file mode 100644 index 00000000000..6db15beb181 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/PairTest.java @@ -0,0 +1,150 @@ +import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.MutablePair; + +class PairTest { + String taint() { return "tainted"; } + + private static class IntSource { + static int taint() { return 0; } + } + + void sink(Object o) {} + + void test() throws Exception { + + ImmutablePair taintedLeft = ImmutablePair.of(taint(), "clean-right"); + ImmutablePair taintedRight = ImmutablePair.of("clean-left", taint()); + Pair taintedLeft2_ = ImmutablePair.left(taint()); + ImmutablePair taintedLeft2 = (ImmutablePair)taintedLeft2_; + Pair taintedRight2_ = ImmutablePair.right(taint()); + ImmutablePair taintedRight2 = (ImmutablePair)taintedRight2_; + Pair taintedLeft3 = Pair.of(taint(), "clean-right"); + Pair taintedRight3 = Pair.of("clean-left", taint()); + ImmutablePair taintedLeft4 = new ImmutablePair(taint(), "clean-right"); + ImmutablePair taintedRight4 = new ImmutablePair("clean-left", taint()); + + // Check flow through ImmutablePairs: + sink(taintedLeft.getLeft()); // $hasValueFlow + sink(taintedLeft.getRight()); + sink(taintedLeft.getKey()); // $hasValueFlow + sink(taintedLeft.getValue()); + sink(taintedLeft.left); // $hasValueFlow + sink(taintedLeft.right); + sink(taintedRight.getLeft()); + sink(taintedRight.getRight()); // $hasValueFlow + sink(taintedRight.getKey()); + sink(taintedRight.getValue()); // $hasValueFlow + sink(taintedRight.left); + sink(taintedRight.right); // $hasValueFlow + sink(taintedLeft2.getLeft()); // $hasValueFlow + sink(taintedLeft2.getRight()); + sink(taintedLeft2.getKey()); // $hasValueFlow + sink(taintedLeft2.getValue()); + sink(taintedLeft2.left); // $hasValueFlow + sink(taintedLeft2.right); + sink(taintedRight2.getLeft()); + sink(taintedRight2.getRight()); // $hasValueFlow + sink(taintedRight2.getKey()); + sink(taintedRight2.getValue()); // $hasValueFlow + sink(taintedRight2.left); + sink(taintedRight2.right); // $hasValueFlow + sink(taintedLeft3.getLeft()); // $hasValueFlow + sink(taintedLeft3.getRight()); + sink(taintedLeft3.getKey()); // $hasValueFlow + sink(taintedLeft3.getValue()); + sink(taintedRight3.getLeft()); + sink(taintedRight3.getRight()); // $hasValueFlow + sink(taintedRight3.getKey()); + sink(taintedRight3.getValue()); // $hasValueFlow + sink(taintedLeft4.getLeft()); // $hasValueFlow + sink(taintedLeft4.getRight()); + sink(taintedLeft4.getKey()); // $hasValueFlow + sink(taintedLeft4.getValue()); + sink(taintedLeft4.left); // $hasValueFlow + sink(taintedLeft4.right); + sink(taintedRight4.getLeft()); + sink(taintedRight4.getRight()); // $hasValueFlow + sink(taintedRight4.getKey()); + sink(taintedRight4.getValue()); // $hasValueFlow + sink(taintedRight4.left); + sink(taintedRight4.right); // $hasValueFlow + + // Check flow also works via an alias of type Pair: + sink(taintedLeft2_.getLeft()); // $hasValueFlow + sink(taintedLeft2_.getRight()); + sink(taintedLeft2_.getKey()); // $hasValueFlow + sink(taintedLeft2_.getValue()); + sink(taintedRight2_.getLeft()); + sink(taintedRight2_.getRight()); // $hasValueFlow + sink(taintedRight2_.getKey()); + sink(taintedRight2_.getValue()); // $hasValueFlow + + // Check flow through MutablePairs: + MutablePair taintedLeftMutable = MutablePair.of(taint(), "clean-right"); + MutablePair taintedRightMutable = MutablePair.of("clean-left", taint()); + MutablePair setTaintLeft = MutablePair.of("clean-left", "clean-right"); + setTaintLeft.setLeft(taint()); + MutablePair setTaintRight = MutablePair.of("clean-left", "clean-right"); + setTaintRight.setRight(taint()); + MutablePair setTaintValue = MutablePair.of("clean-left", "clean-right"); + setTaintValue.setValue(taint()); + MutablePair taintedLeftMutableConstructed = new MutablePair(taint(), "clean-right"); + MutablePair taintedRightMutableConstructed = new MutablePair("clean-left", taint()); + + sink(taintedLeftMutable.getLeft()); // $hasValueFlow + sink(taintedLeftMutable.getRight()); + sink(taintedLeftMutable.getKey()); // $hasValueFlow + sink(taintedLeftMutable.getValue()); + sink(taintedLeftMutable.left); // $hasValueFlow + sink(taintedLeftMutable.right); + sink(taintedRightMutable.getLeft()); + sink(taintedRightMutable.getRight()); // $hasValueFlow + sink(taintedRightMutable.getKey()); + sink(taintedRightMutable.getValue()); // $hasValueFlow + sink(taintedRightMutable.left); + sink(taintedRightMutable.right); // $hasValueFlow + sink(setTaintLeft.getLeft()); // $hasValueFlow + sink(setTaintLeft.getRight()); + sink(setTaintLeft.getKey()); // $hasValueFlow + sink(setTaintLeft.getValue()); + sink(setTaintLeft.left); // $hasValueFlow + sink(setTaintLeft.right); + sink(setTaintRight.getLeft()); + sink(setTaintRight.getRight()); // $hasValueFlow + sink(setTaintRight.getKey()); + sink(setTaintRight.getValue()); // $hasValueFlow + sink(setTaintRight.left); + sink(setTaintRight.right); // $hasValueFlow + sink(setTaintValue.getLeft()); + sink(setTaintValue.getRight()); // $hasValueFlow + sink(setTaintValue.getKey()); + sink(setTaintValue.getValue()); // $hasValueFlow + sink(setTaintValue.left); + sink(setTaintValue.right); // $hasValueFlow + sink(taintedLeftMutableConstructed.getLeft()); // $hasValueFlow + sink(taintedLeftMutableConstructed.getRight()); + sink(taintedLeftMutableConstructed.getKey()); // $hasValueFlow + sink(taintedLeftMutableConstructed.getValue()); + sink(taintedLeftMutableConstructed.left); // $hasValueFlow + sink(taintedLeftMutableConstructed.right); + sink(taintedRightMutableConstructed.getLeft()); + sink(taintedRightMutableConstructed.getRight()); // $hasValueFlow + sink(taintedRightMutableConstructed.getKey()); + sink(taintedRightMutableConstructed.getValue()); // $hasValueFlow + sink(taintedRightMutableConstructed.left); + sink(taintedRightMutableConstructed.right); // $hasValueFlow + + // Check flow also works via an alias of type Pair: + Pair taintedLeftMutableAlias = taintedLeftMutable; + Pair taintedRightMutableAlias = taintedRightMutable; + sink(taintedLeftMutableAlias.getLeft()); // $hasValueFlow + sink(taintedLeftMutableAlias.getRight()); + sink(taintedLeftMutableAlias.getKey()); // $hasValueFlow + sink(taintedLeftMutableAlias.getValue()); + sink(taintedRightMutableAlias.getLeft()); + sink(taintedRightMutableAlias.getRight()); // $hasValueFlow + sink(taintedRightMutableAlias.getKey()); + sink(taintedRightMutableAlias.getValue()); // $hasValueFlow + } +} \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/TripleTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/TripleTest.java new file mode 100644 index 00000000000..b6f9c53cc7e --- /dev/null +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/TripleTest.java @@ -0,0 +1,181 @@ +import org.apache.commons.lang3.tuple.Triple; +import org.apache.commons.lang3.tuple.ImmutableTriple; +import org.apache.commons.lang3.tuple.MutableTriple; + +class TripleTest { + String taint() { return "tainted"; } + + private static class IntSource { + static int taint() { return 0; } + } + + void sink(Object o) {} + + void test() throws Exception { + + ImmutableTriple taintedLeft = ImmutableTriple.of(taint(), "clean-middle", "clean-right"); + ImmutableTriple taintedMiddle = ImmutableTriple.of("clean-left", taint(), "clean-right"); + ImmutableTriple taintedRight = ImmutableTriple.of("clean-left", "clean-middle", taint()); + + // Check flow through ImmutableTriples: + sink(taintedLeft.getLeft()); // $hasValueFlow + sink(taintedLeft.getMiddle()); + sink(taintedLeft.getRight()); + sink(taintedLeft.left); // $hasValueFlow + sink(taintedLeft.middle); + sink(taintedLeft.right); + sink(taintedMiddle.getLeft()); + sink(taintedMiddle.getMiddle()); // $hasValueFlow + sink(taintedMiddle.getRight()); + sink(taintedMiddle.left); + sink(taintedMiddle.middle); // $hasValueFlow + sink(taintedMiddle.right); + sink(taintedRight.getLeft()); + sink(taintedRight.getMiddle()); + sink(taintedRight.getRight()); // $hasValueFlow + sink(taintedRight.left); + sink(taintedRight.middle); + sink(taintedRight.right); // $hasValueFlow + + Triple taintedLeft2 = taintedLeft; + Triple taintedMiddle2 = taintedMiddle; + Triple taintedRight2 = taintedRight; + + // Check flow also works via an alias of type Triple: + sink(taintedLeft2.getLeft()); // $hasValueFlow + sink(taintedLeft2.getMiddle()); + sink(taintedLeft2.getRight()); + sink(taintedMiddle2.getLeft()); + sink(taintedMiddle2.getMiddle()); // $hasValueFlow + sink(taintedMiddle2.getRight()); + sink(taintedRight2.getLeft()); + sink(taintedRight2.getMiddle()); + sink(taintedRight2.getRight()); // $hasValueFlow + + // Check flow via Triple.of: + Triple taintedLeft3 = Triple.of(taint(), "clean-middle", "clean-right"); + Triple taintedMiddle3 = Triple.of("clean-left", taint(), "clean-right"); + Triple taintedRight3 = Triple.of("clean-left", "clean-middle", taint()); + + sink(taintedLeft3.getLeft()); // $hasValueFlow + sink(taintedLeft3.getMiddle()); + sink(taintedLeft3.getRight()); + sink(taintedMiddle3.getLeft()); + sink(taintedMiddle3.getMiddle()); // $hasValueFlow + sink(taintedMiddle3.getRight()); + sink(taintedRight3.getLeft()); + sink(taintedRight3.getMiddle()); + sink(taintedRight3.getRight()); // $hasValueFlow + + // Check flow via constructor: + ImmutableTriple taintedLeft4 = new ImmutableTriple(taint(), "clean-middle", "clean-right"); + ImmutableTriple taintedMiddle4 = new ImmutableTriple("clean-left", taint(), "clean-right"); + ImmutableTriple taintedRight4 = new ImmutableTriple("clean-left", "clean-middle", taint()); + + sink(taintedLeft4.getLeft()); // $hasValueFlow + sink(taintedLeft4.getMiddle()); + sink(taintedLeft4.getRight()); + sink(taintedMiddle4.getLeft()); + sink(taintedMiddle4.getMiddle()); // $hasValueFlow + sink(taintedMiddle4.getRight()); + sink(taintedRight4.getLeft()); + sink(taintedRight4.getMiddle()); + sink(taintedRight4.getRight()); // $hasValueFlow + + MutableTriple mutableTaintedLeft = MutableTriple.of(taint(), "clean-middle", "clean-right"); + MutableTriple mutableTaintedMiddle = MutableTriple.of("clean-left", taint(), "clean-right"); + MutableTriple mutableTaintedRight = MutableTriple.of("clean-left", "clean-middle", taint()); + MutableTriple setTaintedLeft = MutableTriple.of("clean-left", "clean-middle", "clean-right"); + setTaintedLeft.setLeft(taint()); + MutableTriple setTaintedMiddle = MutableTriple.of("clean-left", "clean-middle", "clean-right"); + setTaintedMiddle.setMiddle(taint()); + MutableTriple setTaintedRight = MutableTriple.of("clean-left", "clean-middle", "clean-right"); + setTaintedRight.setRight(taint()); + MutableTriple mutableTaintedLeftConstructed = new MutableTriple(taint(), "clean-middle", "clean-right"); + MutableTriple mutableTaintedMiddleConstructed = new MutableTriple("clean-left", taint(), "clean-right"); + MutableTriple mutableTaintedRightConstructed = new MutableTriple("clean-left", "clean-middle", taint()); + + // Check flow through MutableTriples: + sink(mutableTaintedLeft.getLeft()); // $hasValueFlow + sink(mutableTaintedLeft.getMiddle()); + sink(mutableTaintedLeft.getRight()); + sink(mutableTaintedLeft.left); // $hasValueFlow + sink(mutableTaintedLeft.middle); + sink(mutableTaintedLeft.right); + sink(mutableTaintedMiddle.getLeft()); + sink(mutableTaintedMiddle.getMiddle()); // $hasValueFlow + sink(mutableTaintedMiddle.getRight()); + sink(mutableTaintedMiddle.left); + sink(mutableTaintedMiddle.middle); // $hasValueFlow + sink(mutableTaintedMiddle.right); + sink(mutableTaintedRight.getLeft()); + sink(mutableTaintedRight.getMiddle()); + sink(mutableTaintedRight.getRight()); // $hasValueFlow + sink(mutableTaintedRight.left); + sink(mutableTaintedRight.middle); + sink(mutableTaintedRight.right); // $hasValueFlow + sink(setTaintedLeft.getLeft()); // $hasValueFlow + sink(setTaintedLeft.getMiddle()); + sink(setTaintedLeft.getRight()); + sink(setTaintedLeft.left); // $hasValueFlow + sink(setTaintedLeft.middle); + sink(setTaintedLeft.right); + sink(setTaintedMiddle.getLeft()); + sink(setTaintedMiddle.getMiddle()); // $hasValueFlow + sink(setTaintedMiddle.getRight()); + sink(setTaintedMiddle.left); + sink(setTaintedMiddle.middle); // $hasValueFlow + sink(setTaintedMiddle.right); + sink(setTaintedRight.getLeft()); + sink(setTaintedRight.getMiddle()); + sink(setTaintedRight.getRight()); // $hasValueFlow + sink(setTaintedRight.left); + sink(setTaintedRight.middle); + sink(setTaintedRight.right); // $hasValueFlow + sink(mutableTaintedLeftConstructed.getLeft()); // $hasValueFlow + sink(mutableTaintedLeftConstructed.getMiddle()); + sink(mutableTaintedLeftConstructed.getRight()); + sink(mutableTaintedLeftConstructed.left); // $hasValueFlow + sink(mutableTaintedLeftConstructed.middle); + sink(mutableTaintedLeftConstructed.right); + sink(mutableTaintedMiddleConstructed.getLeft()); + sink(mutableTaintedMiddleConstructed.getMiddle()); // $hasValueFlow + sink(mutableTaintedMiddleConstructed.getRight()); + sink(mutableTaintedMiddleConstructed.left); + sink(mutableTaintedMiddleConstructed.middle); // $hasValueFlow + sink(mutableTaintedMiddleConstructed.right); + sink(mutableTaintedRightConstructed.getLeft()); + sink(mutableTaintedRightConstructed.getMiddle()); + sink(mutableTaintedRightConstructed.getRight()); // $hasValueFlow + sink(mutableTaintedRightConstructed.left); + sink(mutableTaintedRightConstructed.middle); + sink(mutableTaintedRightConstructed.right); // $hasValueFlow + + Triple mutableTaintedLeft2 = mutableTaintedLeft; + Triple mutableTaintedMiddle2 = mutableTaintedMiddle; + Triple mutableTaintedRight2 = mutableTaintedRight; + Triple setTaintedLeft2 = setTaintedLeft; + Triple setTaintedMiddle2 = setTaintedMiddle; + Triple setTaintedRight2 = setTaintedRight; + + // Check flow also works via an alias of type Triple: + sink(mutableTaintedLeft2.getLeft()); // $hasValueFlow + sink(mutableTaintedLeft2.getMiddle()); + sink(mutableTaintedLeft2.getRight()); + sink(mutableTaintedMiddle2.getLeft()); + sink(mutableTaintedMiddle2.getMiddle()); // $hasValueFlow + sink(mutableTaintedMiddle2.getRight()); + sink(mutableTaintedRight2.getLeft()); + sink(mutableTaintedRight2.getMiddle()); + sink(mutableTaintedRight2.getRight()); // $hasValueFlow + sink(setTaintedLeft2.getLeft()); // $hasValueFlow + sink(setTaintedLeft2.getMiddle()); + sink(setTaintedLeft2.getRight()); + sink(setTaintedMiddle2.getLeft()); + sink(setTaintedMiddle2.getMiddle()); // $hasValueFlow + sink(setTaintedMiddle2.getRight()); + sink(setTaintedRight2.getLeft()); + sink(setTaintedRight2.getMiddle()); + sink(setTaintedRight2.getRight()); // $hasValueFlow + } +} \ No newline at end of file diff --git a/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/tuple/ImmutablePair.java b/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/tuple/ImmutablePair.java new file mode 100644 index 00000000000..ee4cacd78a6 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/tuple/ImmutablePair.java @@ -0,0 +1,195 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.apache.commons.lang3.tuple; + +import java.util.Map; + +/** + *

An immutable pair consisting of two {@code Object} elements.

+ * + *

Although the implementation is immutable, there is no restriction on the objects + * that may be stored. If mutable objects are stored in the pair, then the pair + * itself effectively becomes mutable. The class is also {@code final}, so a subclass + * can not add undesirable behavior.

+ * + *

#ThreadSafe# if both paired objects are thread-safe

+ * + * @param the left element type + * @param the right element type + * + * @since 3.0 + */ +public final class ImmutablePair extends Pair { + + /** + * An empty array. + *

+ * Consider using {@link #emptyArray()} to avoid generics warnings. + *

+ * + * @since 3.10. + */ + public static final ImmutablePair[] EMPTY_ARRAY = null; + + /** + * An immutable pair of nulls. + */ + // This is not defined with generics to avoid warnings in call sites. + @SuppressWarnings("rawtypes") + private static final ImmutablePair NULL = null; + + /** Serialization version */ + private static final long serialVersionUID = 4954918890077093841L; + + /** + * Returns the empty array singleton that can be assigned without compiler warning. + * + * @param the left element type + * @param the right element type + * @return the empty array singleton that can be assigned without compiler warning. + * + * @since 3.10. + */ + @SuppressWarnings("unchecked") + public static ImmutablePair[] emptyArray() { + return null; + } + + /** + *

Creates an immutable pair of two objects inferring the generic types.

+ * + *

This factory allows the pair to be created using inference to + * obtain the generic types.

+ * + * @param the left element type + * @param the right element type + * @param left the left element, may be null + * @return a pair formed from the two parameters, not null + * @since 3.11 + */ + public static Pair left(final L left) { + return null; + } + + /** + * Returns an immutable pair of nulls. + * + * @param the left element of this pair. Value is {@code null}. + * @param the right element of this pair. Value is {@code null}. + * @return an immutable pair of nulls. + * @since 3.6 + */ + public static ImmutablePair nullPair() { + return null; + } + + /** + *

Creates an immutable pair of two objects inferring the generic types.

+ * + *

This factory allows the pair to be created using inference to + * obtain the generic types.

+ * + * @param the left element type + * @param the right element type + * @param left the left element, may be null + * @param right the right element, may be null + * @return a pair formed from the two parameters, not null + */ + public static ImmutablePair of(final L left, final R right) { + return null; + } + + /** + *

Creates an immutable pair from an existing pair.

+ * + *

This factory allows the pair to be created using inference to + * obtain the generic types.

+ * + * @param the left element type + * @param the right element type + * @param pair the existing pair. + * @return a pair formed from the two parameters, not null + * @since 3.10 + */ + public static ImmutablePair of(final Map.Entry pair) { + return null; + } + + /** + *

Creates an immutable pair of two objects inferring the generic types.

+ * + *

This factory allows the pair to be created using inference to + * obtain the generic types.

+ * + * @param the left element type + * @param the right element type + * @param right the right element, may be null + * @return a pair formed from the two parameters, not null + * @since 3.11 + */ + public static Pair right(final R right) { + return null; + } + + /** Left object */ + public final L left; + + /** Right object */ + public final R right; + + /** + * Create a new pair instance. + * + * @param left the left value, may be null + * @param right the right value, may be null + */ + public ImmutablePair(final L left, final R right) { + this.left = null; + this.right = null; + } + + /** + * {@inheritDoc} + */ + @Override + public L getLeft() { + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public R getRight() { + return null; + } + + /** + *

Throws {@code UnsupportedOperationException}.

+ * + *

This pair is immutable, so this operation is not supported.

+ * + * @param value the value to set + * @return never + * @throws UnsupportedOperationException as this operation is not supported + */ + @Override + public R setValue(final R value) { + return null; + } + +} \ No newline at end of file diff --git a/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/tuple/ImmutableTriple.java b/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/tuple/ImmutableTriple.java new file mode 100644 index 00000000000..846fcbd9052 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/tuple/ImmutableTriple.java @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.apache.commons.lang3.tuple; + +/** + *

An immutable triple consisting of three {@code Object} elements.

+ * + *

Although the implementation is immutable, there is no restriction on the objects + * that may be stored. If mutable objects are stored in the triple, then the triple + * itself effectively becomes mutable. The class is also {@code final}, so a subclass + * can not add undesirable behavior.

+ * + *

#ThreadSafe# if all three objects are thread-safe

+ * + * @param the left element type + * @param the middle element type + * @param the right element type + * + * @since 3.2 + */ +public final class ImmutableTriple extends Triple { + + /** + * An empty array. + *

+ * Consider using {@link #emptyArray()} to avoid generics warnings. + *

+ * + * @since 3.10. + */ + public static final ImmutableTriple[] EMPTY_ARRAY = null; + + /** + * Returns the empty array singleton that can be assigned without compiler warning. + * + * @param the left element type + * @param the middle element type + * @param the right element type + * @return the empty array singleton that can be assigned without compiler warning. + * + * @since 3.10. + */ + @SuppressWarnings("unchecked") + public static ImmutableTriple[] emptyArray() { + return null; + } + + /** + * Returns an immutable triple of nulls. + * + * @param the left element of this triple. Value is {@code null}. + * @param the middle element of this triple. Value is {@code null}. + * @param the right element of this triple. Value is {@code null}. + * @return an immutable triple of nulls. + * @since 3.6 + */ + public static ImmutableTriple nullTriple() { + return null; + } + + /** + *

Obtains an immutable triple of three objects inferring the generic types.

+ * + *

This factory allows the triple to be created using inference to + * obtain the generic types.

+ * + * @param the left element type + * @param the middle element type + * @param the right element type + * @param left the left element, may be null + * @param middle the middle element, may be null + * @param right the right element, may be null + * @return a triple formed from the three parameters, not null + */ + public static ImmutableTriple of(final L left, final M middle, final R right) { + return null; + } + /** Left object */ + public final L left; + /** Middle object */ + public final M middle; + + /** Right object */ + public final R right; + + /** + * Create a new triple instance. + * + * @param left the left value, may be null + * @param middle the middle value, may be null + * @param right the right value, may be null + */ + public ImmutableTriple(final L left, final M middle, final R right) { + this.left = null; + this.middle = null; + this.right = null; + } + + //----------------------------------------------------------------------- + /** + * {@inheritDoc} + */ + @Override + public L getLeft() { + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public M getMiddle() { + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public R getRight() { + return null; + } +} \ No newline at end of file diff --git a/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/tuple/MutablePair.java b/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/tuple/MutablePair.java new file mode 100644 index 00000000000..5826a2145fc --- /dev/null +++ b/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/tuple/MutablePair.java @@ -0,0 +1,158 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.apache.commons.lang3.tuple; + +import java.util.Map; + +/** + *

A mutable pair consisting of two {@code Object} elements.

+ * + *

Not #ThreadSafe#

+ * + * @param the left element type + * @param the right element type + * + * @since 3.0 + */ +public class MutablePair extends Pair { + + /** + * An empty array. + *

+ * Consider using {@link #emptyArray()} to avoid generics warnings. + *

+ * + * @since 3.10. + */ + public static final MutablePair[] EMPTY_ARRAY = null; + + /** + * Returns the empty array singleton that can be assigned without compiler warning. + * + * @param the left element type + * @param the right element type + * @return the empty array singleton that can be assigned without compiler warning. + * + * @since 3.10. + */ + @SuppressWarnings("unchecked") + public static MutablePair[] emptyArray() { + return null; + } + + /** + *

Creates a mutable pair of two objects inferring the generic types.

+ * + *

This factory allows the pair to be created using inference to + * obtain the generic types.

+ * + * @param the left element type + * @param the right element type + * @param left the left element, may be null + * @param right the right element, may be null + * @return a pair formed from the two parameters, not null + */ + public static MutablePair of(final L left, final R right) { + return null; + } + + /** + *

Creates a mutable pair from an existing pair.

+ * + *

This factory allows the pair to be created using inference to + * obtain the generic types.

+ * + * @param the left element type + * @param the right element type + * @param pair the existing pair. + * @return a pair formed from the two parameters, not null + */ + public static MutablePair of(final Map.Entry pair) { + return null; + } + + /** Left object */ + public L left; + + /** Right object */ + public R right; + + /** + * Create a new pair instance of two nulls. + */ + public MutablePair() { + } + + /** + * Create a new pair instance. + * + * @param left the left value, may be null + * @param right the right value, may be null + */ + public MutablePair(final L left, final R right) { + this.left = null; + this.right = null; + } + + //----------------------------------------------------------------------- + /** + * {@inheritDoc} + */ + @Override + public L getLeft() { + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public R getRight() { + return null; + } + + /** + * Sets the left element of the pair. + * + * @param left the new value of the left element, may be null + */ + public void setLeft(final L left) { + + } + + /** + * Sets the right element of the pair. + * + * @param right the new value of the right element, may be null + */ + public void setRight(final R right) { + + } + + /** + * Sets the {@code Map.Entry} value. + * This sets the right element of the pair. + * + * @param value the right value to set, not null + * @return the old value for the right element + */ + @Override + public R setValue(final R value) { + return null; + } + +} \ No newline at end of file diff --git a/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/tuple/MutableTriple.java b/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/tuple/MutableTriple.java new file mode 100644 index 00000000000..dc489c44293 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/tuple/MutableTriple.java @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.apache.commons.lang3.tuple; + +/** + *

A mutable triple consisting of three {@code Object} elements.

+ * + *

Not #ThreadSafe#

+ * + * @param the left element type + * @param the middle element type + * @param the right element type + * + * @since 3.2 + */ +public class MutableTriple extends Triple { + + /** + * The empty array singleton. + *

+ * Consider using {@link #emptyArray()} to avoid generics warnings. + *

+ * + * @since 3.10. + */ + public static final MutableTriple[] EMPTY_ARRAY = null; + + /** + * Returns the empty array singleton that can be assigned without compiler warning. + * + * @param the left element type + * @param the middle element type + * @param the right element type + * @return the empty array singleton that can be assigned without compiler warning. + * + * @since 3.10. + */ + @SuppressWarnings("unchecked") + public static MutableTriple[] emptyArray() { + return null; + } + + /** + *

Obtains a mutable triple of three objects inferring the generic types.

+ * + *

This factory allows the triple to be created using inference to + * obtain the generic types.

+ * + * @param the left element type + * @param the middle element type + * @param the right element type + * @param left the left element, may be null + * @param middle the middle element, may be null + * @param right the right element, may be null + * @return a triple formed from the three parameters, not null + */ + public static MutableTriple of(final L left, final M middle, final R right) { + return null; + } + /** Left object */ + public L left; + /** Middle object */ + public M middle; + + /** Right object */ + public R right; + + /** + * Create a new triple instance of three nulls. + */ + public MutableTriple() { + } + + /** + * Create a new triple instance. + * + * @param left the left value, may be null + * @param middle the middle value, may be null + * @param right the right value, may be null + */ + public MutableTriple(final L left, final M middle, final R right) { + this.left = null; + this.middle = null; + this.right = null; + } + + //----------------------------------------------------------------------- + /** + * {@inheritDoc} + */ + @Override + public L getLeft() { + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public M getMiddle() { + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public R getRight() { + return null; + } + + /** + * Sets the left element of the triple. + * + * @param left the new value of the left element, may be null + */ + public void setLeft(final L left) { + + } + + /** + * Sets the middle element of the triple. + * + * @param middle the new value of the middle element, may be null + */ + public void setMiddle(final M middle) { + + } + + /** + * Sets the right element of the triple. + * + * @param right the new value of the right element, may be null + */ + public void setRight(final R right) { + + } +} \ No newline at end of file diff --git a/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/tuple/Pair.java b/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/tuple/Pair.java new file mode 100644 index 00000000000..1f23f886e5b --- /dev/null +++ b/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/tuple/Pair.java @@ -0,0 +1,204 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.apache.commons.lang3.tuple; + +import java.io.Serializable; +import java.util.Map; + +/** + *

A pair consisting of two elements.

+ * + *

This class is an abstract implementation defining the basic API. + * It refers to the elements as 'left' and 'right'. It also implements the + * {@code Map.Entry} interface where the key is 'left' and the value is 'right'.

+ * + *

Subclass implementations may be mutable or immutable. + * However, there is no restriction on the type of the stored objects that may be stored. + * If mutable objects are stored in the pair, then the pair itself effectively becomes mutable.

+ * + * @param the left element type + * @param the right element type + * + * @since 3.0 + */ +public abstract class Pair implements Map.Entry, Comparable>, Serializable { + + /** Serialization version */ + private static final long serialVersionUID = 4954918890077093841L; + + /** + * An empty array. + *

+ * Consider using {@link #emptyArray()} to avoid generics warnings. + *

+ * + * @since 3.10. + */ + public static final Pair[] EMPTY_ARRAY = null; + + /** + * Returns the empty array singleton that can be assigned without compiler warning. + * + * @param the left element type + * @param the right element type + * @return the empty array singleton that can be assigned without compiler warning. + * + * @since 3.10. + */ + @SuppressWarnings("unchecked") + public static Pair[] emptyArray() { + return null; + } + + /** + *

Creates an immutable pair of two objects inferring the generic types.

+ * + *

This factory allows the pair to be created using inference to + * obtain the generic types.

+ * + * @param the left element type + * @param the right element type + * @param left the left element, may be null + * @param right the right element, may be null + * @return a pair formed from the two parameters, not null + */ + public static Pair of(final L left, final R right) { + return null; + } + + /** + *

Creates an immutable pair from an existing pair.

+ * + *

This factory allows the pair to be created using inference to + * obtain the generic types.

+ * + * @param the left element type + * @param the right element type + * @param pair the existing pair. + * @return a pair formed from the two parameters, not null + * @since 3.10 + */ + public static Pair of(final Map.Entry pair) { + return null; + } + + //----------------------------------------------------------------------- + /** + *

Compares the pair based on the left element followed by the right element. + * The types must be {@code Comparable}.

+ * + * @param other the other pair, not null + * @return negative if this is less, zero if equal, positive if greater + */ + @Override + public int compareTo(final Pair other) { + return 0; + } + + /** + *

Compares this pair to another based on the two elements.

+ * + * @param obj the object to compare to, null returns false + * @return true if the elements of the pair are equal + */ + @Override + public boolean equals(final Object obj) { + return false; + } + + /** + *

Gets the key from this pair.

+ * + *

This method implements the {@code Map.Entry} interface returning the + * left element as the key.

+ * + * @return the left element as the key, may be null + */ + @Override + public final L getKey() { + return null; + } + + //----------------------------------------------------------------------- + /** + *

Gets the left element from this pair.

+ * + *

When treated as a key-value pair, this is the key.

+ * + * @return the left element, may be null + */ + public abstract L getLeft(); + + /** + *

Gets the right element from this pair.

+ * + *

When treated as a key-value pair, this is the value.

+ * + * @return the right element, may be null + */ + public abstract R getRight(); + + /** + *

Gets the value from this pair.

+ * + *

This method implements the {@code Map.Entry} interface returning the + * right element as the value.

+ * + * @return the right element as the value, may be null + */ + @Override + public R getValue() { + return null; + } + + /** + *

Returns a suitable hash code. + * The hash code follows the definition in {@code Map.Entry}.

+ * + * @return the hash code + */ + @Override + public int hashCode() { + return 0; + } + + /** + *

Returns a String representation of this pair using the format {@code ($left,$right)}.

+ * + * @return a string describing this object, not null + */ + @Override + public String toString() { + return ""; + } + + /** + *

Formats the receiver using the given format.

+ * + *

This uses {@link java.util.Formattable} to perform the formatting. Two variables may + * be used to embed the left and right elements. Use {@code %1$s} for the left + * element (key) and {@code %2$s} for the right element (value). + * The default format used by {@code toString()} is {@code (%1$s,%2$s)}.

+ * + * @param format the format string, optionally containing {@code %1$s} and {@code %2$s}, not null + * @return the formatted string, not null + */ + public String toString(final String format) { + return ""; + } + +} \ No newline at end of file diff --git a/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/tuple/Triple.java b/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/tuple/Triple.java new file mode 100644 index 00000000000..d8453f7e3cd --- /dev/null +++ b/java/ql/test/stubs/apache-commons-lang3-3.7/org/apache/commons/lang3/tuple/Triple.java @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.apache.commons.lang3.tuple; + +import java.io.Serializable; + +/** + *

A triple consisting of three elements.

+ * + *

This class is an abstract implementation defining the basic API. + * It refers to the elements as 'left', 'middle' and 'right'.

+ * + *

Subclass implementations may be mutable or immutable. + * However, there is no restriction on the type of the stored objects that may be stored. + * If mutable objects are stored in the triple, then the triple itself effectively becomes mutable.

+ * + * @param the left element type + * @param the middle element type + * @param the right element type + * + * @since 3.2 + */ +public abstract class Triple implements Comparable>, Serializable { + + /** + * An empty array. + *

+ * Consider using {@link #emptyArray()} to avoid generics warnings. + *

+ * + * @since 3.10. + */ + public static final Triple[] EMPTY_ARRAY = null; + + /** + * Returns the empty array singleton that can be assigned without compiler warning. + * + * @param the left element type + * @param the middle element type + * @param the right element type + * @return the empty array singleton that can be assigned without compiler warning. + * + * @since 3.10. + */ + @SuppressWarnings("unchecked") + public static Triple[] emptyArray() { + return null; + } + + /** + *

Obtains an immutable triple of three objects inferring the generic types.

+ * + *

This factory allows the triple to be created using inference to + * obtain the generic types.

+ * + * @param the left element type + * @param the middle element type + * @param the right element type + * @param left the left element, may be null + * @param middle the middle element, may be null + * @param right the right element, may be null + * @return a triple formed from the three parameters, not null + */ + public static Triple of(final L left, final M middle, final R right) { + return null; + } + + //----------------------------------------------------------------------- + /** + *

Compares the triple based on the left element, followed by the middle element, + * finally the right element. + * The types must be {@code Comparable}.

+ * + * @param other the other triple, not null + * @return negative if this is less, zero if equal, positive if greater + */ + @Override + public int compareTo(final Triple other) { + return 0; + } + + /** + *

Compares this triple to another based on the three elements.

+ * + * @param obj the object to compare to, null returns false + * @return true if the elements of the triple are equal + */ + @Override + public boolean equals(final Object obj) { + return false; + } + + //----------------------------------------------------------------------- + /** + *

Gets the left element from this triple.

+ * + * @return the left element, may be null + */ + public abstract L getLeft(); + + /** + *

Gets the middle element from this triple.

+ * + * @return the middle element, may be null + */ + public abstract M getMiddle(); + + /** + *

Gets the right element from this triple.

+ * + * @return the right element, may be null + */ + public abstract R getRight(); + + /** + *

Returns a suitable hash code.

+ * + * @return the hash code + */ + @Override + public int hashCode() { + return 0; + } + + /** + *

Returns a String representation of this triple using the format {@code ($left,$middle,$right)}.

+ * + * @return a string describing this object, not null + */ + @Override + public String toString() { + return ""; + } + + /** + *

Formats the receiver using the given format.

+ * + *

This uses {@link java.util.Formattable} to perform the formatting. Three variables may + * be used to embed the left and right elements. Use {@code %1$s} for the left + * element, {@code %2$s} for the middle and {@code %3$s} for the right element. + * The default format used by {@code toString()} is {@code (%1$s,%2$s,%3$s)}.

+ * + * @param format the format string, optionally containing {@code %1$s}, {@code %2$s} and {@code %3$s}, not null + * @return the formatted string, not null + */ + public String toString(final String format) { + return ""; + } + +}