/* * 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 jtaint.Taint; import java.util.BitSet; public class SafeTaint implements Cloneable { boolean[] b; public Object clone() { SafeTaint st; try { st = (SafeTaint) super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException("JDK Clone Failure"); } st.b = (boolean[]) b.clone(); return st; } public SafeTaint() { b = new boolean[0]; } public SafeTaint(BitSet bs, int len) { b = new boolean[len]; if (bs == null) return; for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) b[i] = true; } public SafeTaint(boolean fill, int len) { b = new boolean[len]; for (int i = 0; i < len; i++) b[i] = fill; } public SafeTaint(boolean[] b) { this.b = (boolean[]) b.clone(); } public SafeTaint(char[] t, int len) { this.b = new boolean[len]; for (int i = 0; i < t.length; i++) for (int j = 0; j < 16; j++) if ((t[i] & (1 << j)) != 0) b[16 * i + j] = true; } public SafeTaint setLength(int newLength) throws IllegalArgumentException { boolean[] newb; if (newLength < 0) throw new IllegalArgumentException("invalid index"); newb = new boolean[newLength]; for (int i = 0; i < b.length && i < newb.length; i++) newb[i] = b[i]; b = newb; return this; } public SafeTaint set(int index) throws IllegalArgumentException { if (index < 0 || index >= b.length) throw new IllegalArgumentException("invalid index"); b[index] = true; return this; } public SafeTaint set(int fromIndex, int toIndex) throws IllegalArgumentException { if (fromIndex > toIndex || toIndex >= b.length || (fromIndex|toIndex) < 0) throw new IllegalArgumentException("invalid index"); for (int i = fromIndex; i < toIndex; i++) b[i] = true; return this; } public SafeTaint clear(int index) throws IllegalArgumentException { if (index < 0 || index >= b.length) throw new IllegalArgumentException("invalid index"); b[index] = false; return this; } public SafeTaint clear(int fromIndex, int toIndex) throws IllegalArgumentException { if (fromIndex > toIndex || toIndex >= b.length || (fromIndex|toIndex) < 0) throw new IllegalArgumentException("invalid index"); for (int i = fromIndex; i < toIndex; i++) b[i] = false; return this; } public boolean get(int index) throws IllegalArgumentException { if (index < 0 || index >= b.length) throw new IllegalArgumentException("invalid index"); return b[index]; } public SafeTaint subset(int beginIndex, int endIndex) throws IllegalArgumentException { boolean[] newb; if (beginIndex > endIndex || endIndex > b.length || (beginIndex|endIndex) < 0) throw new IllegalArgumentException("invalid index"); newb = new boolean[endIndex - beginIndex]; for (int i = beginIndex; i < endIndex; i++) newb[i - beginIndex] = b[i]; b = newb; return this; } public SafeTaint delete(int beginIndex, int endIndex) throws IllegalArgumentException { boolean[] newb; int remlen; if (beginIndex < 0 || beginIndex > endIndex || beginIndex > b.length) throw new IllegalArgumentException("invalid index"); if (endIndex > b.length) endIndex = b.length; remlen = endIndex - beginIndex; newb = new boolean[b.length - remlen]; for (int i = 0; i < beginIndex; i++) newb[i] = b[i]; for (int i = endIndex; i < b.length; i++) newb[i - remlen] = b[i]; b = newb; return this; } public SafeTaint append(SafeTaint st) { boolean[] newb = new boolean[b.length + st.b.length]; for (int i = 0; i < b.length; i++) newb[i] = b[i]; for (int i = 0; i < st.b.length; i++) newb[i + b.length] = st.b[i]; b = newb; return this; } public SafeTaint insert(int offset, SafeTaint st) throws IllegalArgumentException { boolean[] newb = new boolean[b.length + st.b.length]; if (offset < 0 || offset > b.length) throw new IllegalArgumentException("invalid offset"); for (int i = 0; i < offset; i++) newb[i] = b[i]; for (int i = 0; i < st.b.length; i++) newb[offset + i] = st.b[i]; for (int i = offset; i < b.length; i++) newb[i + st.b.length] = b[i]; b = newb; return this; } public SafeTaint reverse() { boolean[] newb = new boolean[b.length]; for (int i = 0, j = b.length-1; i < b.length; i++, j--) newb[j] = b[i]; b = newb; return this; } public boolean isTainted() { boolean tainted = false; for (int i = 0; i < b.length; i++) if (b[i]) tainted = true; return tainted; } public int cardinality() { int c = 0; for (int i = 0; i < b.length; i++) if (b[i]) c++; return c; } public BitSet asBitSet() { BitSet bs = new BitSet(); for (int i = 0; i < b.length; i++) bs.set(i, b[i]); return bs; } public int length() { return b.length; } public void getTaintAsChars(char[] dst, int dstBegin) { for (int i = 0; i < b.length; i++) if (b[i]) dst[dstBegin + i/16] |= (1 << (i & 15)); } private String printTaint() { String s = "{ "; for (int i = 0; i < b.length; i++) { if (b[i]) s += i + " "; } s += "}"; return s; } public String toString() { return "[tainted: " + isTainted() +" ]" + "[length: " + b.length + "] " + printTaint(); } public boolean verify(Taint t) throws IllegalArgumentException { boolean caught = false; if (t == null) return !isTainted(); if (t.length() != b.length) { System.out.println("t length " + t.length() + " st length " + b.length); return false; } for (int i = 0; i < b.length; i++) { if (b[i] != t.get(i)) { System.out.println("t[ " + i +"] = " + t.get(i) + " st[ " + i + "] = " + b[i]); return false; } } try { t.get(b.length); } catch (IllegalArgumentException e) { return true; } System.out.println("Failed to catch exception at offset " + b.length); return false; } }