/*
* Copyright 2009-2012 Michael Dalton
*
* 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
*
* 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 jtaint;
import java.util.BitSet;
public class RegexTest
{
private static void verify(String s, String data, BitSet b) {
if (!s.equals(data))
throw new RuntimeException("Unexpected data : " +
"got " + s + " expected " + data);
Taint t = s.@internal@taint();
if (t == null)
t = new Taint(false, s.length());
if (!b.equals(t.asBitSet()))
throw new RuntimeException("Unexpected taint: " +
"got " + s.@internal@taint() + " expected " + b);
}
/** Test string regex replacement methods. Any characters in the
* string not matched by the regular expression should retain their
* prior taint values. Any substrings matched by the regular expression
* in the replace method call should have their taint cleared.
*/
private static void testReplace() {
String t1 = new String("abcdefabcdefgh");
t1 = new String(t1, new Taint(true, t1.length()));
String p1 = new String("ijklmnop");
BitSet b = new BitSet();
b.set(1); b.set(3); b.set(5); b.set(7);
p1 = new String(p1, new Taint(b, p1.length()));
/* Simple replacement tests */
b = new BitSet();
b.set(0); b.set(4); b.set(5); b.set(6); b.set(7);
b.set(8); b.set(9); b.set(10); b.set(11); b.set(12); b.set(13);
verify(t1.replaceFirst("bcd", "def"), "adefefabcdefgh", b);
b = new BitSet();
b.set(0); b.set(1); b.set(2); b.set(3); b.set(4); b.set(5);
b.set(6); b.set(7); b.set(8); b.set(9); b.set(10); b.set(11);
verify(t1.replaceFirst("gh", "moo"), "abcdefabcdefmoo", b);
b = new BitSet();
b.set(3); b.set(4); b.set(5); b.set(6); b.set(7); b.set(8);
b.set(9); b.set(10); b.set(11); b.set(12); b.set(13);
verify(t1.replaceFirst("abc", "xyz"), "xyzdefabcdefgh", b);
/* Partial taint replacement test */
b = new BitSet();
b.set(5); b.set(7);
verify(p1.replaceFirst("jkl", "123"), "i123mnop", b);
/* Simple replaceAll */
b = new BitSet();
b.set(3); b.set(4); b.set(5); b.set(9); b.set(10); b.set(11);
b.set(12); b.set(13);
verify(t1.replaceAll("abc", "123"), "123def123defgh", b);
b = new BitSet();
b.set(1); b.set(3); b.set(10);
verify(p1.replaceAll("mno", "minnow"), "ijklminnowp", b);
/* More complex queries */
b = new BitSet();
b.set(0, t1.length());
verify(t1.replaceFirst("^def", "blah"), "abcdefabcdefgh", b);
b = new BitSet();
b.set(3); b.set(4); b.set(5); b.set(6); b.set(7); b.set(8);
b.set(9); b.set(10); b.set(11); b.set(12); b.set(13);
verify(t1.replaceAll("^abc", "moo"), "moodefabcdefgh", b);
b = new BitSet();
b.set(3); b.set(4); b.set(5); b.set(9); b.set(10); b.set(11);
b.set(12); b.set(13);
verify(t1.replaceAll("[a-c]+", "XXX"), "XXXdefXXXdefgh", b);
}
/** Test String split methods. Each non-empty substring should have the
* same taint values as in the original (non-split) String
*/
private static void testSplit() {
String t1 = new String("abc:def:abc:def:gh");
t1 = new String(t1, new Taint(true, t1.length()));
String p1 = new String("i:j:k:lmno:p:");
BitSet b = new BitSet();
b.set(1); b.set(2); b.set(3); b.set(4); b.set(7); b.set(11);
p1 = new String(p1, new Taint(b, p1.length()));
String[] r = t1.split(":");
/* Simple split test */
b = new BitSet();
b.set(0, 3);
if (r.length != 5)
throw new RuntimeException("Unexpected split() array " + r);
verify(r[0], "abc", b);
verify(r[1], "def", b);
verify(r[2], "abc", b);
verify(r[3], "def", b);
b.clear(2);
verify(r[4], "gh", b);
/* Partial taint split test */
r = p1.split(":");
b = new BitSet();
if (r.length != 5)
throw new RuntimeException("Unexpected split() array " + r);
verify(r[0], "i", b);
b.set(0);
verify(r[1], "j", b);
verify(r[2], "k", b);
b.clear(0);
b.set(1);
verify(r[3], "lmno", b);
b.clear(1);
b.set(0);
verify(r[4], "p", b);
/* Partial taint split test - positive limit */
r = p1.split(":", 3);
b = new BitSet();
if (r.length != 3)
throw new RuntimeException("Unexpected split() array " + r);
verify(r[0], "i", b);
b.set(0);
verify(r[1], "j", b);
b.set(3); b.set(7);
verify(r[2], "k:lmno:p:", b);
/* Partial taint split test - negative limit */
r = p1.split(":", -3);
b = new BitSet();
if (r.length != 6)
throw new RuntimeException("Unexpected split() array " + r);
verify(r[0], "i", b);
b.set(0);
verify(r[1], "j", b);
verify(r[2], "k", b);
b.clear(0);
b.set(1);
verify(r[3], "lmno", b);
b.clear(1);
b.set(0);
verify(r[4], "p", b);
b.clear(0);
verify(r[5], "", b);
}
public static void main(String[] args) {
testReplace();
testSplit();
if (Log.hasError() || Log.hasWarning() || Log.hasVuln()) {
System.out.println("Error or Warning encountered -- check logs");
System.exit(-1);
}
}
}