blob: ffa82b7da1347a485ba83e005f94598bc1c3207c [file] [log] [blame]
import java.util.ArrayList;
import java.util.List;
import org.checkerframework.checker.tainting.qual.PolyTainted;
import org.checkerframework.checker.tainting.qual.Tainted;
import org.checkerframework.checker.tainting.qual.Untainted;
import org.checkerframework.framework.qual.HasQualifierParameter;
public class HasQualParamDefaults {
@HasQualifierParameter(Tainted.class)
public class Buffer {
final List<@PolyTainted String> list = new ArrayList<>();
@PolyTainted String someString = "";
public Buffer() {}
public @Untainted Buffer(@Tainted String s) {
// :: error: (assignment)
this.someString = s;
}
public Buffer(Buffer copy) {
this.list.addAll(copy.list);
this.someString = copy.someString;
}
public Buffer append(@PolyTainted String s) {
list.add(s);
someString = s;
return this;
}
public @PolyTainted String prettyPrint() {
String prettyString = list.get(1);
for (@PolyTainted String s : list) {
prettyString += s + " ~~ ";
}
return prettyString;
}
public @PolyTainted String unTaintedOnly(@Untainted Buffer this, @PolyTainted String s) {
// :: error: (argument)
list.add(s);
// :: error: (assignment)
someString = s;
return s;
}
void initializeLocalTainted(@Tainted Buffer b) {
Buffer local = b;
@Tainted Buffer copy1 = local;
// :: error: (assignment)
@Untainted Buffer copy2 = local;
}
void initializeLocalUntainted(@Untainted Buffer b) {
Buffer local = b;
@Untainted Buffer copy1 = local;
// :: error: (assignment)
@Tainted Buffer copy2 = local;
}
void initializeLocalPolyTainted(@PolyTainted Buffer b) {
Buffer local = b;
@PolyTainted Buffer copy = local;
}
void noInitializer(@Untainted Buffer b) {
Buffer local;
// :: error: (assignment)
local = b;
}
}
class Use {
void passingUses(@Untainted String untainted, @Untainted Buffer buffer) {
buffer.list.add(untainted);
buffer.someString = untainted;
buffer.append(untainted);
}
void failingUses(@Tainted String tainted, @Untainted Buffer buffer) {
// :: error: (argument)
buffer.list.add(tainted);
// :: error: (assignment)
buffer.someString = tainted;
// :: error: (argument)
buffer.append(tainted);
}
void casts(@Untainted Object untainted, @Tainted Object tainted) {
@Untainted Buffer b1 = (@Untainted Buffer) untainted; // ok
// :: error: (invariant.cast.unsafe)
@Untainted Buffer b2 = (@Untainted Buffer) tainted;
// :: error: (invariant.cast.unsafe)
@Tainted Buffer b3 = (@Tainted Buffer) untainted; // error
// :: error: (invariant.cast.unsafe)
@Tainted Buffer b4 = (@Tainted Buffer) tainted; // error
@Untainted Buffer b5 = (Buffer) untainted; // ok
// :: error: (invariant.cast.unsafe)
@Tainted Buffer b6 = (Buffer) tainted;
}
void creation() {
@Untainted Buffer b1 = new @Untainted Buffer();
@Tainted Buffer b2 = new @Tainted Buffer();
@PolyTainted Buffer b3 = new @PolyTainted Buffer();
}
}
// For classes with @HasQualifierParameter, different defaulting rules are applied on that type
// inside the class body and outside the class body, so local variables need to be tested
// outside the class as well.
class LocalVars {
void initializeLocalTainted(@Tainted Buffer b) {
Buffer local = b;
@Tainted Buffer copy1 = local;
// :: error: (assignment)
@Untainted Buffer copy2 = local;
}
void initializeLocalUntainted(@Untainted Buffer b) {
Buffer local = b;
@Untainted Buffer copy1 = local;
// :: error: (assignment)
@Tainted Buffer copy2 = local;
}
void initializeLocalPolyTainted(@PolyTainted Buffer b) {
Buffer local = b;
@PolyTainted Buffer copy = local;
}
void noInitializer(@Untainted Buffer b) {
Buffer local;
// :: error: (assignment)
local = b;
}
// These next two cases test circular dependencies. Calculating the type of a local variable
// looks at the type of initializer, but if the type of the initializer depends on the type
// of the variable, then infinite recursion could occur.
void testTypeVariableInference() {
GenericWithQualParam<String> set = new GenericWithQualParam<>();
}
void testVariableInOwnInitializer() {
Buffer b = (b = null);
}
}
@HasQualifierParameter(Tainted.class)
static class GenericWithQualParam<T> {}
}