Files
codeql/java/ql/test/library-tests/dataflow/taint/B.java
2023-01-12 16:24:57 -05:00

221 lines
6.2 KiB
Java

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.util.StringTokenizer;
public class B {
public static String[] taint() { return new String[] { "tainted" }; }
public static void sink(Object o) { }
public static void maintest() throws java.io.UnsupportedEncodingException, java.net.MalformedURLException, java.io.IOException {
String[] args = taint();
// tainted - access to main args
String[] aaaargs = args;
sink(aaaargs);
// tainted - access to tainted array
String s = args[0];
sink(s);
// tainted - concatenation of tainted string
String concat = "Look at me " + s + ", I'm tainted!";
sink(concat);
// tainted - parenthesised
String pars = (concat);
sink(pars);
// tainted method argument, implies tainted return value
String method = tainty(pars);
sink(method);
// tainted - complex
String complex = ("Look at me " + args[0]) + ", I'm tainted!";
sink(complex);
// tainted - data preserving constructors
String constructed = new String(complex);
sink(constructed);
// tainted - data preserving method
String valueOf = String.valueOf(complex.toCharArray());
sink(valueOf);
// tainted - data preserving method
String valueOfSubstring = String.valueOf(complex.toCharArray(), 0, 1);
sink(valueOfSubstring);
// tainted - unsafe escape
String badEscape = constructed.replaceAll("irrelevant", "irrelevant");
sink(badEscape);
// tainted - tokenized string
String token = new StringTokenizer(badEscape).nextToken();
sink(token);
// tainted - fluent concatenation
String fluentConcat = "".concat("str").concat(token).concat("bar");
sink(fluentConcat);
// not tainted
String safe = notTainty(complex);
sink(safe);
String shouldBeFine = taintyOtherArg(safe, complex);
sink(shouldBeFine);
// non-whitelisted constructors don't pass taint
StringWrapper herring = new StringWrapper(complex);
sink(herring);
// toString does not pass taint yet
String valueOfObject = String.valueOf(args);
sink(valueOfObject);
// tainted equality check with constant
boolean cond = "foo" == s;
sink(cond);
// tainted logic with tainted operand
boolean logic = cond && safe();
sink(logic);
// tainted
logic = safe() || cond;
sink(logic);
// tainted, use of equals
logic = badEscape.equals("constant");
sink(logic);
// not tainted
boolean okay = s == shouldBeFine;
sink(okay);
// methods on string that pass on taint
String trimmed = s.trim();
sink(trimmed);
String[] split = s.split(" ");
sink(split);
String lower = s.toLowerCase();
sink(lower);
String upper = s.toUpperCase();
sink(upper);
byte[] bytes = s.getBytes("UTF-8");
sink(bytes);
String toString = s.toString();
sink(toString);
String subs = s.substring(1, 10);
sink(subs);
String repl = "some constant".replace(" ", s);
sink(repl);
String replAll = "some constant".replaceAll(" ", s);
sink(replAll);
String replFirst = "some constant".replaceFirst(" ", s);
sink(replFirst);
char[] chars = new char[10];
s.getChars(0, 1, chars, 0);
sink(chars);
String translated = s.translateEscapes();
sink(translated);
ByteArrayOutputStream baos = null;
ObjectOutput oos = null;
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try
{
// serialization of tainted string
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(s);
byte[] serializedData = baos.toByteArray(); // tainted
sink(serializedData);
// serialization of fixed string
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject("not tainted");
byte[] serializedData2 = baos.toByteArray(); // *not* tainted
sink(serializedData2);
// de-serialization of tainted string
bais = new ByteArrayInputStream(serializedData);
ois = new ObjectInputStream(bais);
String deserializedData = (String)ois.readObject(); // tainted
sink(deserializedData);
} catch (IOException e) {
// ignored in test code
} catch (ClassNotFoundException e) {
// ignored in test code
}
// tainted array initializers
String[] taintedArray = new String[] { s };
sink(taintedArray);
String[][] taintedArray2 = new String[][] { { s } };
sink(taintedArray2);
String[][][] taintedArray3 = new String[][][] { { { s } } };
sink(taintedArray3);
// Tainted file path and URI
sink(new java.io.File(s).toURI().toURL());
// Tainted file to Path
sink(new java.io.File(s).toPath());
// Tainted File to Path to File
sink(new java.io.File(s).toPath().toFile());
// Tainted file to absolute file
sink(new java.io.File(s).getAbsoluteFile());
// Tainted file to canonical file
sink(new java.io.File(s).getCanonicalFile());
return;
}
public static String tainty(String arg) {
// tainted return value
return arg;
}
public static String taintyOtherArg(String safe, String tainted) {
return safe;
}
public static String notTainty(String arg) {
return "foo";
}
public static class StringWrapper {
public String wrapped;
public StringWrapper(String s) {
this.wrapped = s;
}
}
public static boolean safe() {
return true;
}
public static void extendedTests(){
String s = taint()[0];
String replReceiver = s.replace("irrelevant", "irrelevant");
sink(replReceiver);
String replChar = "a".replace('a', s.charAt(0));
sink(replChar);
String replCharReceiver = s.replace('a', 'b');
sink(replCharReceiver);
String charAt = "";
for(int i = 0; i < 10; i++)
charAt = charAt + s.charAt(i);
sink(charAt);
byte[] bytes = new byte[10];
s.getBytes(0, 1, bytes, 0);
sink(bytes);
String replAll = s.replaceAll("irrelevant", "irrelevant");
sink(replAll);
String replFirst = s.replaceFirst("irrelevant", "irrelevant");
sink(replFirst);
}
}