Add models for WordUtils and StrTokenizer

Both of these have commons-text and commons-lang variants.
This commit is contained in:
Chris Smowton
2021-02-17 09:33:10 +00:00
parent fe07630e40
commit 1580d23b2b
10 changed files with 429 additions and 0 deletions

View File

@@ -211,3 +211,58 @@ private class ApacheStrBuilderTaintWriter extends ApacheStrBuilderCallable, Tain
toArg = 2
}
}
private class ApacheWordUtilsTaintPreservingMethod extends TaintPreservingCallable {
ApacheWordUtilsTaintPreservingMethod() {
this.getDeclaringType()
.hasQualifiedName(["org.apache.commons.lang3.text", "org.apache.commons.text"], "WordUtils") and
this.getReturnType() instanceof TypeString
}
override predicate returnsTaintFrom(int arg) {
this.getParameterType(arg) instanceof TypeString and
arg != 4 // Exclude the wrapOn parameter from `wrap(String, int, String, boolean, String)`
}
}
private class ApacheStrTokenizer extends RefType {
ApacheStrTokenizer() {
this.hasQualifiedName(["org.apache.commons.lang3.text", "org.apache.commons.text"],
"StrTokenizer") or
this.hasQualifiedName("org.apache.commons.text", "StringTokenizer")
}
}
/**
* A callable that sets the string to be tokenized by an Apache Commons `Str[ing]Tokenizer`.
*
* Note `reset` is an instance method that taints an existing instance; all others return a fresh instance.
*/
private class ApacheStrTokenizerTaintingMethod extends TaintPreservingCallable {
ApacheStrTokenizerTaintingMethod() {
this.getDeclaringType() instanceof ApacheStrTokenizer and
(
this instanceof Constructor or
this.getName() in ["getCSVInstance", "getTSVInstance", "reset"]
)
}
override predicate returnsTaintFrom(int arg) { arg = 0 }
override predicate transfersTaint(int fromArg, int toArg) {
this.getName() = "reset" and
returnsTaintFrom(fromArg) and
toArg = -1
}
}
private class ApacheStrTokenizerTaintGetter extends TaintPreservingCallable {
ApacheStrTokenizerTaintGetter() {
this.getDeclaringType() instanceof ApacheStrTokenizer and
this.getName() in [
"getContent", "getTokenArray", "getTokenList", "nextToken", "previousToken", "toString"
]
}
override predicate returnsTaintFrom(int arg) { arg = -1 }
}

View File

@@ -0,0 +1,46 @@
import org.apache.commons.lang3.text.StrTokenizer;
import org.apache.commons.lang3.text.StrMatcher;
public class StrTokenizerTest {
String taint() { return "tainted"; }
void sink(Object o) {}
void test() throws Exception {
// Test constructors:
sink((new StrTokenizer(taint().toCharArray())).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint().toCharArray(), ',')).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint().toCharArray(), ',', '"')).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint().toCharArray(), ",")).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint().toCharArray(), (StrMatcher)null)).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint().toCharArray(), (StrMatcher)null, (StrMatcher)null)).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint())).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint(), ',')).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint(), ',', '"')).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint(), ",")).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint(), (StrMatcher)null)).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint(), (StrMatcher)null, (StrMatcher)null)).toString()); // $hasTaintFlow=y
// Test constructing static methods:
sink(StrTokenizer.getCSVInstance(taint().toCharArray()).toString()); // $hasTaintFlow=y
sink(StrTokenizer.getCSVInstance(taint()).toString()); // $hasTaintFlow=y
sink(StrTokenizer.getTSVInstance(taint().toCharArray()).toString()); // $hasTaintFlow=y
sink(StrTokenizer.getTSVInstance(taint()).toString()); // $hasTaintFlow=y
// Test accessors:
sink((new StrTokenizer(taint())).clone()); // $hasTaintFlow=y
sink((new StrTokenizer(taint())).getContent()); // $hasTaintFlow=y
sink((new StrTokenizer(taint())).getTokenArray()); // $hasTaintFlow=y
sink((new StrTokenizer(taint())).getTokenList()); // $hasTaintFlow=y
sink((new StrTokenizer(taint())).next()); // $hasTaintFlow=y
sink((new StrTokenizer(taint())).nextToken()); // $hasTaintFlow=y
sink((new StrTokenizer(taint())).previous()); // $hasTaintFlow=y
sink((new StrTokenizer(taint())).previousToken()); // $hasTaintFlow=y
// Test mutators:
sink((new StrTokenizer()).reset(taint().toCharArray()).toString()); // $hasTaintFlow=y
sink((new StrTokenizer()).reset(taint()).toString()); // $hasTaintFlow=y
}
}

