diff --git a/annotator-core/src/main/java/edu/ucr/cs/riple/core/checkers/CheckerBaseClass.java b/annotator-core/src/main/java/edu/ucr/cs/riple/core/checkers/CheckerBaseClass.java
index 971d0d44b..94d2c20a1 100644
--- a/annotator-core/src/main/java/edu/ucr/cs/riple/core/checkers/CheckerBaseClass.java
+++ b/annotator-core/src/main/java/edu/ucr/cs/riple/core/checkers/CheckerBaseClass.java
@@ -27,6 +27,7 @@
import edu.ucr.cs.riple.core.Config;
import edu.ucr.cs.riple.core.Context;
import edu.ucr.cs.riple.core.checkers.nullaway.NullAway;
+import edu.ucr.cs.riple.core.checkers.ucrtaint.UCRTaint;
import edu.ucr.cs.riple.core.metadata.index.Error;
import edu.ucr.cs.riple.core.module.ModuleInfo;
import edu.ucr.cs.riple.injector.location.OnField;
@@ -75,6 +76,8 @@ public static Checker> getCheckerByName(String name, Context context) {
switch (name) {
case NullAway.NAME:
return new NullAway(context);
+ case UCRTaint.NAME:
+ return new UCRTaint(context);
default:
throw new RuntimeException("Unknown checker name: " + name);
}
diff --git a/annotator-core/src/main/java/edu/ucr/cs/riple/core/checkers/ucrtaint/UCRTaint.java b/annotator-core/src/main/java/edu/ucr/cs/riple/core/checkers/ucrtaint/UCRTaint.java
new file mode 100644
index 000000000..8e5433606
--- /dev/null
+++ b/annotator-core/src/main/java/edu/ucr/cs/riple/core/checkers/ucrtaint/UCRTaint.java
@@ -0,0 +1,135 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2023 Nima Karimipour
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package edu.ucr.cs.riple.core.checkers.ucrtaint;
+
+import com.google.common.collect.ImmutableSet;
+import edu.ucr.cs.riple.core.Context;
+import edu.ucr.cs.riple.core.checkers.CheckerBaseClass;
+import edu.ucr.cs.riple.core.injectors.AnnotationInjector;
+import edu.ucr.cs.riple.core.metadata.index.Fix;
+import edu.ucr.cs.riple.core.metadata.region.Region;
+import edu.ucr.cs.riple.core.module.ModuleConfiguration;
+import edu.ucr.cs.riple.core.module.ModuleInfo;
+import edu.ucr.cs.riple.injector.changes.AddTypeUseMarkerAnnotation;
+import edu.ucr.cs.riple.injector.location.Location;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashSet;
+import java.util.Set;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+
+/**
+ * Represents UCRTaint checker in
+ * Annotator.
+ */
+public class UCRTaint extends CheckerBaseClass {
+
+ /** The name of the checker. This is used to identify the checker in the configuration file. */
+ public static final String NAME = "UCRTaint";
+
+ public UCRTaint(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void preprocess(AnnotationInjector injector) {}
+
+ @Override
+ public Set deserializeErrors(ModuleInfo module) {
+ ImmutableSet paths =
+ module.getModuleConfiguration().stream()
+ .map(moduleInfo -> moduleInfo.dir.resolve("errors.json"))
+ .collect(ImmutableSet.toImmutableSet());
+ Set errors = new HashSet<>();
+ paths.forEach(
+ path -> {
+ try {
+ String content = Files.readString(path, Charset.defaultCharset());
+ content = "{ \"errors\": [" + content.substring(0, content.length() - 1) + "]}";
+ JSONObject jsonObject = (JSONObject) new JSONParser().parse(content);
+ JSONArray errorsJson = (JSONArray) jsonObject.get("errors");
+ errorsJson.forEach(o -> errors.add(deserializeErrorFromJSON((JSONObject) o, module)));
+ } catch (IOException | ParseException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ return errors;
+ }
+
+ private UCRTaintError deserializeErrorFromJSON(JSONObject errorsJson, ModuleInfo moduleInfo) {
+ String errorType = (String) errorsJson.get("messageKey");
+ int offset = ((Long) errorsJson.get("offset")).intValue();
+ Region region =
+ new Region(
+ (String) ((JSONObject) errorsJson.get("region")).get("member"),
+ (String) ((JSONObject) errorsJson.get("region")).get("class"));
+ ImmutableSet.Builder builder = ImmutableSet.builder();
+ ((JSONArray) errorsJson.get("fixes"))
+ .forEach(
+ o -> {
+ JSONObject fixJson = (JSONObject) o;
+ Location location =
+ Location.createLocationFromJSON((JSONObject) fixJson.get("location"));
+ location.ifField(onField -> extendVariableList(onField, moduleInfo));
+ builder.add(
+ new Fix(
+ new AddTypeUseMarkerAnnotation(
+ location, "edu.ucr.cs.riple.taint.ucrtainting.qual.RUntainted"),
+ errorType,
+ true));
+ });
+ return new UCRTaintError(errorType, "", region, offset, builder.build());
+ }
+
+ @Override
+ public void suppressRemainingErrors(AnnotationInjector injector) {
+ throw new RuntimeException(
+ "Suppression for remaining errors is not supported for " + NAME + "yet!");
+ }
+
+ @Override
+ public void verifyCheckerCompatibility() {}
+
+ @Override
+ public void prepareConfigFilesForBuild(ImmutableSet configurations) {
+ // TODO: implement this once configuration on UCRTaint is finalized.
+ }
+
+ @Override
+ public UCRTaintError createError(
+ String errorType,
+ String errorMessage,
+ Region region,
+ int offset,
+ ImmutableSet resolvingFixes,
+ ModuleInfo moduleInfo) {
+ return new UCRTaintError(errorType, errorMessage, region, offset, resolvingFixes);
+ }
+}
diff --git a/annotator-core/src/main/java/edu/ucr/cs/riple/core/checkers/ucrtaint/UCRTaintError.java b/annotator-core/src/main/java/edu/ucr/cs/riple/core/checkers/ucrtaint/UCRTaintError.java
new file mode 100644
index 000000000..1b05b3031
--- /dev/null
+++ b/annotator-core/src/main/java/edu/ucr/cs/riple/core/checkers/ucrtaint/UCRTaintError.java
@@ -0,0 +1,43 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2023 Nima Karimipour
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package edu.ucr.cs.riple.core.checkers.ucrtaint;
+
+import com.google.common.collect.ImmutableSet;
+import edu.ucr.cs.riple.core.metadata.index.Error;
+import edu.ucr.cs.riple.core.metadata.index.Fix;
+import edu.ucr.cs.riple.core.metadata.region.Region;
+
+/** Represents an error reported by {@link UCRTaint}. */
+public class UCRTaintError extends Error {
+
+ public UCRTaintError(
+ String messageType,
+ String message,
+ Region region,
+ int offset,
+ ImmutableSet resolvingFixes) {
+ super(messageType, message, region, offset, resolvingFixes);
+ }
+}
diff --git a/annotator-core/src/main/java/edu/ucr/cs/riple/core/metadata/region/CompoundRegionRegistry.java b/annotator-core/src/main/java/edu/ucr/cs/riple/core/metadata/region/CompoundRegionRegistry.java
index 8da3412aa..f63c46fbd 100644
--- a/annotator-core/src/main/java/edu/ucr/cs/riple/core/metadata/region/CompoundRegionRegistry.java
+++ b/annotator-core/src/main/java/edu/ucr/cs/riple/core/metadata/region/CompoundRegionRegistry.java
@@ -56,6 +56,7 @@ public CompoundRegionRegistry(ModuleInfo moduleInfo) {
ImmutableSet.of(
new FieldRegionRegistry(moduleInfo),
methodRegionRegistry,
+ new LocalVariableRegionRegistry(),
new ParameterRegionRegistry(moduleInfo, methodRegionRegistry));
}
diff --git a/annotator-core/src/main/java/edu/ucr/cs/riple/core/metadata/region/LocalVariableRegionRegistry.java b/annotator-core/src/main/java/edu/ucr/cs/riple/core/metadata/region/LocalVariableRegionRegistry.java
new file mode 100644
index 000000000..e941d6d87
--- /dev/null
+++ b/annotator-core/src/main/java/edu/ucr/cs/riple/core/metadata/region/LocalVariableRegionRegistry.java
@@ -0,0 +1,42 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2023 Nima Karimipour
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package edu.ucr.cs.riple.core.metadata.region;
+
+import edu.ucr.cs.riple.injector.location.Location;
+import edu.ucr.cs.riple.injector.location.OnLocalVariable;
+import java.util.Optional;
+import java.util.Set;
+
+/** Region Registry for Local variables. */
+public class LocalVariableRegionRegistry implements RegionRegistry {
+ @Override
+ public Optional> getImpactedRegions(Location location) {
+ if (!location.isOnLocalVariable()) {
+ return Optional.empty();
+ }
+ OnLocalVariable localVariable = location.toLocalVariable();
+ return Optional.of(Set.of(new Region(localVariable.clazz, localVariable.encMethod.method)));
+ }
+}
diff --git a/injector/src/main/java/edu/ucr/cs/riple/injector/location/Location.java b/injector/src/main/java/edu/ucr/cs/riple/injector/location/Location.java
index a32c7ef81..add5b665b 100644
--- a/injector/src/main/java/edu/ucr/cs/riple/injector/location/Location.java
+++ b/injector/src/main/java/edu/ucr/cs/riple/injector/location/Location.java
@@ -28,10 +28,12 @@
import com.google.common.collect.Sets;
import edu.ucr.cs.riple.injector.Helper;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Objects;
import java.util.function.Consumer;
import javax.annotation.Nullable;
+import org.json.simple.JSONObject;
/** Represents a location of an element in the source code. */
public abstract class Location {
@@ -57,6 +59,19 @@ public Location(LocationKind type, Path path, String clazz) {
this.path = path;
}
+ /**
+ * Creates an instance of {@link Location} for a given type, and retrieves path and class values
+ * from the given JSON object.
+ *
+ * @param type The type of the location.
+ * @param json The JSON object containing the path and class values.
+ */
+ public Location(LocationKind type, JSONObject json) {
+ this.type = type;
+ this.clazz = (String) json.get("class");
+ this.path = Paths.get((String) json.get("path"));
+ }
+
/**
* Creates an instance of {@link Location} based on values written in a row of a TSV file. These
* values should be in order of:
@@ -98,6 +113,24 @@ public static Location createLocationFromArrayInfo(String[] values) {
throw new RuntimeException("Cannot reach this statement, values: " + Arrays.toString(values));
}
+ public static Location createLocationFromJSON(JSONObject json) {
+ String kind = (String) json.get("kind");
+ switch (kind) {
+ case "METHOD":
+ return new OnMethod(json);
+ case "FIELD":
+ return new OnField(json);
+ case "PARAMETER":
+ return new OnParameter(json);
+ case "LOCAL_VARIABLE":
+ return new OnLocalVariable(json);
+ case "CLASS":
+ return new OnClass(json);
+ default:
+ throw new RuntimeException("Cannot reach this statement, kind: " + kind);
+ }
+ }
+
/**
* If this location is of kind {@link LocationKind#METHOD}, calls the consumer on the location.
*
diff --git a/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnClass.java b/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnClass.java
index e5cffb497..0ed276afa 100644
--- a/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnClass.java
+++ b/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnClass.java
@@ -27,6 +27,7 @@
import edu.ucr.cs.riple.injector.Helper;
import java.nio.file.Path;
import java.util.regex.Pattern;
+import org.json.simple.JSONObject;
/** Represents a location for class element. This location is used to apply changes to a class. */
public class OnClass extends Location {
@@ -45,6 +46,10 @@ public OnClass(String path, String clazz) {
this(Helper.deserializePath(path), clazz);
}
+ public OnClass(JSONObject json) {
+ super(LocationKind.CLASS, json);
+ }
+
/**
* Checks if flat name is for an anonymous class.
*
diff --git a/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnField.java b/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnField.java
index 9331cfddc..1a87d3e7f 100644
--- a/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnField.java
+++ b/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnField.java
@@ -27,9 +27,11 @@
import edu.ucr.cs.riple.injector.Helper;
import java.nio.file.Path;
import java.util.Collections;
+import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
+import org.json.simple.JSONObject;
/**
* Represents a location for field element. This location is used to apply changes to a class field.
@@ -59,6 +61,11 @@ public OnField(String path, String clazz, Set variables) {
this(Helper.deserializePath(path), clazz, variables);
}
+ public OnField(JSONObject json) {
+ super(LocationKind.FIELD, json);
+ this.variables = new HashSet<>(Collections.singletonList((String) json.get("variables")));
+ }
+
@Override
public void ifField(Consumer consumer) {
consumer.accept(this);
diff --git a/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnLocalVariable.java b/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnLocalVariable.java
index 8de77c97f..3a8fac47b 100644
--- a/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnLocalVariable.java
+++ b/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnLocalVariable.java
@@ -28,6 +28,7 @@
import java.nio.file.Path;
import java.util.Objects;
import java.util.function.Consumer;
+import org.json.simple.JSONObject;
/**
* Represents a location for local variable element. This location is used to apply changes to a
@@ -51,6 +52,12 @@ public OnLocalVariable(String path, String clazz, String encMethod, String varNa
this(Helper.deserializePath(path), clazz, encMethod, varName);
}
+ public OnLocalVariable(JSONObject json) {
+ super(LocationKind.LOCAL_VARIABLE, json);
+ this.encMethod = new OnMethod(json);
+ this.varName = (String) json.get("varName");
+ }
+
@Override
public void ifLocalVariable(Consumer consumer) {
consumer.accept(this);
diff --git a/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnMethod.java b/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnMethod.java
index f3c2c1cfc..d25ba12e5 100644
--- a/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnMethod.java
+++ b/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnMethod.java
@@ -30,6 +30,7 @@
import java.nio.file.Path;
import java.util.Objects;
import java.util.function.Consumer;
+import org.json.simple.JSONObject;
/** Represents a location for method element. This location is used to apply changes to a method. */
public class OnMethod extends Location {
@@ -52,6 +53,12 @@ public OnMethod(String path, String clazz, String method) {
this(Helper.deserializePath(path), clazz, method);
}
+ public OnMethod(JSONObject json) {
+ super(LocationKind.METHOD, json);
+ this.method = (String) json.get("method");
+ this.matcher = new SignatureMatcher(method);
+ }
+
/**
* Checks if the given method matches the method signature of this location.
*
diff --git a/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnParameter.java b/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnParameter.java
index 4719c12a0..e52c87545 100644
--- a/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnParameter.java
+++ b/injector/src/main/java/edu/ucr/cs/riple/injector/location/OnParameter.java
@@ -28,6 +28,7 @@
import java.nio.file.Path;
import java.util.Objects;
import java.util.function.Consumer;
+import org.json.simple.JSONObject;
/**
* Represents a location for parameter element. This location is used to apply changes to a
@@ -50,6 +51,12 @@ public OnParameter(String path, String clazz, String method, int index) {
this(Helper.deserializePath(path), clazz, method, index);
}
+ public OnParameter(JSONObject json) {
+ super(LocationKind.PARAMETER, json);
+ this.enclosingMethod = new OnMethod(json);
+ this.index = ((Long) json.get("index")).intValue();
+ }
+
@Override
public void ifParameter(Consumer consumer) {
consumer.accept(this);