View File

@@ -0,0 +1,46 @@
import org.apache.commons.text.StrTokenizer;
import org.apache.commons.text.StrMatcher;
public class StrTokenizerTextTest {
String taint() { return "tainted"; }
void sink(Object o) {}
void test() throws Exception {
// Test constructors:
sink((new StrTokenizer(taint().toCharArray())).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint().toCharArray(), ',')).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint().toCharArray(), ',', '"')).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint().toCharArray(), ",")).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint().toCharArray(), (StrMatcher)null)).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint().toCharArray(), (StrMatcher)null, (StrMatcher)null)).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint())).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint(), ',')).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint(), ',', '"')).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint(), ",")).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint(), (StrMatcher)null)).toString()); // $hasTaintFlow=y
sink((new StrTokenizer(taint(), (StrMatcher)null, (StrMatcher)null)).toString()); // $hasTaintFlow=y
// Test constructing static methods:
sink(StrTokenizer.getCSVInstance(taint().toCharArray()).toString()); // $hasTaintFlow=y
sink(StrTokenizer.getCSVInstance(taint()).toString()); // $hasTaintFlow=y
sink(StrTokenizer.getTSVInstance(taint().toCharArray()).toString()); // $hasTaintFlow=y
sink(StrTokenizer.getTSVInstance(taint()).toString()); // $hasTaintFlow=y
// Test accessors:
sink((new StrTokenizer(taint())).clone()); // $hasTaintFlow=y
sink((new StrTokenizer(taint())).getContent()); // $hasTaintFlow=y
sink((new StrTokenizer(taint())).getTokenArray()); // $hasTaintFlow=y
sink((new StrTokenizer(taint())).getTokenList()); // $hasTaintFlow=y
sink((new StrTokenizer(taint())).next()); // $hasTaintFlow=y
sink((new StrTokenizer(taint())).nextToken()); // $hasTaintFlow=y
sink((new StrTokenizer(taint())).previous()); // $hasTaintFlow=y
sink((new StrTokenizer(taint())).previousToken()); // $hasTaintFlow=y
// Test mutators:
sink((new StrTokenizer()).reset(taint().toCharArray()).toString()); // $hasTaintFlow=y
sink((new StrTokenizer()).reset(taint()).toString()); // $hasTaintFlow=y
}
}

View File

@@ -0,0 +1,46 @@
import org.apache.commons.text.StringTokenizer;
import org.apache.commons.text.matcher.StringMatcher;
public class StringTokenizerTest {
String taint() { return "tainted"; }
void sink(Object o) {}
void test() throws Exception {
// Test constructors:
sink((new StringTokenizer(taint().toCharArray())).toString()); // $hasTaintFlow=y
sink((new StringTokenizer(taint().toCharArray(), ',')).toString()); // $hasTaintFlow=y
sink((new StringTokenizer(taint().toCharArray(), ',', '"')).toString()); // $hasTaintFlow=y
sink((new StringTokenizer(taint().toCharArray(), ",")).toString()); // $hasTaintFlow=y
sink((new StringTokenizer(taint().toCharArray(), (StringMatcher)null)).toString()); // $hasTaintFlow=y
sink((new StringTokenizer(taint().toCharArray(), (StringMatcher)null, (StringMatcher)null)).toString()); // $hasTaintFlow=y
sink((new StringTokenizer(taint())).toString()); // $hasTaintFlow=y
sink((new StringTokenizer(taint(), ',')).toString()); // $hasTaintFlow=y
sink((new StringTokenizer(taint(), ',', '"')).toString()); // $hasTaintFlow=y
sink((new StringTokenizer(taint(), ",")).toString()); // $hasTaintFlow=y
sink((new StringTokenizer(taint(), (StringMatcher)null)).toString()); // $hasTaintFlow=y
sink((new StringTokenizer(taint(), (StringMatcher)null, (StringMatcher)null)).toString()); // $hasTaintFlow=y
// Test constructing static methods:
sink(StringTokenizer.getCSVInstance(taint().toCharArray()).toString()); // $hasTaintFlow=y
sink(StringTokenizer.getCSVInstance(taint()).toString()); // $hasTaintFlow=y
sink(StringTokenizer.getTSVInstance(taint().toCharArray()).toString()); // $hasTaintFlow=y
sink(StringTokenizer.getTSVInstance(taint()).toString()); // $hasTaintFlow=y
// Test accessors:
sink((new StringTokenizer(taint())).clone()); // $hasTaintFlow=y
sink((new StringTokenizer(taint())).getContent()); // $hasTaintFlow=y
sink((new StringTokenizer(taint())).getTokenArray()); // $hasTaintFlow=y
sink((new StringTokenizer(taint())).getTokenList()); // $hasTaintFlow=y
sink((new StringTokenizer(taint())).next()); // $hasTaintFlow=y
sink((new StringTokenizer(taint())).nextToken()); // $hasTaintFlow=y
sink((new StringTokenizer(taint())).previous()); // $hasTaintFlow=y
sink((new StringTokenizer(taint())).previousToken()); // $hasTaintFlow=y
// Test mutators:
sink((new StringTokenizer()).reset(taint().toCharArray()).toString()); // $hasTaintFlow=y
sink((new StringTokenizer()).reset(taint()).toString()); // $hasTaintFlow=y
}
}

View File

@@ -0,0 +1,26 @@
import org.apache.commons.lang3.text.WordUtils;
public class WordUtilsTest {
String taint() { return "tainted"; }
void sink(Object o) {}
void test() throws Exception {
sink(WordUtils.capitalize(taint())); // $hasTaintFlow=y
sink(WordUtils.capitalize(taint(), ' ', ',')); // $hasTaintFlow=y
sink(WordUtils.capitalizeFully(taint())); // $hasTaintFlow=y
sink(WordUtils.capitalizeFully(taint(), ' ', ',')); // $hasTaintFlow=y
sink(WordUtils.initials(taint())); // $hasTaintFlow=y
sink(WordUtils.initials(taint(), ' ', ',')); // $hasTaintFlow=y
sink(WordUtils.swapCase(taint())); // $hasTaintFlow=y
sink(WordUtils.uncapitalize(taint())); // $hasTaintFlow=y
sink(WordUtils.uncapitalize(taint(), ' ', ',')); // $hasTaintFlow=y
sink(WordUtils.wrap(taint(), 0)); // $hasTaintFlow=y
sink(WordUtils.wrap(taint(), 0, "\n", false)); // $hasTaintFlow=y
sink(WordUtils.wrap("wrap me", 0, taint(), false)); // $hasTaintFlow=y
sink(WordUtils.wrap(taint(), 0, "\n", false, "\n")); // $hasTaintFlow=y
sink(WordUtils.wrap("wrap me", 0, taint(), false, "\n")); // $hasTaintFlow=y
// GOOD: the wrap-on line terminator does not propagate to the return value
sink(WordUtils.wrap("wrap me", 0, "\n", false, taint()));
}
}

View File

@@ -0,0 +1,28 @@
import org.apache.commons.text.WordUtils;
public class WordUtilsTextTest {
String taint() { return "tainted"; }
void sink(Object o) {}
void test() throws Exception {
sink(WordUtils.abbreviate(taint(), 0, 0, "append me")); // $hasTaintFlow=y
sink(WordUtils.abbreviate("abbreviate me", 0, 0, taint())); // $hasTaintFlow=y
sink(WordUtils.capitalize(taint())); // $hasTaintFlow=y
sink(WordUtils.capitalize(taint(), ' ', ',')); // $hasTaintFlow=y
sink(WordUtils.capitalizeFully(taint())); // $hasTaintFlow=y
sink(WordUtils.capitalizeFully(taint(), ' ', ',')); // $hasTaintFlow=y
sink(WordUtils.initials(taint())); // $hasTaintFlow=y
sink(WordUtils.initials(taint(), ' ', ',')); // $hasTaintFlow=y
sink(WordUtils.swapCase(taint())); // $hasTaintFlow=y
sink(WordUtils.uncapitalize(taint())); // $hasTaintFlow=y
sink(WordUtils.uncapitalize(taint(), ' ', ',')); // $hasTaintFlow=y
sink(WordUtils.wrap(taint(), 0)); // $hasTaintFlow=y
sink(WordUtils.wrap(taint(), 0, "\n", false)); // $hasTaintFlow=y
sink(WordUtils.wrap("wrap me", 0, taint(), false)); // $hasTaintFlow=y
sink(WordUtils.wrap(taint(), 0, "\n", false, "\n")); // $hasTaintFlow=y
sink(WordUtils.wrap("wrap me", 0, taint(), false, "\n")); // $hasTaintFlow=y
// GOOD: the wrap-on line terminator does not propagate to the return value
sink(WordUtils.wrap("wrap me", 0, "\n", false, taint()));
}
}

View File

@@ -17,6 +17,7 @@
package org.apache.commons.lang3.text;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;

View File

@@ -0,0 +1,79 @@
/*
* 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.text;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class WordUtils {
public WordUtils() {
}
public static String wrap(final String str, final int wrapLength) {
return null;
}
public static String wrap(final String str, final int wrapLength, final String newLineStr, final boolean wrapLongWords) {
return null;
}
public static String wrap(final String str, int wrapLength, String newLineStr, final boolean wrapLongWords, String wrapOn) {
return null;
}
public static String capitalize(final String str) {
return null;
}
public static String capitalize(final String str, final char... delimiters) {
return null;
}
public static String capitalizeFully(final String str) {
return null;
}
public static String capitalizeFully(String str, final char... delimiters) {
return null;
}
public static String uncapitalize(final String str) {
return null;
}
public static String uncapitalize(final String str, final char... delimiters) {
return null;
}
public static String swapCase(final String str) {
return null;
}
public static String initials(final String str) {
return null;
}
public static String initials(final String str, final char... delimiters) {
return null;
}
public static boolean containsAllWords(final CharSequence word, final CharSequence... words) {
return false;
}
}

View File

@@ -16,8 +16,12 @@
*/
package org.apache.commons.text;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
public class StrTokenizer implements ListIterator<String>, Cloneable {
public static StrTokenizer getCSVInstance() {

View File

@@ -0,0 +1,98 @@
/*
* 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.text;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class WordUtils {
public WordUtils() {
}
public static String wrap(final String str, final int wrapLength) {
return null;
}
public static String wrap(final String str,
final int wrapLength,
final String newLineStr,
final boolean wrapLongWords) {
return null;
}
public static String wrap(final String str,
int wrapLength,
String newLineStr,
final boolean wrapLongWords,
String wrapOn) {
return null;
}
public static String capitalize(final String str) {
return null;
}
public static String capitalize(final String str, final char... delimiters) {
return null;
}
public static String capitalizeFully(final String str) {
return null;
}
public static String capitalizeFully(String str, final char... delimiters) {
return null;
}
public static String uncapitalize(final String str) {
return null;
}
public static String uncapitalize(final String str, final char... delimiters) {
return null;
}
public static String swapCase(final String str) {
return null;
}
public static String initials(final String str) {
return null;
}
public static String initials(final String str, final char... delimiters) {
return null;
}
public static boolean containsAllWords(final CharSequence word, final CharSequence... words) {
return false;
}
public static boolean isDelimiter(final char ch, final char[] delimiters) {
return false;
}
public static boolean isDelimiter(final int codePoint, final char[] delimiters) {
return false;
}
public static String abbreviate(final String str, int lower, int upper, final String appendToEnd) {
return null;
}
}