From 13f846be011b054010712cb68a6b6f58ed33fa02 Mon Sep 17 00:00:00 2001 From: hello Date: Tue, 18 Jun 2024 14:42:27 -0700 Subject: [PATCH 001/184] Basic duplication of TaintChecker for SQLi --- .../sqltainting/qual/PolySqlTainted.java | 22 +++++++++++ .../checker/sqltainting/qual/SqlTainted.java | 24 ++++++++++++ .../sqltainting/qual/SqlUntainted.java | 27 +++++++++++++ .../SqlTaintingAnnotatedTypeFactory.java | 38 +++++++++++++++++++ .../sqltainting/SqlTaintingChecker.java | 15 ++++++++ .../sqltainting/SqlTaintingVisitor.java | 31 +++++++++++++++ 6 files changed, 157 insertions(+) create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlTainted.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlTainted.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlUntainted.java create mode 100644 checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java create mode 100644 checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java create mode 100644 checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingVisitor.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlTainted.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlTainted.java new file mode 100644 index 00000000000..8b377444aee --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlTainted.java @@ -0,0 +1,22 @@ +package org.checkerframework.checker.sqltainting.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.checkerframework.checker.sqltainting.qual.SqlTainted; +import org.checkerframework.framework.qual.PolymorphicQualifier; + +/** + * A polymorphic qualifier for the Tainting type system. + * + * @checker_framework.manual #tainting-checker Tainting Checker + * @checker_framework.manual #qualifier-polymorphism Qualifier polymorphism + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@PolymorphicQualifier(SqlTainted.class) +public @interface PolySqlTainted {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlTainted.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlTainted.java new file mode 100644 index 00000000000..8608db95065 --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlTainted.java @@ -0,0 +1,24 @@ +package org.checkerframework.checker.sqltainting.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.checkerframework.checker.sqltainting.qual.SqlUntainted; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Denotes a possibly-tainted value: at run time, the value might be tainted or might be untainted. + * + * @see SqlUntainted + * @checker_framework.manual #tainting-checker Tainting Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({}) +@DefaultQualifierInHierarchy // unannotated values are marked SqlTainted +public @interface SqlTainted {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlUntainted.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlUntainted.java new file mode 100644 index 00000000000..448d5ac2991 --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlUntainted.java @@ -0,0 +1,27 @@ +package org.checkerframework.checker.sqltainting.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.checkerframework.checker.sqltainting.qual.SqlTainted; +import org.checkerframework.framework.qual.DefaultFor; +import org.checkerframework.framework.qual.LiteralKind; +import org.checkerframework.framework.qual.QualifierForLiterals; +import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TypeUseLocation; + +/** + * Denotes a reference that is untainted, i.e. can be trusted. + * + * @checker_framework.manual #tainting-checker Tainting Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(SqlTainted.class) +@QualifierForLiterals(LiteralKind.STRING) +@DefaultFor(TypeUseLocation.LOWER_BOUND) +public @interface SqlUntainted {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java new file mode 100644 index 00000000000..dd43119cec7 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java @@ -0,0 +1,38 @@ +package org.checkerframework.checker.sqltainting; + +import java.util.Set; +import javax.lang.model.element.AnnotationMirror; + +import org.checkerframework.checker.sqltainting.SqlTaintingAnnotatedTypeFactory; +import org.checkerframework.checker.sqltainting.qual.SqlUntainted; +import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; +import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.javacutil.AnnotationBuilder; +import org.checkerframework.javacutil.AnnotationMirrorSet; + +/** Annotated type factory for the SQL Tainting Checker. */ +public class SqlTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { + + /** The {@code @}{@link SqlUntainted} annotation mirror. */ + private final AnnotationMirror SQLUNTAINTED; + + /** A singleton set containing the {@code @}{@link SqlUntainted} annotation mirror. */ + private final AnnotationMirrorSet setOfSqlUntainted; + + /** + * Creates a {@link SqlTaintingAnnotatedTypeFactory}. + * + * @param checker the tainting checker + */ + public SqlTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { + super(checker); + this.SQLUNTAINTED = AnnotationBuilder.fromClass(getElementUtils(), SqlUntainted.class); + this.setOfSqlUntainted = AnnotationMirrorSet.singleton(SQLUNTAINTED); + postInit(); + } + + @Override + protected Set getEnumConstructorQualifiers() { + return setOfSqlUntainted; + } +} diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java new file mode 100644 index 00000000000..827a38f70c3 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java @@ -0,0 +1,15 @@ +package org.checkerframework.checker.sqltainting; + +import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.framework.source.SuppressWarningsPrefix; + +/** + * A type-checker plug-in for the Tainting type system qualifier that finds (and verifies the + * absence of) trust bugs. + * + *

It verifies that only verified values are trusted and that user-input is sanitized before use. + * + * @checker_framework.manual #tainting-checker Tainting Checker + */ +@SuppressWarningsPrefix({"sqluntainted", "sqltainting"}) +public class SqlTaintingChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingVisitor.java b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingVisitor.java new file mode 100644 index 00000000000..4a761649260 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingVisitor.java @@ -0,0 +1,31 @@ +package org.checkerframework.checker.sqltainting; + +import javax.lang.model.element.ExecutableElement; + +import org.checkerframework.checker.tainting.TaintingChecker; +import org.checkerframework.checker.tainting.TaintingVisitor; +import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; +import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.common.basetype.BaseTypeVisitor; +import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType; + +/** Visitor for the {@link SqlTaintingChecker}. */ +public class SqlTaintingVisitor extends BaseTypeVisitor { + + /** + * Creates a {@link SqlTaintingVisitor}. + * + * @param checker the checker that uses this visitor + */ + public SqlTaintingVisitor(BaseTypeChecker checker) { + super(checker); + } + + /** + * Don't check that the constructor result is top. Checking that the super() or this() call is a + * subtype of the constructor result is sufficient. + */ + @Override + protected void checkConstructorResult( + AnnotatedExecutableType constructorType, ExecutableElement constructorElement) {} +} From 9950b17ba4ecd1f989637803433852a33ca352aa Mon Sep 17 00:00:00 2001 From: hello Date: Fri, 21 Jun 2024 15:49:20 -0700 Subject: [PATCH 002/184] Added basic SQL tainting test --- ...ySqlTainted.java => PolySqlDangerous.java} | 6 +-- .../{SqlTainted.java => SqlDangerous.java} | 10 ++-- .../qual/{SqlUntainted.java => SqlSafe.java} | 11 ++--- .../SqlTaintingAnnotatedTypeFactory.java | 18 ++++--- .../sqltainting/SqlTaintingChecker.java | 2 +- .../sqltainting/SqlTaintingVisitor.java | 3 -- .../tests/sqltainting/SimpleSqlDangerous.java | 47 +++++++++++++++++++ 7 files changed, 66 insertions(+), 31 deletions(-) rename checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/{PolySqlTainted.java => PolySqlDangerous.java} (81%) rename checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/{SqlTainted.java => SqlDangerous.java} (67%) rename checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/{SqlUntainted.java => SqlSafe.java} (74%) create mode 100644 checker/tests/sqltainting/SimpleSqlDangerous.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlTainted.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlDangerous.java similarity index 81% rename from checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlTainted.java rename to checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlDangerous.java index 8b377444aee..48a33916db2 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlTainted.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlDangerous.java @@ -5,8 +5,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; - -import org.checkerframework.checker.sqltainting.qual.SqlTainted; import org.checkerframework.framework.qual.PolymorphicQualifier; /** @@ -18,5 +16,5 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@PolymorphicQualifier(SqlTainted.class) -public @interface PolySqlTainted {} +@PolymorphicQualifier(SqlDangerous.class) +public @interface PolySqlDangerous {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlTainted.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlDangerous.java similarity index 67% rename from checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlTainted.java rename to checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlDangerous.java index 8608db95065..74819dba42f 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlTainted.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlDangerous.java @@ -5,20 +5,18 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; - -import org.checkerframework.checker.sqltainting.qual.SqlUntainted; import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; import org.checkerframework.framework.qual.SubtypeOf; /** - * Denotes a possibly-tainted value: at run time, the value might be tainted or might be untainted. + * Denotes a possibly-dangerous value: at run time, the value might be safe for SQL query use or + * might be dangerous. * - * @see SqlUntainted - * @checker_framework.manual #tainting-checker Tainting Checker + * @see SqlSafe */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf({}) @DefaultQualifierInHierarchy // unannotated values are marked SqlTainted -public @interface SqlTainted {} +public @interface SqlDangerous {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlUntainted.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSafe.java similarity index 74% rename from checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlUntainted.java rename to checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSafe.java index 448d5ac2991..11a2195c3f5 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlUntainted.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSafe.java @@ -5,8 +5,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; - -import org.checkerframework.checker.sqltainting.qual.SqlTainted; import org.checkerframework.framework.qual.DefaultFor; import org.checkerframework.framework.qual.LiteralKind; import org.checkerframework.framework.qual.QualifierForLiterals; @@ -14,14 +12,13 @@ import org.checkerframework.framework.qual.TypeUseLocation; /** - * Denotes a reference that is untainted, i.e. can be trusted. - * - * @checker_framework.manual #tainting-checker Tainting Checker + * Denotes a reference that is SQL-safe, i.e., originates from a trusted source or has been + * sanitized. */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(SqlTainted.class) +@SubtypeOf(SqlDangerous.class) @QualifierForLiterals(LiteralKind.STRING) @DefaultFor(TypeUseLocation.LOWER_BOUND) -public @interface SqlUntainted {} +public @interface SqlSafe {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java index dd43119cec7..4df92616eb3 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java @@ -2,9 +2,7 @@ import java.util.Set; import javax.lang.model.element.AnnotationMirror; - -import org.checkerframework.checker.sqltainting.SqlTaintingAnnotatedTypeFactory; -import org.checkerframework.checker.sqltainting.qual.SqlUntainted; +import org.checkerframework.checker.sqltainting.qual.SqlSafe; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.javacutil.AnnotationBuilder; @@ -13,11 +11,11 @@ /** Annotated type factory for the SQL Tainting Checker. */ public class SqlTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { - /** The {@code @}{@link SqlUntainted} annotation mirror. */ - private final AnnotationMirror SQLUNTAINTED; + /** The {@code @}{@link SqlSafe} annotation mirror. */ + private final AnnotationMirror SQLSAFE; - /** A singleton set containing the {@code @}{@link SqlUntainted} annotation mirror. */ - private final AnnotationMirrorSet setOfSqlUntainted; + /** A singleton set containing the {@code @}{@link SqlSafe} annotation mirror. */ + private final AnnotationMirrorSet setOfSqlSafe; /** * Creates a {@link SqlTaintingAnnotatedTypeFactory}. @@ -26,13 +24,13 @@ public class SqlTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { */ public SqlTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); - this.SQLUNTAINTED = AnnotationBuilder.fromClass(getElementUtils(), SqlUntainted.class); - this.setOfSqlUntainted = AnnotationMirrorSet.singleton(SQLUNTAINTED); + this.SQLSAFE = AnnotationBuilder.fromClass(getElementUtils(), SqlSafe.class); + this.setOfSqlSafe = AnnotationMirrorSet.singleton(SQLSAFE); postInit(); } @Override protected Set getEnumConstructorQualifiers() { - return setOfSqlUntainted; + return setOfSqlSafe; } } diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java index 827a38f70c3..bdad895e05d 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java @@ -11,5 +11,5 @@ * * @checker_framework.manual #tainting-checker Tainting Checker */ -@SuppressWarningsPrefix({"sqluntainted", "sqltainting"}) +@SuppressWarningsPrefix({"sqlsafe", "sqltainting"}) public class SqlTaintingChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingVisitor.java b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingVisitor.java index 4a761649260..8502d9be71a 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingVisitor.java +++ b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingVisitor.java @@ -1,9 +1,6 @@ package org.checkerframework.checker.sqltainting; import javax.lang.model.element.ExecutableElement; - -import org.checkerframework.checker.tainting.TaintingChecker; -import org.checkerframework.checker.tainting.TaintingVisitor; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.common.basetype.BaseTypeVisitor; diff --git a/checker/tests/sqltainting/SimpleSqlDangerous.java b/checker/tests/sqltainting/SimpleSqlDangerous.java new file mode 100644 index 00000000000..beec867a2ef --- /dev/null +++ b/checker/tests/sqltainting/SimpleSqlDangerous.java @@ -0,0 +1,47 @@ +import org.checkerframework.checker.sqltainting.qual.SqlSafe; + +public class SimpleSqlDangerous { + + void execute(@SqlSafe String s) {} + + void dangerous(String s) {} + + void stringLiteral() { + execute("ldskjfldj"); + dangerous("lksjdflkjdf"); + } + + void stringRef(String ref) { + // :: error: (argument) + execute(ref); // error + dangerous(ref); + } + + void safeRef(@SqlSafe String ref) { + execute(ref); + dangerous(ref); + } + + void concatenation(@SqlSafe String s1, String s2) { + execute(s1 + s1); + execute(s1 += s1); + execute(s1 + "m"); + // :: error: (argument) + execute(s1 + s2); // error + + // :: error: (argument) + execute(s2 + s1); // error + // :: error: (argument) + execute(s2 + "m"); // error + // :: error: (argument) + execute(s2 + s2); // error + + dangerous(s1 + s1); + dangerous(s1 + "m"); + dangerous(s1 + s2); + + dangerous(s2 + s1); + dangerous(s2 + "m"); + dangerous(s2 + s2); + } +} From 2707a54379c21ac68c186ffd81b26af006490c83 Mon Sep 17 00:00:00 2001 From: hello Date: Fri, 21 Jun 2024 15:54:42 -0700 Subject: [PATCH 003/184] Added basic test --- checker/tests/sqltainting/SimpleSqlDangerous.java | 1 + 1 file changed, 1 insertion(+) diff --git a/checker/tests/sqltainting/SimpleSqlDangerous.java b/checker/tests/sqltainting/SimpleSqlDangerous.java index beec867a2ef..74c10567eac 100644 --- a/checker/tests/sqltainting/SimpleSqlDangerous.java +++ b/checker/tests/sqltainting/SimpleSqlDangerous.java @@ -14,6 +14,7 @@ void stringLiteral() { void stringRef(String ref) { // :: error: (argument) execute(ref); // error + dangerous(ref); } From 7d905a5e3b66624b0f1ef3f39ab63e9c65a65209 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 23 Jun 2024 21:27:08 -0700 Subject: [PATCH 004/184] Added sql tainting test file under junit directory --- .../checker/test/junit/SqltaintingTest.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 checker/src/test/java/org/checkerframework/checker/test/junit/SqltaintingTest.java diff --git a/checker/src/test/java/org/checkerframework/checker/test/junit/SqltaintingTest.java b/checker/src/test/java/org/checkerframework/checker/test/junit/SqltaintingTest.java new file mode 100644 index 00000000000..c84c7345f4c --- /dev/null +++ b/checker/src/test/java/org/checkerframework/checker/test/junit/SqltaintingTest.java @@ -0,0 +1,24 @@ +package org.checkerframework.checker.test.junit; + +import java.io.File; +import java.util.List; +import org.checkerframework.checker.sqltainting.SqlTaintingChecker; +import org.checkerframework.framework.test.CheckerFrameworkPerDirectoryTest; +import org.junit.runners.Parameterized.Parameters; + +public class SqltaintingTest extends CheckerFrameworkPerDirectoryTest { + + /** + * Create a TaintingTest. + * + * @param testFiles the files containing test code, which will be type-checked + */ + public SqltaintingTest(List testFiles) { + super(testFiles, SqlTaintingChecker.class, "sqltainting"); + } + + @Parameters + public static String[] getTestDirs() { + return new String[] {"sqltainting", "all-systems"}; + } +} From a4ab6f4ec53c533e31813ac8ebf07448fd0d5c2e Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 25 Jun 2024 19:32:26 -0700 Subject: [PATCH 005/184] Renamed SqlSafe -> SqlSanitized, SqlDangerous -> SqlQueryValue; renamed references in code as necessary --- .../sqltainting/qual/PolySqlQueryValue.java | 19 ++++++++ .../sqltainting/qual/SqlQueryValue.java | 22 +++++++++ .../sqltainting/qual/SqlSanitized.java | 24 ++++++++++ .../SqlTaintingAnnotatedTypeFactory.java | 16 +++---- .../sqltainting/SqlTaintingChecker.java | 2 +- .../sqltainting/SimpleSqlQueryValue.java | 48 +++++++++++++++++++ 6 files changed, 122 insertions(+), 9 deletions(-) create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlQueryValue.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlQueryValue.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSanitized.java create mode 100644 checker/tests/sqltainting/SimpleSqlQueryValue.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlQueryValue.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlQueryValue.java new file mode 100644 index 00000000000..6bc2b8c940b --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlQueryValue.java @@ -0,0 +1,19 @@ +package org.checkerframework.checker.sqltainting.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.PolymorphicQualifier; + +/** + * A polymorphic qualifier for the SQL Value Tainting type system. + * + * @checker_framework.manual #qualifier-polymorphism Qualifier polymorphism + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@PolymorphicQualifier(SqlQueryValue.class) +public @interface PolySqlQueryValue {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlQueryValue.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlQueryValue.java new file mode 100644 index 00000000000..aa9c9883ab0 --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlQueryValue.java @@ -0,0 +1,22 @@ +package org.checkerframework.checker.sqltainting.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Denotes a value to be used as part of a SQL query. Might be safe for SQL query use or might be + * dangerous. + * + * @see SqlSanitized + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({}) +@DefaultQualifierInHierarchy +public @interface SqlQueryValue {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSanitized.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSanitized.java new file mode 100644 index 00000000000..6973376e9a4 --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSanitized.java @@ -0,0 +1,24 @@ +package org.checkerframework.checker.sqltainting.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.DefaultFor; +import org.checkerframework.framework.qual.LiteralKind; +import org.checkerframework.framework.qual.QualifierForLiterals; +import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TypeUseLocation; + +/** + * Denotes a value to be used in a SQL query that has been sanitized (i.e. non-alphanumeric + * characters escaped as necessary) and is thus safe for SQL query use. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(SqlQueryValue.class) +@QualifierForLiterals(LiteralKind.STRING) +@DefaultFor(TypeUseLocation.LOWER_BOUND) +public @interface SqlSanitized {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java index 4df92616eb3..83901f9a9a3 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java @@ -2,7 +2,7 @@ import java.util.Set; import javax.lang.model.element.AnnotationMirror; -import org.checkerframework.checker.sqltainting.qual.SqlSafe; +import org.checkerframework.checker.sqltainting.qual.SqlSanitized; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.javacutil.AnnotationBuilder; @@ -11,11 +11,11 @@ /** Annotated type factory for the SQL Tainting Checker. */ public class SqlTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { - /** The {@code @}{@link SqlSafe} annotation mirror. */ - private final AnnotationMirror SQLSAFE; + /** The {@code @}{@link SqlSanitized} annotation mirror. */ + private final AnnotationMirror SQLSANITIZED; - /** A singleton set containing the {@code @}{@link SqlSafe} annotation mirror. */ - private final AnnotationMirrorSet setOfSqlSafe; + /** A singleton set containing the {@code @}{@link SqlSanitized} annotation mirror. */ + private final AnnotationMirrorSet setOfSqlSanitized; /** * Creates a {@link SqlTaintingAnnotatedTypeFactory}. @@ -24,13 +24,13 @@ public class SqlTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { */ public SqlTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); - this.SQLSAFE = AnnotationBuilder.fromClass(getElementUtils(), SqlSafe.class); - this.setOfSqlSafe = AnnotationMirrorSet.singleton(SQLSAFE); + this.SQLSANITIZED = AnnotationBuilder.fromClass(getElementUtils(), SqlSanitized.class); + this.setOfSqlSanitized = AnnotationMirrorSet.singleton(SQLSANITIZED); postInit(); } @Override protected Set getEnumConstructorQualifiers() { - return setOfSqlSafe; + return setOfSqlSanitized; } } diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java index bdad895e05d..b520463b292 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java @@ -11,5 +11,5 @@ * * @checker_framework.manual #tainting-checker Tainting Checker */ -@SuppressWarningsPrefix({"sqlsafe", "sqltainting"}) +@SuppressWarningsPrefix({"sqlsanitized", "sqltainting"}) public class SqlTaintingChecker extends BaseTypeChecker {} diff --git a/checker/tests/sqltainting/SimpleSqlQueryValue.java b/checker/tests/sqltainting/SimpleSqlQueryValue.java new file mode 100644 index 00000000000..4302a57e28a --- /dev/null +++ b/checker/tests/sqltainting/SimpleSqlQueryValue.java @@ -0,0 +1,48 @@ +import org.checkerframework.checker.sqltainting.qual.SqlSanitized; + +public class SimpleSqlQueryValue { + + void execute(@SqlSanitized String s) {} + + void unsanitized(String s) {} + + void stringLiteral() { + execute("ldskjfldj"); + unsanitized("lksjdflkjdf"); + } + + void stringRef(String ref) { + // :: error: (argument) + execute(ref); // error + + unsanitized(ref); + } + + void safeRef(@SqlSanitized String ref) { + execute(ref); + unsanitized(ref); + } + + void concatenation(@SqlSanitized String s1, String s2) { + execute(s1 + s1); + execute(s1 += s1); + execute(s1 + "m"); + // :: error: (argument) + execute(s1 + s2); // error + + // :: error: (argument) + execute(s2 + s1); // error + // :: error: (argument) + execute(s2 + "m"); // error + // :: error: (argument) + execute(s2 + s2); // error + + unsanitized(s1 + s1); + unsanitized(s1 + "m"); + unsanitized(s1 + s2); + + unsanitized(s2 + s1); + unsanitized(s2 + "m"); + unsanitized(s2 + s2); + } +} From 4861495f419f5ca0e52fe5eb03fed435dd34db73 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Wed, 26 Jun 2024 14:23:29 -0700 Subject: [PATCH 006/184] Revised @QualifierForLiterals annotation to automatically annotate escaped SQL values as SqlSanitized. --- .../checker/sqltainting/qual/SqlSanitized.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSanitized.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSanitized.java index 6973376e9a4..4a625ce4cb7 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSanitized.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSanitized.java @@ -6,7 +6,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.checkerframework.framework.qual.DefaultFor; -import org.checkerframework.framework.qual.LiteralKind; import org.checkerframework.framework.qual.QualifierForLiterals; import org.checkerframework.framework.qual.SubtypeOf; import org.checkerframework.framework.qual.TypeUseLocation; @@ -14,11 +13,15 @@ /** * Denotes a value to be used in a SQL query that has been sanitized (i.e. non-alphanumeric * characters escaped as necessary) and is thus safe for SQL query use. + * + *

All empty Strings and String literals consisting solely of alphanumeric characters, + * whitespace, and backslash-escaped sensitive characters (i.e. single/double quotes, backslashes, + * hyphens, percent signs, underscores) are annotated SQLSanitized automatically. */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQueryValue.class) -@QualifierForLiterals(LiteralKind.STRING) +@QualifierForLiterals(stringPatterns = "^(\\w|\\s|\\\\'|\\\\\"|\\\\\\\\|\\\\-|\\\\%|\\\\_)*$") @DefaultFor(TypeUseLocation.LOWER_BOUND) public @interface SqlSanitized {} From 9c1cda5cf41b828997ef166b24a29f058a658486 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 27 Jun 2024 12:08:27 -0700 Subject: [PATCH 007/184] Added tests for @QualifierForLiterals regex --- .../tests/sqltainting/SqlSanitizedRegex.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 checker/tests/sqltainting/SqlSanitizedRegex.java diff --git a/checker/tests/sqltainting/SqlSanitizedRegex.java b/checker/tests/sqltainting/SqlSanitizedRegex.java new file mode 100644 index 00000000000..0781c11f743 --- /dev/null +++ b/checker/tests/sqltainting/SqlSanitizedRegex.java @@ -0,0 +1,43 @@ +import org.checkerframework.checker.sqltainting.qual.SqlSanitized; + +public class SqlSanitizedRegex { + + void execute(@SqlSanitized String s) {} + + void emptyString() { + execute(""); + execute(" "); + } + + void alphanumericLiteral() { + execute("0923uoiwej093NSDF9IJdjfs09"); + execute("8YUGKthbJU8yIUou8y7TYg"); + execute("09 23 uoiwej093N SDF9IJdjfs 09"); + execute("8 YUGKthbJU8y IUou 8 y7TYg"); + } + + void escapedLiterals() { + execute("escaped \\\\ \\\\ backslashes"); + execute("escaped \\' \\\" quotes"); + execute("escaped \\- \\- hyphens"); + execute("escaped \\% \\% percents"); + execute("escaped \\_ \\_ underscores"); + + execute("3 escaped \\'\\_\\% characters"); + execute("3 escaped \\\\\\-\\-\\\" characters"); + } + + void unescapedLiterals() { + // :: error: (argument) + execute("unescaped \\' \\\" \" _ \\\\ characters"); // error + // :: error: (argument) + execute("unescaped -- ' \\\\ characters"); // error + } + + void otherChars() { + // :: error: (argument) + execute("109jnsdf;"); // error + // :: error: (argument) + execute("@293081$^&"); // error + } +} From 119d74cb80fc9a5897e912e4a9f607e9c7831bb2 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Fri, 28 Jun 2024 11:56:17 -0700 Subject: [PATCH 008/184] Renamed files --- .../sqltainting/qual/PolySqlDangerous.java | 20 -------- .../sqltainting/qual/SqlDangerous.java | 22 --------- .../checker/sqltainting/qual/SqlSafe.java | 24 ---------- .../tests/sqltainting/SimpleSqlDangerous.java | 48 ------------------- 4 files changed, 114 deletions(-) delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlDangerous.java delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlDangerous.java delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSafe.java delete mode 100644 checker/tests/sqltainting/SimpleSqlDangerous.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlDangerous.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlDangerous.java deleted file mode 100644 index 48a33916db2..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlDangerous.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.checkerframework.checker.sqltainting.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.PolymorphicQualifier; - -/** - * A polymorphic qualifier for the Tainting type system. - * - * @checker_framework.manual #tainting-checker Tainting Checker - * @checker_framework.manual #qualifier-polymorphism Qualifier polymorphism - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@PolymorphicQualifier(SqlDangerous.class) -public @interface PolySqlDangerous {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlDangerous.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlDangerous.java deleted file mode 100644 index 74819dba42f..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlDangerous.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.checkerframework.checker.sqltainting.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; -import org.checkerframework.framework.qual.SubtypeOf; - -/** - * Denotes a possibly-dangerous value: at run time, the value might be safe for SQL query use or - * might be dangerous. - * - * @see SqlSafe - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf({}) -@DefaultQualifierInHierarchy // unannotated values are marked SqlTainted -public @interface SqlDangerous {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSafe.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSafe.java deleted file mode 100644 index 11a2195c3f5..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSafe.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.checkerframework.checker.sqltainting.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultFor; -import org.checkerframework.framework.qual.LiteralKind; -import org.checkerframework.framework.qual.QualifierForLiterals; -import org.checkerframework.framework.qual.SubtypeOf; -import org.checkerframework.framework.qual.TypeUseLocation; - -/** - * Denotes a reference that is SQL-safe, i.e., originates from a trusted source or has been - * sanitized. - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(SqlDangerous.class) -@QualifierForLiterals(LiteralKind.STRING) -@DefaultFor(TypeUseLocation.LOWER_BOUND) -public @interface SqlSafe {} diff --git a/checker/tests/sqltainting/SimpleSqlDangerous.java b/checker/tests/sqltainting/SimpleSqlDangerous.java deleted file mode 100644 index 74c10567eac..00000000000 --- a/checker/tests/sqltainting/SimpleSqlDangerous.java +++ /dev/null @@ -1,48 +0,0 @@ -import org.checkerframework.checker.sqltainting.qual.SqlSafe; - -public class SimpleSqlDangerous { - - void execute(@SqlSafe String s) {} - - void dangerous(String s) {} - - void stringLiteral() { - execute("ldskjfldj"); - dangerous("lksjdflkjdf"); - } - - void stringRef(String ref) { - // :: error: (argument) - execute(ref); // error - - dangerous(ref); - } - - void safeRef(@SqlSafe String ref) { - execute(ref); - dangerous(ref); - } - - void concatenation(@SqlSafe String s1, String s2) { - execute(s1 + s1); - execute(s1 += s1); - execute(s1 + "m"); - // :: error: (argument) - execute(s1 + s2); // error - - // :: error: (argument) - execute(s2 + s1); // error - // :: error: (argument) - execute(s2 + "m"); // error - // :: error: (argument) - execute(s2 + s2); // error - - dangerous(s1 + s1); - dangerous(s1 + "m"); - dangerous(s1 + s2); - - dangerous(s2 + s1); - dangerous(s2 + "m"); - dangerous(s2 + s2); - } -} From 972ba01f5607f42c58971be37ca9693490bd16d1 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 30 Jun 2024 13:53:26 -0700 Subject: [PATCH 009/184] Revised qualifiers --- .../sqltainting/qual/PolySqlDangerous.java | 20 -------- .../sqltainting/qual/SqlDangerous.java | 22 --------- .../checker/sqltainting/qual/SqlSafe.java | 24 ---------- ...SqlQueryValue.java => SqlUnsanitized.java} | 0 .../tests/sqltainting/SimpleSqlDangerous.java | 48 ------------------- 5 files changed, 114 deletions(-) delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlDangerous.java delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlDangerous.java delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSafe.java rename checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/{SqlQueryValue.java => SqlUnsanitized.java} (100%) delete mode 100644 checker/tests/sqltainting/SimpleSqlDangerous.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlDangerous.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlDangerous.java deleted file mode 100644 index 48a33916db2..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlDangerous.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.checkerframework.checker.sqltainting.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.PolymorphicQualifier; - -/** - * A polymorphic qualifier for the Tainting type system. - * - * @checker_framework.manual #tainting-checker Tainting Checker - * @checker_framework.manual #qualifier-polymorphism Qualifier polymorphism - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@PolymorphicQualifier(SqlDangerous.class) -public @interface PolySqlDangerous {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlDangerous.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlDangerous.java deleted file mode 100644 index 74819dba42f..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlDangerous.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.checkerframework.checker.sqltainting.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; -import org.checkerframework.framework.qual.SubtypeOf; - -/** - * Denotes a possibly-dangerous value: at run time, the value might be safe for SQL query use or - * might be dangerous. - * - * @see SqlSafe - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf({}) -@DefaultQualifierInHierarchy // unannotated values are marked SqlTainted -public @interface SqlDangerous {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSafe.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSafe.java deleted file mode 100644 index 11a2195c3f5..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSafe.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.checkerframework.checker.sqltainting.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultFor; -import org.checkerframework.framework.qual.LiteralKind; -import org.checkerframework.framework.qual.QualifierForLiterals; -import org.checkerframework.framework.qual.SubtypeOf; -import org.checkerframework.framework.qual.TypeUseLocation; - -/** - * Denotes a reference that is SQL-safe, i.e., originates from a trusted source or has been - * sanitized. - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(SqlDangerous.class) -@QualifierForLiterals(LiteralKind.STRING) -@DefaultFor(TypeUseLocation.LOWER_BOUND) -public @interface SqlSafe {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlQueryValue.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlUnsanitized.java similarity index 100% rename from checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlQueryValue.java rename to checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlUnsanitized.java diff --git a/checker/tests/sqltainting/SimpleSqlDangerous.java b/checker/tests/sqltainting/SimpleSqlDangerous.java deleted file mode 100644 index 74c10567eac..00000000000 --- a/checker/tests/sqltainting/SimpleSqlDangerous.java +++ /dev/null @@ -1,48 +0,0 @@ -import org.checkerframework.checker.sqltainting.qual.SqlSafe; - -public class SimpleSqlDangerous { - - void execute(@SqlSafe String s) {} - - void dangerous(String s) {} - - void stringLiteral() { - execute("ldskjfldj"); - dangerous("lksjdflkjdf"); - } - - void stringRef(String ref) { - // :: error: (argument) - execute(ref); // error - - dangerous(ref); - } - - void safeRef(@SqlSafe String ref) { - execute(ref); - dangerous(ref); - } - - void concatenation(@SqlSafe String s1, String s2) { - execute(s1 + s1); - execute(s1 += s1); - execute(s1 + "m"); - // :: error: (argument) - execute(s1 + s2); // error - - // :: error: (argument) - execute(s2 + s1); // error - // :: error: (argument) - execute(s2 + "m"); // error - // :: error: (argument) - execute(s2 + s2); // error - - dangerous(s1 + s1); - dangerous(s1 + "m"); - dangerous(s1 + s2); - - dangerous(s2 + s1); - dangerous(s2 + "m"); - dangerous(s2 + s2); - } -} From de5dbe0dc1b8f3f70e10f0764a684e165c570850 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 30 Jun 2024 13:56:27 -0700 Subject: [PATCH 010/184] Revised qualifiers --- .../checker/sqltainting/qual/PolySqlQueryValue.java | 2 +- .../checker/sqltainting/qual/SqlSanitized.java | 6 +++--- .../checker/sqltainting/qual/SqlUnsanitized.java | 2 +- .../sqltainting/SqlTaintingAnnotatedTypeFactory.java | 1 - .../checker/sqltainting/SqlTaintingChecker.java | 1 - 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlQueryValue.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlQueryValue.java index 6bc2b8c940b..9071a50778b 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlQueryValue.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlQueryValue.java @@ -15,5 +15,5 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@PolymorphicQualifier(SqlQueryValue.class) +@PolymorphicQualifier(SqlUnsanitized.class) public @interface PolySqlQueryValue {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSanitized.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSanitized.java index 4a625ce4cb7..e63f3ea3f05 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSanitized.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSanitized.java @@ -12,7 +12,7 @@ /** * Denotes a value to be used in a SQL query that has been sanitized (i.e. non-alphanumeric - * characters escaped as necessary) and is thus safe for SQL query use. + * characters escaped as necessary) and is thus safe to be embedded as a value in a SQL query. * *

All empty Strings and String literals consisting solely of alphanumeric characters, * whitespace, and backslash-escaped sensitive characters (i.e. single/double quotes, backslashes, @@ -21,7 +21,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(SqlQueryValue.class) -@QualifierForLiterals(stringPatterns = "^(\\w|\\s|\\\\'|\\\\\"|\\\\\\\\|\\\\-|\\\\%|\\\\_)*$") +@SubtypeOf(SqlUnsanitized.class) +@QualifierForLiterals(stringPatterns = "^(\\w|\\s|(\\\\[-'\"\\\\%_])*)*$") @DefaultFor(TypeUseLocation.LOWER_BOUND) public @interface SqlSanitized {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlUnsanitized.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlUnsanitized.java index aa9c9883ab0..f446c06baa5 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlUnsanitized.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlUnsanitized.java @@ -19,4 +19,4 @@ @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf({}) @DefaultQualifierInHierarchy -public @interface SqlQueryValue {} +public @interface SqlUnsanitized {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java index 7e95332cfa3..83901f9a9a3 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java @@ -11,7 +11,6 @@ /** Annotated type factory for the SQL Tainting Checker. */ public class SqlTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { - /** The {@code @}{@link SqlSanitized} annotation mirror. */ private final AnnotationMirror SQLSANITIZED; diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java index 0ad0bed1ad0..b520463b292 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java @@ -11,6 +11,5 @@ * * @checker_framework.manual #tainting-checker Tainting Checker */ - @SuppressWarningsPrefix({"sqlsanitized", "sqltainting"}) public class SqlTaintingChecker extends BaseTypeChecker {} From baa3be79aef7968818489e0259c71db86b36a5ef Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Wed, 3 Jul 2024 12:52:58 -0700 Subject: [PATCH 011/184] Revised documentation for type checker --- .../sqltainting/SqlTaintingAnnotatedTypeFactory.java | 2 +- .../checker/sqltainting/SqlTaintingChecker.java | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java index 83901f9a9a3..a26fc7c1874 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java @@ -20,7 +20,7 @@ public class SqlTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { /** * Creates a {@link SqlTaintingAnnotatedTypeFactory}. * - * @param checker the tainting checker + * @param checker the SQL tainting checker */ public SqlTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java index b520463b292..e9480d35473 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java @@ -4,12 +4,11 @@ import org.checkerframework.framework.source.SuppressWarningsPrefix; /** - * A type-checker plug-in for the Tainting type system qualifier that finds (and verifies the - * absence of) trust bugs. + * A type-checker plug-in for the SQL Tainting type system qualifier that finds (and verifies the + * absence of) SQL injection bugs in embedded query values. * - *

It verifies that only verified values are trusted and that user-input is sanitized before use. - * - * @checker_framework.manual #tainting-checker Tainting Checker + *

It verifies that only SQL-safe embedded query values are trusted and that user input is + * sanitized before use. */ @SuppressWarningsPrefix({"sqlsanitized", "sqltainting"}) public class SqlTaintingChecker extends BaseTypeChecker {} From c122359eb8135db12fed7b8a1a812e1360bc86d2 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Wed, 3 Jul 2024 14:03:48 -0700 Subject: [PATCH 012/184] Stub file for base64 encoding --- .../sqltainting/BCryptPasswordEncoder.astub | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 checker/src/main/java/org/checkerframework/checker/sqltainting/BCryptPasswordEncoder.astub diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/BCryptPasswordEncoder.astub b/checker/src/main/java/org/checkerframework/checker/sqltainting/BCryptPasswordEncoder.astub new file mode 100644 index 00000000000..23e336a95ee --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/sqltainting/BCryptPasswordEncoder.astub @@ -0,0 +1,14 @@ +package org.springframework.security.crypto.bcrypt; + +import java.security.SecureRandom; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.security.crypto.password.PasswordEncoder; + +import org.checkerframework.checker.sqltainting.qual.SqlSanitized; + +public class BCryptPasswordEncoder implements PasswordEncoder { + @SqlSanitized String encode(CharSequence rawPassword); +} From 74218575af936abb31a824df16c9bc391f0d006b Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Fri, 5 Jul 2024 12:41:58 -0700 Subject: [PATCH 013/184] Stub file to require sanitized query string in executeQuery --- .../checkerframework/checker/sqltainting/Statement.astub | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 checker/src/main/java/org/checkerframework/checker/sqltainting/Statement.astub diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/Statement.astub b/checker/src/main/java/org/checkerframework/checker/sqltainting/Statement.astub new file mode 100644 index 00000000000..3f12141abaa --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/sqltainting/Statement.astub @@ -0,0 +1,9 @@ +package java.sql; + +import java.util.regex.Pattern; + +import org.checkerframework.checker.sqltainting.qual.SqlSanitized; + +public interface Statement extends Wrapper, AutoCloseable { + ResultSet executeQuery(@SqlSanitized String var1) throws SQLException; +} From 00819a9f9936de2a996da100f04433dc3fef98be Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 9 Jul 2024 12:14:00 -0700 Subject: [PATCH 014/184] Created sqlquerytainting directory --- .../SqlQueryTaintingAnnotatedTypeFactory.java | 36 +++++++++++++++++++ .../SqlQueryTaintingChecker.java | 14 ++++++++ .../SqlQueryTaintingVisitor.java | 28 +++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java create mode 100644 checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java create mode 100644 checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java new file mode 100644 index 00000000000..a26fc7c1874 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -0,0 +1,36 @@ +package org.checkerframework.checker.sqltainting; + +import java.util.Set; +import javax.lang.model.element.AnnotationMirror; +import org.checkerframework.checker.sqltainting.qual.SqlSanitized; +import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; +import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.javacutil.AnnotationBuilder; +import org.checkerframework.javacutil.AnnotationMirrorSet; + +/** Annotated type factory for the SQL Tainting Checker. */ +public class SqlTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { + + /** The {@code @}{@link SqlSanitized} annotation mirror. */ + private final AnnotationMirror SQLSANITIZED; + + /** A singleton set containing the {@code @}{@link SqlSanitized} annotation mirror. */ + private final AnnotationMirrorSet setOfSqlSanitized; + + /** + * Creates a {@link SqlTaintingAnnotatedTypeFactory}. + * + * @param checker the SQL tainting checker + */ + public SqlTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { + super(checker); + this.SQLSANITIZED = AnnotationBuilder.fromClass(getElementUtils(), SqlSanitized.class); + this.setOfSqlSanitized = AnnotationMirrorSet.singleton(SQLSANITIZED); + postInit(); + } + + @Override + protected Set getEnumConstructorQualifiers() { + return setOfSqlSanitized; + } +} diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java new file mode 100644 index 00000000000..f4559454404 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java @@ -0,0 +1,14 @@ +package org.checkerframework.checker.sqlquerytainting; + +import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.framework.source.SuppressWarningsPrefix; + +/** + * A type-checker plug-in for the SQL Tainting type system qualifier that finds (and verifies the + * absence of) SQL injection bugs in embedded query values. + * + *

It verifies that only SQL-safe embedded query values are trusted and that user input is + * sanitized before use. + */ +@SuppressWarningsPrefix({"sqlquerysanitized", "sqlquerytainting"}) +public class SqlTaintingChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java new file mode 100644 index 00000000000..e0435e0f440 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java @@ -0,0 +1,28 @@ +package org.checkerframework.checker.sqlquerytainting; + +import javax.lang.model.element.ExecutableElement; +import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; +import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.common.basetype.BaseTypeVisitor; +import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType; + +/** Visitor for the {@link SqlTaintingChecker}. */ +public class SqlTaintingVisitor extends BaseTypeVisitor { + + /** + * Creates a {@link SqlTaintingVisitor}. + * + * @param checker the checker that uses this visitor + */ + public SqlTaintingVisitor(BaseTypeChecker checker) { + super(checker); + } + + /** + * Don't check that the constructor result is top. Checking that the super() or this() call is a + * subtype of the constructor result is sufficient. + */ + @Override + protected void checkConstructorResult( + AnnotatedExecutableType constructorType, ExecutableElement constructorElement) {} +} From 61eb2b375614f474b7776083bbe3bfaf65b555a5 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 9 Jul 2024 12:16:27 -0700 Subject: [PATCH 015/184] Renamed sqlquerytainting files --- .../SqlQueryTaintingAnnotatedTypeFactory.java | 11 +++++------ .../sqlquerytainting/SqlQueryTaintingChecker.java | 2 +- .../sqlquerytainting/SqlQueryTaintingVisitor.java | 8 ++++---- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java index a26fc7c1874..46b5ec71889 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -1,15 +1,14 @@ -package org.checkerframework.checker.sqltainting; +package org.checkerframework.checker.sqlquerytainting; import java.util.Set; import javax.lang.model.element.AnnotationMirror; -import org.checkerframework.checker.sqltainting.qual.SqlSanitized; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.javacutil.AnnotationBuilder; import org.checkerframework.javacutil.AnnotationMirrorSet; -/** Annotated type factory for the SQL Tainting Checker. */ -public class SqlTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { +/** Annotated type factory for the SQL Query Tainting Checker. */ +public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { /** The {@code @}{@link SqlSanitized} annotation mirror. */ private final AnnotationMirror SQLSANITIZED; @@ -18,11 +17,11 @@ public class SqlTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { private final AnnotationMirrorSet setOfSqlSanitized; /** - * Creates a {@link SqlTaintingAnnotatedTypeFactory}. + * Creates a {@link SqlQueryTaintingAnnotatedTypeFactory}. * * @param checker the SQL tainting checker */ - public SqlTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { + public SqlQueryTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); this.SQLSANITIZED = AnnotationBuilder.fromClass(getElementUtils(), SqlSanitized.class); this.setOfSqlSanitized = AnnotationMirrorSet.singleton(SQLSANITIZED); diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java index f4559454404..b69319c5d2a 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java @@ -11,4 +11,4 @@ * sanitized before use. */ @SuppressWarningsPrefix({"sqlquerysanitized", "sqlquerytainting"}) -public class SqlTaintingChecker extends BaseTypeChecker {} +public class SqlQueryTaintingChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java index e0435e0f440..4b0aba79624 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java @@ -6,15 +6,15 @@ import org.checkerframework.common.basetype.BaseTypeVisitor; import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType; -/** Visitor for the {@link SqlTaintingChecker}. */ -public class SqlTaintingVisitor extends BaseTypeVisitor { +/** Visitor for the {@link SqlQueryTaintingChecker}. */ +public class SqlQueryTaintingVisitor extends BaseTypeVisitor { /** - * Creates a {@link SqlTaintingVisitor}. + * Creates a {@link SqlQueryTaintingVisitor}. * * @param checker the checker that uses this visitor */ - public SqlTaintingVisitor(BaseTypeChecker checker) { + public SqlQueryTaintingVisitor(BaseTypeChecker checker) { super(checker); } From 07b769039be8a42a187af5e242f05221d8677bd3 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 9 Jul 2024 14:20:21 -0700 Subject: [PATCH 016/184] Added qualifiers SqlQueryComplete, SqlQuerySnippet, SqlQueryUnknown, and SqlSanitizedUser --- .../sqlquerytainting/SqlQueryComplete.java | 16 +++++++ .../sqlquerytainting/SqlQuerySnippet.java | 15 ++++++ .../sqlquerytainting/SqlQueryUnknown.java | 13 +++++ .../sqlquerytainting/SqlSanitizedUser.java | 21 ++++++++ .../SqlQueryTaintingAnnotatedTypeFactory.java | 14 +++--- .../sqlquerytainting/SimpleSqlQuery.java | 48 +++++++++++++++++++ 6 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryComplete.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQuerySnippet.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryUnknown.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlSanitizedUser.java create mode 100644 checker/tests/sqlquerytainting/SimpleSqlQuery.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryComplete.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryComplete.java new file mode 100644 index 00000000000..ce32d7bb90e --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryComplete.java @@ -0,0 +1,16 @@ +package org.checkerframework.checker.sqlquerytainting; + +import java.lang.annotation.*; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Denotes a String that represents a complete, safe SQL query to be executed. Safety from SQL + * injection vulnerabilities is guaranteed as all components of @SqlQueryComplete Strings either + * originate entirely within the author's code, or originate from user input and have been + * sanitized. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(SqlQueryUnknown.class) +public @interface SqlQueryComplete {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQuerySnippet.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQuerySnippet.java new file mode 100644 index 00000000000..ef4feb8469d --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQuerySnippet.java @@ -0,0 +1,15 @@ +package org.checkerframework.checker.sqlquerytainting; + +import java.lang.annotation.*; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Denotes a String that comprises part of a SQL query - commonly, it may be a SQL command fragment, + * a command requiring user input concatenation, or a command with user input requiring end quote + * concatenation. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(SqlQueryUnknown.class) +public @interface SqlQuerySnippet {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryUnknown.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryUnknown.java new file mode 100644 index 00000000000..1c9a229244a --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryUnknown.java @@ -0,0 +1,13 @@ +package org.checkerframework.checker.sqlquerytainting; + +import java.lang.annotation.*; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.SubtypeOf; + +/** Represents the top of the SQL query tainting qualifier hierarchy. */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({}) +@DefaultQualifierInHierarchy +public @interface SqlQueryUnknown {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlSanitizedUser.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlSanitizedUser.java new file mode 100644 index 00000000000..e75ae66f62a --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlSanitizedUser.java @@ -0,0 +1,21 @@ +package org.checkerframework.checker.sqlquerytainting; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.QualifierForLiterals; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Denotes a value to be used in a SQL query originating from user input that has been sanitized + * (i.e. non-alphanumeric characters escaped as necessary) and is thus safe to be embedded as a + * value in a SQL query. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(SqlQueryUnknown.class) +@QualifierForLiterals(stringPatterns = "^(\\w|\\s|(\\\\[-'\"\\\\%_])*)*$") +public @interface SqlSanitizedUser {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java index 46b5ec71889..c785754fe9b 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -10,11 +10,11 @@ /** Annotated type factory for the SQL Query Tainting Checker. */ public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { - /** The {@code @}{@link SqlSanitized} annotation mirror. */ - private final AnnotationMirror SQLSANITIZED; + /** The {@code @}{@link SqlSanitizedUser} annotation mirror. */ + private final AnnotationMirror SQLSANITIZEDUSER; - /** A singleton set containing the {@code @}{@link SqlSanitized} annotation mirror. */ - private final AnnotationMirrorSet setOfSqlSanitized; + /** A singleton set containing the {@code @}{@link SqlSanitizedUser} annotation mirror. */ + private final AnnotationMirrorSet setOfSqlSanitizedUser; /** * Creates a {@link SqlQueryTaintingAnnotatedTypeFactory}. @@ -23,13 +23,13 @@ public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFacto */ public SqlQueryTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); - this.SQLSANITIZED = AnnotationBuilder.fromClass(getElementUtils(), SqlSanitized.class); - this.setOfSqlSanitized = AnnotationMirrorSet.singleton(SQLSANITIZED); + this.SQLSANITIZEDUSER = AnnotationBuilder.fromClass(getElementUtils(), SqlSanitizedUser.class); + this.setOfSqlSanitizedUser = AnnotationMirrorSet.singleton(SQLSANITIZEDUSER); postInit(); } @Override protected Set getEnumConstructorQualifiers() { - return setOfSqlSanitized; + return setOfSqlSanitizedUser; } } diff --git a/checker/tests/sqlquerytainting/SimpleSqlQuery.java b/checker/tests/sqlquerytainting/SimpleSqlQuery.java new file mode 100644 index 00000000000..4302a57e28a --- /dev/null +++ b/checker/tests/sqlquerytainting/SimpleSqlQuery.java @@ -0,0 +1,48 @@ +import org.checkerframework.checker.sqltainting.qual.SqlSanitized; + +public class SimpleSqlQueryValue { + + void execute(@SqlSanitized String s) {} + + void unsanitized(String s) {} + + void stringLiteral() { + execute("ldskjfldj"); + unsanitized("lksjdflkjdf"); + } + + void stringRef(String ref) { + // :: error: (argument) + execute(ref); // error + + unsanitized(ref); + } + + void safeRef(@SqlSanitized String ref) { + execute(ref); + unsanitized(ref); + } + + void concatenation(@SqlSanitized String s1, String s2) { + execute(s1 + s1); + execute(s1 += s1); + execute(s1 + "m"); + // :: error: (argument) + execute(s1 + s2); // error + + // :: error: (argument) + execute(s2 + s1); // error + // :: error: (argument) + execute(s2 + "m"); // error + // :: error: (argument) + execute(s2 + s2); // error + + unsanitized(s1 + s1); + unsanitized(s1 + "m"); + unsanitized(s1 + s2); + + unsanitized(s2 + s1); + unsanitized(s2 + "m"); + unsanitized(s2 + s2); + } +} From c606a189f373cf039eb4fda736a3c0beebc3e9c2 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 11 Jul 2024 16:46:26 -0700 Subject: [PATCH 017/184] Revised qualifiers to SqlEvenQuotes, SqlOddQuotes, SqlQuoteless --- .../sqlquerytainting/SqlQueryComplete.java | 16 ----------- .../sqlquerytainting/SqlQuerySnippet.java | 15 ----------- .../sqlquerytainting/SqlSanitizedUser.java | 21 --------------- .../sqlquerytainting/qual/SqlEvenQuotes.java | 22 +++++++++++++++ .../sqlquerytainting/qual/SqlOddQuotes.java | 27 +++++++++++++++++++ .../{ => qual}/SqlQueryUnknown.java | 2 +- .../sqlquerytainting/qual/SqlQuoteless.java | 26 ++++++++++++++++++ .../SqlQueryTaintingAnnotatedTypeFactory.java | 1 + 8 files changed, 77 insertions(+), 53 deletions(-) delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryComplete.java delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQuerySnippet.java delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlSanitizedUser.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java rename checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/{ => qual}/SqlQueryUnknown.java (87%) create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryComplete.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryComplete.java deleted file mode 100644 index ce32d7bb90e..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryComplete.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.checkerframework.checker.sqlquerytainting; - -import java.lang.annotation.*; -import org.checkerframework.framework.qual.SubtypeOf; - -/** - * Denotes a String that represents a complete, safe SQL query to be executed. Safety from SQL - * injection vulnerabilities is guaranteed as all components of @SqlQueryComplete Strings either - * originate entirely within the author's code, or originate from user input and have been - * sanitized. - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(SqlQueryUnknown.class) -public @interface SqlQueryComplete {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQuerySnippet.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQuerySnippet.java deleted file mode 100644 index ef4feb8469d..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQuerySnippet.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.checkerframework.checker.sqlquerytainting; - -import java.lang.annotation.*; -import org.checkerframework.framework.qual.SubtypeOf; - -/** - * Denotes a String that comprises part of a SQL query - commonly, it may be a SQL command fragment, - * a command requiring user input concatenation, or a command with user input requiring end quote - * concatenation. - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(SqlQueryUnknown.class) -public @interface SqlQuerySnippet {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlSanitizedUser.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlSanitizedUser.java deleted file mode 100644 index e75ae66f62a..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlSanitizedUser.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.checkerframework.checker.sqlquerytainting; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.QualifierForLiterals; -import org.checkerframework.framework.qual.SubtypeOf; - -/** - * Denotes a value to be used in a SQL query originating from user input that has been sanitized - * (i.e. non-alphanumeric characters escaped as necessary) and is thus safe to be embedded as a - * value in a SQL query. - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(SqlQueryUnknown.class) -@QualifierForLiterals(stringPatterns = "^(\\w|\\s|(\\\\[-'\"\\\\%_])*)*$") -public @interface SqlSanitizedUser {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java new file mode 100644 index 00000000000..f3138e84fd8 --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java @@ -0,0 +1,22 @@ +package org.checkerframework.checker.sqlquerytainting.qual; + +import java.lang.annotation.*; +import org.checkerframework.framework.qual.QualifierForLiterals; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Used to denote a String that comprises part of a SQL query and + * contains an even number of unescaped single quotes – i.e., there + * must be an even number of ‘ characters in a SqlEvenQuotes String + * that are not preceded immediately by a / character. SQLEvenQuotes + * Strings are safe to be passed to query execution methods. + * + * Common use cases include: complete SQL queries, such as “SELECT * + * FROM table WHERE field = ‘value’”. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(SqlQueryUnknown.class) +@QualifierForLiterals(stringPatterns = "^(([^\\\\\\']|\\\\.)*\\'){2}([^\\\\\\']|(\\'([^\\\\\\']|\\\\.)*\\')|\\\\.)*\\\\?$") +public @interface SqlEvenQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java new file mode 100644 index 00000000000..70bdf8b6d6a --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java @@ -0,0 +1,27 @@ +package org.checkerframework.checker.sqlquerytainting.qual; + +import java.lang.annotation.*; +import org.checkerframework.framework.qual.QualifierForLiterals; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Used to denote a String that comprises part of a SQL query and + * contains an odd number of unescaped single quotes – i.e., there + * must be an odd number of ‘ characters in a SqlOddQuotes String + * that are not preceded immediately by a / character. SQLOddQuotes + * Strings are not safe to be passed to query execution methods. + * + * Common use cases include: SQL query fragments to be concatenated + * with user input, such as “SELECT * FROM table WHERE field = ‘”; + * SQL query fragments containing user input but missing an ending + * single quote, such as “SELECT * FROM table WHERE field = ‘value”; + * connecting punctuation, such as “’, “; and any combinations of the + * above with paired-off single quotes, such as “SELECT * FROM table + * WHERE field1 = ‘value1’, field2 = ‘value2’, field3 = ‘”. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(SqlQueryUnknown.class) +@QualifierForLiterals(stringPatterns = "^(([^\\\\\\']|\\\\.)*\\')([^\\\\\\']|\\'([^\\\\\\']|\\\\.)*\\'|\\\\.)*\\\\?$") +public @interface SqlOddQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryUnknown.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java similarity index 87% rename from checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryUnknown.java rename to checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java index 1c9a229244a..80962285d2c 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryUnknown.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.sqlquerytainting; +package org.checkerframework.checker.sqlquerytainting.qual; import java.lang.annotation.*; import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java new file mode 100644 index 00000000000..d6af47df514 --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java @@ -0,0 +1,26 @@ +package org.checkerframework.checker.sqlquerytainting.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.QualifierForLiterals; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Used to denote a String that comprises part of a SQL query and + * contains exactly zero unescaped single quotes – i.e., all occurrences + * of the ‘ character in such a String are preceded immediately by a / + * character. SQLQuoteless Strings are safe to be passed to query execution + * methods. + * + * Common use cases include SQL query fragments such as “SELECT * FROM” + * and properly sanitized user input. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(SqlQueryUnknown.class) +@QualifierForLiterals(stringPatterns = "^([^\\']|(\\\\'))*$") +public @interface SqlQuoteless {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java index c785754fe9b..15a7d2247b4 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -2,6 +2,7 @@ import java.util.Set; import javax.lang.model.element.AnnotationMirror; +import org.checkerframework.checker.sqlquerytainting.qual.SqlSanitizedUser; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.javacutil.AnnotationBuilder; From 4acc56dc4186008d88ae976c98442599174a7a13 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 11 Jul 2024 16:51:04 -0700 Subject: [PATCH 018/184] Revised qualifiers to SqlOddQuotes, SqlEvenQuotes, SqlQuoteless --- .../sqlquerytainting/qual/SqlEvenQuotes.java | 17 ++++++------- .../sqlquerytainting/qual/SqlOddQuotes.java | 24 +++++++++---------- .../sqlquerytainting/qual/SqlQuoteless.java | 11 ++++----- 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java index f3138e84fd8..fe5c3c8d6ba 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java @@ -5,18 +5,19 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * Used to denote a String that comprises part of a SQL query and - * contains an even number of unescaped single quotes – i.e., there - * must be an even number of ‘ characters in a SqlEvenQuotes String - * that are not preceded immediately by a / character. SQLEvenQuotes - * Strings are safe to be passed to query execution methods. + * Used to denote a String that comprises part of a SQL query and contains an even number of + * unescaped single quotes – i.e., there must be an even number of ‘ characters in a SqlEvenQuotes + * String that are not preceded immediately by a / character. SQLEvenQuotes Strings are safe to be + * passed to query execution methods. * - * Common use cases include: complete SQL queries, such as “SELECT * - * FROM table WHERE field = ‘value’”. + *

Common use cases include: complete SQL queries, such as “SELECT * FROM table WHERE field = + * ‘value’”. */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQueryUnknown.class) -@QualifierForLiterals(stringPatterns = "^(([^\\\\\\']|\\\\.)*\\'){2}([^\\\\\\']|(\\'([^\\\\\\']|\\\\.)*\\')|\\\\.)*\\\\?$") +@QualifierForLiterals( + stringPatterns = + "^(([^\\\\\\']|\\\\.)*\\'){2}([^\\\\\\']|(\\'([^\\\\\\']|\\\\.)*\\')|\\\\.)*\\\\?$") public @interface SqlEvenQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java index 70bdf8b6d6a..94c7c804858 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java @@ -5,23 +5,21 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * Used to denote a String that comprises part of a SQL query and - * contains an odd number of unescaped single quotes – i.e., there - * must be an odd number of ‘ characters in a SqlOddQuotes String - * that are not preceded immediately by a / character. SQLOddQuotes - * Strings are not safe to be passed to query execution methods. + * Used to denote a String that comprises part of a SQL query and contains an odd number of + * unescaped single quotes – i.e., there must be an odd number of ‘ characters in a SqlOddQuotes + * String that are not preceded immediately by a / character. SQLOddQuotes Strings are not safe to + * be passed to query execution methods. * - * Common use cases include: SQL query fragments to be concatenated - * with user input, such as “SELECT * FROM table WHERE field = ‘”; - * SQL query fragments containing user input but missing an ending - * single quote, such as “SELECT * FROM table WHERE field = ‘value”; - * connecting punctuation, such as “’, “; and any combinations of the - * above with paired-off single quotes, such as “SELECT * FROM table - * WHERE field1 = ‘value1’, field2 = ‘value2’, field3 = ‘”. + *

Common use cases include: SQL query fragments to be concatenated with user input, such as + * “SELECT * FROM table WHERE field = ‘”; SQL query fragments containing user input but missing an + * ending single quote, such as “SELECT * FROM table WHERE field = ‘value”; connecting punctuation, + * such as “’, “; and any combinations of the above with paired-off single quotes, such as “SELECT * + * FROM table WHERE field1 = ‘value1’, field2 = ‘value2’, field3 = ‘”. */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQueryUnknown.class) -@QualifierForLiterals(stringPatterns = "^(([^\\\\\\']|\\\\.)*\\')([^\\\\\\']|\\'([^\\\\\\']|\\\\.)*\\'|\\\\.)*\\\\?$") +@QualifierForLiterals( + stringPatterns = "^(([^\\\\\\']|\\\\.)*\\')([^\\\\\\']|\\'([^\\\\\\']|\\\\.)*\\'|\\\\.)*\\\\?$") public @interface SqlOddQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java index d6af47df514..6db1bd62691 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java @@ -9,14 +9,13 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * Used to denote a String that comprises part of a SQL query and - * contains exactly zero unescaped single quotes – i.e., all occurrences - * of the ‘ character in such a String are preceded immediately by a / - * character. SQLQuoteless Strings are safe to be passed to query execution + * Used to denote a String that comprises part of a SQL query and contains exactly zero unescaped + * single quotes – i.e., all occurrences of the ‘ character in such a String are preceded + * immediately by a / character. SQLQuoteless Strings are safe to be passed to query execution * methods. * - * Common use cases include SQL query fragments such as “SELECT * FROM” - * and properly sanitized user input. + *

Common use cases include SQL query fragments such as “SELECT * FROM” and properly sanitized + * user input. */ @Documented @Retention(RetentionPolicy.RUNTIME) From 2843a300b386c59ae9c29054075f0e3ce69f1a6b Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Fri, 12 Jul 2024 15:02:29 -0700 Subject: [PATCH 019/184] Revised documentation and implementation of SQL query qualifiers: combined SqlQuoteless and SqlEvenQuotes; revised documentations --- .../sqlquerytainting/qual/SqlEvenQuotes.java | 17 ++++++------- .../sqlquerytainting/qual/SqlOddQuotes.java | 10 ++++---- .../qual/SqlQueryUnknown.java | 8 +++++- .../sqlquerytainting/qual/SqlQuoteless.java | 25 ------------------- 4 files changed, 20 insertions(+), 40 deletions(-) delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java index fe5c3c8d6ba..abed915b334 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java @@ -5,19 +5,18 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * Used to denote a String that comprises part of a SQL query and contains an even number of - * unescaped single quotes – i.e., there must be an even number of ‘ characters in a SqlEvenQuotes - * String that are not preceded immediately by a / character. SQLEvenQuotes Strings are safe to be - * passed to query execution methods. + * SqlEvenQuotes: Used to denote a String that comprises part of a SQL query and contains either + * zero or an even number of unescaped single quotes – i.e., there must be either zero or an even + * number of ‘ characters in a SqlEvenQuotes String that are not preceded immediately by a \ + * character. SqlEvenQuotes Strings are syntactical and safe to be passed to query execution + * methods. * - *

Common use cases include: complete SQL queries, such as “SELECT * FROM table WHERE field = - * ‘value’”. + *

Common use cases include: SQL query fragments, such as “SELECT * FROM”; properly sanitized + * user input; and complete SQL queries, such as “SELECT * FROM table WHERE field = ‘value’”. */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQueryUnknown.class) -@QualifierForLiterals( - stringPatterns = - "^(([^\\\\\\']|\\\\.)*\\'){2}([^\\\\\\']|(\\'([^\\\\\\']|\\\\.)*\\')|\\\\.)*\\\\?$") +@QualifierForLiterals(stringPatterns = "^((([^\\\\']|\\\\.)*'){2})*([^\\\\']|\\\\.)*\\\\?$") public @interface SqlEvenQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java index 94c7c804858..90bd29e2033 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java @@ -5,10 +5,10 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * Used to denote a String that comprises part of a SQL query and contains an odd number of - * unescaped single quotes – i.e., there must be an odd number of ‘ characters in a SqlOddQuotes - * String that are not preceded immediately by a / character. SQLOddQuotes Strings are not safe to - * be passed to query execution methods. + * SqlOddQuotes: Used to denote a String that comprises part of a SQL query and contains an odd + * number of unescaped single quotes – i.e., there must be an odd number of ‘ characters in a + * SqlOddQuotes String that are not preceded immediately by a \ character. SqlOddQuotes Strings are + * not syntactical to be passed to query execution methods. * *

Common use cases include: SQL query fragments to be concatenated with user input, such as * “SELECT * FROM table WHERE field = ‘”; SQL query fragments containing user input but missing an @@ -21,5 +21,5 @@ @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQueryUnknown.class) @QualifierForLiterals( - stringPatterns = "^(([^\\\\\\']|\\\\.)*\\')([^\\\\\\']|\\'([^\\\\\\']|\\\\.)*\\'|\\\\.)*\\\\?$") + stringPatterns = "^(([^\\\\']|\\\\.)*')([^\\\\']|'([^\\\\']|\\\\.)*'|\\\\.)*\\\\?$") public @interface SqlOddQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java index 80962285d2c..76582b57758 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java @@ -4,7 +4,13 @@ import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; import org.checkerframework.framework.qual.SubtypeOf; -/** Represents the top of the SQL query tainting qualifier hierarchy. */ +/** + * Represents the top of the SQL query tainting qualifier hierarchy. Used to denote a String that + * comprises part of a SQL query, the quoting of which is unknown. SqlQueryUnknown Strings are SQL + * injection vulnerabilities and thus unsafe to be passed to query execution methods. + * + *

Common use cases include unsanitized user input. + */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java deleted file mode 100644 index 6db1bd62691..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.checkerframework.checker.sqlquerytainting.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.QualifierForLiterals; -import org.checkerframework.framework.qual.SubtypeOf; - -/** - * Used to denote a String that comprises part of a SQL query and contains exactly zero unescaped - * single quotes – i.e., all occurrences of the ‘ character in such a String are preceded - * immediately by a / character. SQLQuoteless Strings are safe to be passed to query execution - * methods. - * - *

Common use cases include SQL query fragments such as “SELECT * FROM” and properly sanitized - * user input. - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(SqlQueryUnknown.class) -@QualifierForLiterals(stringPatterns = "^([^\\']|(\\\\'))*$") -public @interface SqlQuoteless {} From 1f6dd09789ffa418e49c7830d7e6a202f4cdcb25 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Fri, 12 Jul 2024 15:03:05 -0700 Subject: [PATCH 020/184] Added type concatenation rules for SQL query qualifiers --- .../SqlQueryTaintingAnnotatedTypeFactory.java | 70 ++++++++++++++++--- 1 file changed, 62 insertions(+), 8 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java index 15a7d2247b4..8249ebdc8a1 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -1,21 +1,34 @@ package org.checkerframework.checker.sqlquerytainting; +import com.sun.source.tree.BinaryTree; import java.util.Set; import javax.lang.model.element.AnnotationMirror; -import org.checkerframework.checker.sqlquerytainting.qual.SqlSanitizedUser; +import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; +import org.checkerframework.checker.sqlquerytainting.qual.SqlOddQuotes; +import org.checkerframework.checker.sqlquerytainting.qual.SqlQueryUnknown; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.framework.type.AnnotatedTypeFactory; +import org.checkerframework.framework.type.AnnotatedTypeMirror; +import org.checkerframework.framework.type.treeannotator.TreeAnnotator; import org.checkerframework.javacutil.AnnotationBuilder; import org.checkerframework.javacutil.AnnotationMirrorSet; +import org.checkerframework.javacutil.TreeUtils; /** Annotated type factory for the SQL Query Tainting Checker. */ public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { - /** The {@code @}{@link SqlSanitizedUser} annotation mirror. */ - private final AnnotationMirror SQLSANITIZEDUSER; + /** The {@code @}{@link SqlEvenQuotes} annotation mirror. */ + private final AnnotationMirror SQLEVENQUOTES; - /** A singleton set containing the {@code @}{@link SqlSanitizedUser} annotation mirror. */ - private final AnnotationMirrorSet setOfSqlSanitizedUser; + /** The {@code @}{@link SqlOddQuotes} annotation mirror. */ + private final AnnotationMirror SQLODDQUOTES; + + /** The {@code @}{@link SqlQueryUnknown} annotation mirror. */ + private final AnnotationMirror SQLQUERYUNKNOWN; + + /** A singleton set containing the {@code @}{@link SqlEvenQuotes} annotation mirror. */ + private final AnnotationMirrorSet setOfSqlEvenQuotes; /** * Creates a {@link SqlQueryTaintingAnnotatedTypeFactory}. @@ -24,13 +37,54 @@ public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFacto */ public SqlQueryTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); - this.SQLSANITIZEDUSER = AnnotationBuilder.fromClass(getElementUtils(), SqlSanitizedUser.class); - this.setOfSqlSanitizedUser = AnnotationMirrorSet.singleton(SQLSANITIZEDUSER); + this.SQLEVENQUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlEvenQuotes.class); + this.SQLODDQUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlOddQuotes.class); + this.SQLQUERYUNKNOWN = AnnotationBuilder.fromClass(getElementUtils(), SqlQueryUnknown.class); + this.setOfSqlEvenQuotes = AnnotationMirrorSet.singleton(SQLEVENQUOTES); postInit(); } @Override protected Set getEnumConstructorQualifiers() { - return setOfSqlSanitizedUser; + return setOfSqlEvenQuotes; + } + + private class SqlQueryTaintingTreeAnnotator extends TreeAnnotator { + public SqlQueryTaintingTreeAnnotator(AnnotatedTypeFactory atypeFactory) { + super(atypeFactory); + } + + @Override + public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { + if (!type.hasPrimaryAnnotationInHierarchy(SQLQUERYUNKNOWN) + && TreeUtils.isStringConcatenation(tree)) { + AnnotatedTypeMirror leftType = getAnnotatedType(tree.getLeftOperand()); + AnnotatedTypeMirror rightType = getAnnotatedType(tree.getRightOperand()); + + if (leftType.hasPrimaryAnnotation(SQLQUERYUNKNOWN) + || rightType.hasPrimaryAnnotation(SQLQUERYUNKNOWN)) { + type.addAnnotation(SQLQUERYUNKNOWN); + return null; + } + + int leftParity = 0; + if (leftType.hasPrimaryAnnotation(SQLODDQUOTES)) { + leftParity = 1; + } + + int rightParity = 0; + if (rightType.hasPrimaryAnnotation(SQLODDQUOTES)) { + rightParity = 1; + } + + if (leftParity + rightParity % 2 == 0) { + type.addAnnotation(SQLEVENQUOTES); + } else { + type.addAnnotation(SQLODDQUOTES); + } + } + + return null; + } } } From e7cf5405187588d57760d365f4b15992844c0260 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Fri, 12 Jul 2024 15:54:48 -0700 Subject: [PATCH 021/184] Debugged SQL query type factory --- .../SqlQueryTaintingAnnotatedTypeFactory.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java index 8249ebdc8a1..2212cc046e4 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -10,6 +10,7 @@ import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.framework.type.AnnotatedTypeFactory; import org.checkerframework.framework.type.AnnotatedTypeMirror; +import org.checkerframework.framework.type.treeannotator.ListTreeAnnotator; import org.checkerframework.framework.type.treeannotator.TreeAnnotator; import org.checkerframework.javacutil.AnnotationBuilder; import org.checkerframework.javacutil.AnnotationMirrorSet; @@ -49,6 +50,12 @@ protected Set getEnumConstructorQualifiers() { return setOfSqlEvenQuotes; } + @Override + public TreeAnnotator createTreeAnnotator() { + return new ListTreeAnnotator( + new SqlQueryTaintingAnnotatedTypeFactory.SqlQueryTaintingTreeAnnotator(this)); + } + private class SqlQueryTaintingTreeAnnotator extends TreeAnnotator { public SqlQueryTaintingTreeAnnotator(AnnotatedTypeFactory atypeFactory) { super(atypeFactory); From 08ddda9057419b962bc1196d2a8fd0776e824c11 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Fri, 12 Jul 2024 15:55:10 -0700 Subject: [PATCH 022/184] Added SQL query bottom type --- .../sqlquerytainting/qual/SqlQueryBottom.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryBottom.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryBottom.java new file mode 100644 index 00000000000..8d58e4de03c --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryBottom.java @@ -0,0 +1,22 @@ +package org.checkerframework.checker.sqlquerytainting.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.DefaultFor; +import org.checkerframework.framework.qual.InvisibleQualifier; +import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TargetLocations; +import org.checkerframework.framework.qual.TypeUseLocation; + +/** Represents the bottom of the SQL query tainting qualifier hierarchy. */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@InvisibleQualifier +@SubtypeOf({SqlEvenQuotes.class, SqlOddQuotes.class}) +@DefaultFor(value = {TypeUseLocation.LOWER_BOUND}) +public @interface SqlQueryBottom {} From b9895724c05d5f8c0903e66f855927dbd4095491 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Fri, 12 Jul 2024 16:23:26 -0700 Subject: [PATCH 023/184] Added test files for SQL query tainting regex --- .../test/junit/SqlQueryTaintingTest.java | 24 ++++++++++ .../sqlquerytainting/SimpleSqlQuery.java | 48 ------------------- .../sqlquerytainting/SqlQualifierRegex.java | 12 +++++ 3 files changed, 36 insertions(+), 48 deletions(-) create mode 100644 checker/src/test/java/org/checkerframework/checker/test/junit/SqlQueryTaintingTest.java delete mode 100644 checker/tests/sqlquerytainting/SimpleSqlQuery.java create mode 100644 checker/tests/sqlquerytainting/SqlQualifierRegex.java diff --git a/checker/src/test/java/org/checkerframework/checker/test/junit/SqlQueryTaintingTest.java b/checker/src/test/java/org/checkerframework/checker/test/junit/SqlQueryTaintingTest.java new file mode 100644 index 00000000000..8f6d47e28f5 --- /dev/null +++ b/checker/src/test/java/org/checkerframework/checker/test/junit/SqlQueryTaintingTest.java @@ -0,0 +1,24 @@ +package org.checkerframework.checker.test.junit; + +import java.io.File; +import java.util.List; +import org.checkerframework.checker.sqlquerytainting.SqlQueryTaintingChecker; +import org.checkerframework.framework.test.CheckerFrameworkPerDirectoryTest; +import org.junit.runners.Parameterized.Parameters; + +public class SqlQueryTaintingTest extends CheckerFrameworkPerDirectoryTest { + + /** + * Create a TaintingTest. + * + * @param testFiles the files containing test code, which will be type-checked + */ + public SqlQueryTaintingTest(List testFiles) { + super(testFiles, SqlQueryTaintingChecker.class, "sqlquerytainting"); + } + + @Parameters + public static String[] getTestDirs() { + return new String[] {"sqlquerytainting", "all-systems"}; + } +} diff --git a/checker/tests/sqlquerytainting/SimpleSqlQuery.java b/checker/tests/sqlquerytainting/SimpleSqlQuery.java deleted file mode 100644 index 4302a57e28a..00000000000 --- a/checker/tests/sqlquerytainting/SimpleSqlQuery.java +++ /dev/null @@ -1,48 +0,0 @@ -import org.checkerframework.checker.sqltainting.qual.SqlSanitized; - -public class SimpleSqlQueryValue { - - void execute(@SqlSanitized String s) {} - - void unsanitized(String s) {} - - void stringLiteral() { - execute("ldskjfldj"); - unsanitized("lksjdflkjdf"); - } - - void stringRef(String ref) { - // :: error: (argument) - execute(ref); // error - - unsanitized(ref); - } - - void safeRef(@SqlSanitized String ref) { - execute(ref); - unsanitized(ref); - } - - void concatenation(@SqlSanitized String s1, String s2) { - execute(s1 + s1); - execute(s1 += s1); - execute(s1 + "m"); - // :: error: (argument) - execute(s1 + s2); // error - - // :: error: (argument) - execute(s2 + s1); // error - // :: error: (argument) - execute(s2 + "m"); // error - // :: error: (argument) - execute(s2 + s2); // error - - unsanitized(s1 + s1); - unsanitized(s1 + "m"); - unsanitized(s1 + s2); - - unsanitized(s2 + s1); - unsanitized(s2 + "m"); - unsanitized(s2 + s2); - } -} diff --git a/checker/tests/sqlquerytainting/SqlQualifierRegex.java b/checker/tests/sqlquerytainting/SqlQualifierRegex.java new file mode 100644 index 00000000000..e728b8b365a --- /dev/null +++ b/checker/tests/sqlquerytainting/SqlQualifierRegex.java @@ -0,0 +1,12 @@ +import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; +import org.checkerframework.checker.sqlquerytainting.qual.SqlOddQuotes; + +public class SqlQualifierRegex { + + void oddQuotes() { + // :: error: (argument) + @SqlOddQuotes String odd1 = ""; // error + + @SqlEvenQuotes String even1 = ""; + } +} From 2d490fad91edaad839fa9e2bdf6242afefc1eb56 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 12 Jul 2024 16:51:57 -0700 Subject: [PATCH 024/184] Update expected error --- checker/tests/sqlquerytainting/SqlQualifierRegex.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/checker/tests/sqlquerytainting/SqlQualifierRegex.java b/checker/tests/sqlquerytainting/SqlQualifierRegex.java index e728b8b365a..c3e901e77e2 100644 --- a/checker/tests/sqlquerytainting/SqlQualifierRegex.java +++ b/checker/tests/sqlquerytainting/SqlQualifierRegex.java @@ -4,8 +4,8 @@ public class SqlQualifierRegex { void oddQuotes() { - // :: error: (argument) - @SqlOddQuotes String odd1 = ""; // error + // :: error: (assignment) + @SqlOddQuotes String odd1 = ""; @SqlEvenQuotes String even1 = ""; } From 069bba1de5e5ff074a9b526fa745f7bfe2d6be60 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 12 Jul 2024 16:55:36 -0700 Subject: [PATCH 025/184] By convention, all-caps variables use `_` as a word separator --- .../SqlQueryTaintingAnnotatedTypeFactory.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java index 2212cc046e4..6fbda671239 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -20,13 +20,13 @@ public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { /** The {@code @}{@link SqlEvenQuotes} annotation mirror. */ - private final AnnotationMirror SQLEVENQUOTES; + private final AnnotationMirror SQL_EVEN_QUOTES; /** The {@code @}{@link SqlOddQuotes} annotation mirror. */ - private final AnnotationMirror SQLODDQUOTES; + private final AnnotationMirror SQL_ODD_QUOTES; /** The {@code @}{@link SqlQueryUnknown} annotation mirror. */ - private final AnnotationMirror SQLQUERYUNKNOWN; + private final AnnotationMirror SQL_QUERY_UNKNOWN; /** A singleton set containing the {@code @}{@link SqlEvenQuotes} annotation mirror. */ private final AnnotationMirrorSet setOfSqlEvenQuotes; @@ -38,10 +38,10 @@ public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFacto */ public SqlQueryTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); - this.SQLEVENQUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlEvenQuotes.class); - this.SQLODDQUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlOddQuotes.class); - this.SQLQUERYUNKNOWN = AnnotationBuilder.fromClass(getElementUtils(), SqlQueryUnknown.class); - this.setOfSqlEvenQuotes = AnnotationMirrorSet.singleton(SQLEVENQUOTES); + this.SQL_EVEN_QUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlEvenQuotes.class); + this.SQL_ODD_QUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlOddQuotes.class); + this.SQL_QUERY_UNKNOWN = AnnotationBuilder.fromClass(getElementUtils(), SqlQueryUnknown.class); + this.setOfSqlEvenQuotes = AnnotationMirrorSet.singleton(SQL_EVEN_QUOTES); postInit(); } @@ -63,31 +63,31 @@ public SqlQueryTaintingTreeAnnotator(AnnotatedTypeFactory atypeFactory) { @Override public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { - if (!type.hasPrimaryAnnotationInHierarchy(SQLQUERYUNKNOWN) + if (!type.hasPrimaryAnnotationInHierarchy(SQL_QUERY_UNKNOWN) && TreeUtils.isStringConcatenation(tree)) { AnnotatedTypeMirror leftType = getAnnotatedType(tree.getLeftOperand()); AnnotatedTypeMirror rightType = getAnnotatedType(tree.getRightOperand()); - if (leftType.hasPrimaryAnnotation(SQLQUERYUNKNOWN) - || rightType.hasPrimaryAnnotation(SQLQUERYUNKNOWN)) { - type.addAnnotation(SQLQUERYUNKNOWN); + if (leftType.hasPrimaryAnnotation(SQL_QUERY_UNKNOWN) + || rightType.hasPrimaryAnnotation(SQL_QUERY_UNKNOWN)) { + type.addAnnotation(SQL_QUERY_UNKNOWN); return null; } int leftParity = 0; - if (leftType.hasPrimaryAnnotation(SQLODDQUOTES)) { + if (leftType.hasPrimaryAnnotation(SQL_ODD_QUOTES)) { leftParity = 1; } int rightParity = 0; - if (rightType.hasPrimaryAnnotation(SQLODDQUOTES)) { + if (rightType.hasPrimaryAnnotation(SQL_ODD_QUOTES)) { rightParity = 1; } if (leftParity + rightParity % 2 == 0) { - type.addAnnotation(SQLEVENQUOTES); + type.addAnnotation(SQL_EVEN_QUOTES); } else { - type.addAnnotation(SQLODDQUOTES); + type.addAnnotation(SQL_ODD_QUOTES); } } From 07fdf6699425a0764c6ae2bd13ffa3ce0cdc0b38 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 12 Jul 2024 17:12:59 -0700 Subject: [PATCH 026/184] Include the default tree annotators as well --- .../sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java | 1 + 1 file changed, 1 insertion(+) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java index 6fbda671239..670aa9c585f 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -53,6 +53,7 @@ protected Set getEnumConstructorQualifiers() { @Override public TreeAnnotator createTreeAnnotator() { return new ListTreeAnnotator( + super.createTreeAnnotator(), new SqlQueryTaintingAnnotatedTypeFactory.SqlQueryTaintingTreeAnnotator(this)); } From 370996c4d40c62b960a6167e11a3e889a5416a8e Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 12 Jul 2024 17:30:32 -0700 Subject: [PATCH 027/184] Use possessive quantifiers (no backtracking) --- .../checker/sqlquerytainting/qual/SqlEvenQuotes.java | 2 +- .../checker/sqlquerytainting/qual/SqlOddQuotes.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java index abed915b334..62124499c86 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java @@ -18,5 +18,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQueryUnknown.class) -@QualifierForLiterals(stringPatterns = "^((([^\\\\']|\\\\.)*'){2})*([^\\\\']|\\\\.)*\\\\?$") +@QualifierForLiterals(stringPatterns = "^((([^\\\\']|\\\\.)*+'){2})*+([^\\\\']|\\\\.)*+\\\\?$") public @interface SqlEvenQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java index 90bd29e2033..600767ee25e 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java @@ -21,5 +21,5 @@ @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQueryUnknown.class) @QualifierForLiterals( - stringPatterns = "^(([^\\\\']|\\\\.)*')([^\\\\']|'([^\\\\']|\\\\.)*'|\\\\.)*\\\\?$") + stringPatterns = "^(([^\\\\']|\\\\.)*+')([^\\\\']|'([^\\\\']|\\\\.)*+'|\\\\.)*+\\\\?$") public @interface SqlOddQuotes {} From db6bf2a1da295a944237e9a6c5ab0c9f843378bc Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 16 Jul 2024 02:36:03 -0700 Subject: [PATCH 028/184] Added test file for qualifier regex --- .../sqlquerytainting/SqlQualifierRegex.java | 47 +++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/checker/tests/sqlquerytainting/SqlQualifierRegex.java b/checker/tests/sqlquerytainting/SqlQualifierRegex.java index c3e901e77e2..0dd114f15a5 100644 --- a/checker/tests/sqlquerytainting/SqlQualifierRegex.java +++ b/checker/tests/sqlquerytainting/SqlQualifierRegex.java @@ -3,10 +3,51 @@ public class SqlQualifierRegex { - void oddQuotes() { + void oddNoEscaped() { // :: error: (assignment) - @SqlOddQuotes String odd1 = ""; + @SqlOddQuotes String none = "asdf"; + @SqlOddQuotes String one = "asdf'asdf"; + // :: error: (assignment) + @SqlOddQuotes String two = "'asdf'"; + @SqlOddQuotes String three = "'asdf'asdf'"; + // :: error: (assignment) + @SqlOddQuotes String manyEven = "'asdf''asdf'asdf'asdf'''"; + @SqlOddQuotes String manyOdd = "''asdf'asdf'''asdf'asdf''"; + } + + void oddWithBackslashes() { + // :: error: (assignment) + @SqlOddQuotes String none = "asdf\\'"; + @SqlOddQuotes String one = "asdf\\''asdf"; + // :: error: (assignment) + @SqlOddQuotes String two = "'a\\'sdf'"; + @SqlOddQuotes String three = "\\''asdf'\\asdf'"; + // :: error: (assignment) + @SqlOddQuotes String manyEven = "'as\\'df'\\''a\\sdf'asdf'as\\'\\'df'\\'''"; + @SqlOddQuotes String manyOdd = "'\\''a\\sdf'asdf'''as\\df'as\\'df''\\'"; + } - @SqlEvenQuotes String even1 = ""; + void evenNoEscaped() { + @SqlEvenQuotes String none = ""; + // :: error: (assignment) + @SqlEvenQuotes String one = "'asdf"; + @SqlEvenQuotes String two = "''asdf"; + // :: error: (assignment) + @SqlEvenQuotes String three = "asdf'asdf''"; + @SqlEvenQuotes String manyEven = "''asdf''asdf'asdf''asdf'asdf"; + // :: error: (assignment) + @SqlEvenQuotes String manyOdd = "asdf''''asdf'asdf'asdf'asdf"; + } + + void evenWithBackslashes() { + @SqlEvenQuotes String none = "\\'\\'\\'"; + // :: error: (assignment) + @SqlEvenQuotes String one = "'asdf\\'"; + @SqlEvenQuotes String two = "'\\''a\\sdf"; + // :: error: (assignment) + @SqlEvenQuotes String three = "asd\\'f'asdf''"; + @SqlEvenQuotes String manyEven = "\\'''asdf''asd\\f'\\asdf'\\''asdf'asdf\\'"; + // :: error: (assignment) + @SqlEvenQuotes String manyOdd = "asdf''\\'''\\asdf'asdf'a\\'sdf'\\'asdf"; } } From 0e0463c2a4ff8b1e7cf550833d4c6686e7f6620c Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 16 Jul 2024 02:36:29 -0700 Subject: [PATCH 029/184] Added test file for qualifier concatenation --- .../sqlquerytainting/SqlQualifierConcat.java | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 checker/tests/sqlquerytainting/SqlQualifierConcat.java diff --git a/checker/tests/sqlquerytainting/SqlQualifierConcat.java b/checker/tests/sqlquerytainting/SqlQualifierConcat.java new file mode 100644 index 00000000000..05ab410caea --- /dev/null +++ b/checker/tests/sqlquerytainting/SqlQualifierConcat.java @@ -0,0 +1,93 @@ +import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; +import org.checkerframework.checker.sqlquerytainting.qual.SqlOddQuotes; +import org.checkerframework.checker.sqlquerytainting.qual.SqlQueryUnknown; + +public class SqlQualifierConcat { + void oddOddConcat() { + @SqlOddQuotes String odd1 = "asd\\'f'asdf''\\"; + @SqlOddQuotes String odd2 = "''asdf''''asdf'asdf'asdf'asdf"; + // :: error: (assignment) + @SqlOddQuotes String oddResult1 = odd1 + odd2; + @SqlEvenQuotes String evenResult1 = odd1 + odd2; + + @SqlOddQuotes String odd3 = "'asdf"; + @SqlOddQuotes String odd4 = "', "; + // :: error: (assignment) + @SqlOddQuotes String oddResult2 = odd3 + odd4; + @SqlEvenQuotes String evenResult2 = odd3 + odd4; + } + + void oddEvenConcat() { + @SqlOddQuotes String odd1 = "asd\\'f'asdf''\\"; + @SqlEvenQuotes String even1 = "'\\''a\\sdf"; + // :: error: (assignment) + @SqlEvenQuotes String evenResult1 = odd1 + even1; + @SqlOddQuotes String oddResult1 = odd1 + even1; + + @SqlOddQuotes String odd2 = "'asdf"; + @SqlEvenQuotes String even2 = "', asdf '"; + // :: error: (assignment) + @SqlEvenQuotes String evenResult2 = odd2 + even2; + @SqlOddQuotes String oddResult2 = odd2 + even2; + } + + void evenOddConcat() { + @SqlOddQuotes String odd1 = "asd\\'f'asdf''\\"; + @SqlEvenQuotes String even1 = "'\\''a\\sdf"; + // :: error: (assignment) + @SqlEvenQuotes String evenResult1 = even1 + odd1; + @SqlOddQuotes String oddResult1 = even1 + odd1; + + @SqlOddQuotes String odd2 = "'asdf"; + @SqlEvenQuotes String even2 = "', asdf '"; + // :: error: (assignment) + @SqlEvenQuotes String evenResult2 = even2 + odd2; + @SqlOddQuotes String oddResult2 = even2 + odd2; + } + + void evenEvenConcat() { + @SqlEvenQuotes String even1 = "\\'''asdf''asd\\f'\\asdf'\\''asdf'asdf\\'"; + @SqlEvenQuotes String even2 = "''asdf"; + // :: error: (assignment) + @SqlOddQuotes String oddResult1 = even1 + even2; + @SqlEvenQuotes String evenResult1 = even1 + even2; + + @SqlEvenQuotes String even3 = "'a\\'sdf'"; + @SqlEvenQuotes String even4 = "'asdf''asdf'asdf'asdf'''"; + // :: error: (assignment) + @SqlOddQuotes String oddResult2 = even3 + even4; + @SqlEvenQuotes String evenResult2 = even3 + even4; + } + + void withTopConcat(@SqlQueryUnknown String top) { + @SqlOddQuotes String odd1 = "'asdf"; + // :: error: (assignment) + @SqlOddQuotes String oddResult1 = odd1 + top; + // :: error: (assignment) + @SqlEvenQuotes String evenResult1 = odd1 + top; + String topResult1 = odd1 + top; + // :: error: (assignment) + @SqlOddQuotes String oddResult2 = top + odd1; + // :: error: (assignment) + @SqlEvenQuotes String evenResult2 = top + odd1; + String topResult2 = top + odd1; + + @SqlEvenQuotes String even1 = "'a\\'sdf'"; + // :: error: (assignment) + @SqlOddQuotes String oddResult3 = even1 + top; + // :: error: (assignment) + @SqlEvenQuotes String evenResult3 = even1 + top; + String topResult3 = even1 + top; + // :: error: (assignment) + @SqlOddQuotes String oddResult4 = top + even1; + // :: error: (assignment) + @SqlEvenQuotes String evenResult4 = top + even1; + String topResult4 = top + even1; + + // :: error: (assignment) + @SqlOddQuotes String oddResult5 = top + top; + // :: error: (assignment) + @SqlEvenQuotes String evenResult5 = top + top; + String topResult5 = top + top; + } +} From 95de8fc59cdc96d86e997be0b0f7b333775a5146 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 16 Jul 2024 02:39:41 -0700 Subject: [PATCH 030/184] Revised order of operations bug --- .../SqlQueryTaintingAnnotatedTypeFactory.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java index 670aa9c585f..dc35c2064e9 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -64,14 +64,13 @@ public SqlQueryTaintingTreeAnnotator(AnnotatedTypeFactory atypeFactory) { @Override public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { - if (!type.hasPrimaryAnnotationInHierarchy(SQL_QUERY_UNKNOWN) - && TreeUtils.isStringConcatenation(tree)) { + if (TreeUtils.isStringConcatenation(tree)) { AnnotatedTypeMirror leftType = getAnnotatedType(tree.getLeftOperand()); AnnotatedTypeMirror rightType = getAnnotatedType(tree.getRightOperand()); if (leftType.hasPrimaryAnnotation(SQL_QUERY_UNKNOWN) || rightType.hasPrimaryAnnotation(SQL_QUERY_UNKNOWN)) { - type.addAnnotation(SQL_QUERY_UNKNOWN); + type.replaceAnnotation(SQL_QUERY_UNKNOWN); return null; } @@ -85,10 +84,10 @@ public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { rightParity = 1; } - if (leftParity + rightParity % 2 == 0) { - type.addAnnotation(SQL_EVEN_QUOTES); + if ((leftParity + rightParity) % 2 == 0) { + type.replaceAnnotation(SQL_EVEN_QUOTES); } else { - type.addAnnotation(SQL_ODD_QUOTES); + type.replaceAnnotation(SQL_ODD_QUOTES); } } From f8cf9f0ae949fb6255188f4eb81b9f594179a2e8 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 16 Jul 2024 12:56:38 -0700 Subject: [PATCH 031/184] Added stub file for Java SQL executeQuery --- .../checker/sqlquerytainting/Statement.astub | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 checker/src/main/java/org/checkerframework/checker/sqlquerytainting/Statement.astub diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/Statement.astub b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/Statement.astub new file mode 100644 index 00000000000..5cd92218614 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/Statement.astub @@ -0,0 +1,9 @@ +package java.sql; + +import java.util.regex.Pattern; + +import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; + +public interface Statement extends Wrapper, AutoCloseable { + ResultSet executeQuery(@SqlEvenQuotes String var1) throws SQLException; +} From 314bc1a4d527f38c1c849cc6e94c97c60cec897e Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 16 Jul 2024 12:57:51 -0700 Subject: [PATCH 032/184] Added stub file for Java base64 encrypt --- .../sqlquerytainting/BCryptPasswordEncoder.astub | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 checker/src/main/java/org/checkerframework/checker/sqlquerytainting/BCryptPasswordEncoder.astub diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/BCryptPasswordEncoder.astub b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/BCryptPasswordEncoder.astub new file mode 100644 index 00000000000..a586ddb2abf --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/BCryptPasswordEncoder.astub @@ -0,0 +1,14 @@ +package org.springframework.security.crypto.bcrypt; + +import java.security.SecureRandom; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.security.crypto.password.PasswordEncoder; + +import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; + +public class BCryptPasswordEncoder implements PasswordEncoder { + @SqlEvenQuotes String encode(CharSequence rawPassword); +} From 7b232bf3f832c2edafa0f8cdebbe01be28955f87 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 16 Jul 2024 13:24:43 -0700 Subject: [PATCH 033/184] Added stub file for ResultSet getString --- .../checker/sqlquerytainting/ResultSet.astub | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 checker/src/main/java/org/checkerframework/checker/sqlquerytainting/ResultSet.astub diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/ResultSet.astub b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/ResultSet.astub new file mode 100644 index 00000000000..d4b41ee7899 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/ResultSet.astub @@ -0,0 +1,7 @@ +package java.sql; + +import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; + +public interface ResultSet extends Wrapper, AutoCloseable { + @SqlEvenQuotes String getString(int var1) throws SQLException; +} From e22e3ca523cf63a059815eea60ef841b5f9f09d0 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 16 Jul 2024 16:35:06 -0700 Subject: [PATCH 034/184] Removed stub file for ResultSet --- .../checker/sqlquerytainting/ResultSet.astub | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 checker/src/main/java/org/checkerframework/checker/sqlquerytainting/ResultSet.astub diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/ResultSet.astub b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/ResultSet.astub deleted file mode 100644 index d4b41ee7899..00000000000 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/ResultSet.astub +++ /dev/null @@ -1,7 +0,0 @@ -package java.sql; - -import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; - -public interface ResultSet extends Wrapper, AutoCloseable { - @SqlEvenQuotes String getString(int var1) throws SQLException; -} From 06aef63386d6e6fa46ef5b4ccc1de0ffd8da37f4 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 16 Jul 2024 16:44:01 -0700 Subject: [PATCH 035/184] Added stub file annotation --- .../checker/sqlquerytainting/SqlQueryTaintingChecker.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java index b69319c5d2a..5ab2b0c42d9 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java @@ -1,6 +1,7 @@ package org.checkerframework.checker.sqlquerytainting; import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.framework.qual.StubFiles; import org.checkerframework.framework.source.SuppressWarningsPrefix; /** @@ -11,4 +12,5 @@ * sanitized before use. */ @SuppressWarningsPrefix({"sqlquerysanitized", "sqlquerytainting"}) +@StubFiles({"BCryptPasswordEncoder.astub", "Statement.astub"}) public class SqlQueryTaintingChecker extends BaseTypeChecker {} From 60e6eef2807c5081ca3b6c4c22a5b4146dc798b3 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 18 Jul 2024 10:23:23 -0700 Subject: [PATCH 036/184] Rename top and bottom qualifiers --- .../sqlquerytainting/qual/SqlEvenQuotes.java | 2 +- .../sqlquerytainting/qual/SqlOddQuotes.java | 2 +- .../{SqlQueryBottom.java => SqlQuotesBottom.java} | 2 +- ...SqlQueryUnknown.java => SqlQuotesUnknown.java} | 4 ++-- .../SqlQueryTaintingAnnotatedTypeFactory.java | 15 ++++++++------- .../sqlquerytainting/SqlQualifierConcat.java | 4 ++-- 6 files changed, 15 insertions(+), 14 deletions(-) rename checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/{SqlQueryBottom.java => SqlQuotesBottom.java} (96%) rename checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/{SqlQueryUnknown.java => SqlQuotesUnknown.java} (90%) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java index 62124499c86..5c709040bdc 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java @@ -17,6 +17,6 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(SqlQueryUnknown.class) +@SubtypeOf(SqlQuotesUnknown.class) @QualifierForLiterals(stringPatterns = "^((([^\\\\']|\\\\.)*+'){2})*+([^\\\\']|\\\\.)*+\\\\?$") public @interface SqlEvenQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java index 600767ee25e..42731e316a6 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java @@ -19,7 +19,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(SqlQueryUnknown.class) +@SubtypeOf(SqlQuotesUnknown.class) @QualifierForLiterals( stringPatterns = "^(([^\\\\']|\\\\.)*+')([^\\\\']|'([^\\\\']|\\\\.)*+'|\\\\.)*+\\\\?$") public @interface SqlOddQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesBottom.java similarity index 96% rename from checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryBottom.java rename to checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesBottom.java index 8d58e4de03c..7d00e665520 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesBottom.java @@ -19,4 +19,4 @@ @InvisibleQualifier @SubtypeOf({SqlEvenQuotes.class, SqlOddQuotes.class}) @DefaultFor(value = {TypeUseLocation.LOWER_BOUND}) -public @interface SqlQueryBottom {} +public @interface SqlQuotesBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesUnknown.java similarity index 90% rename from checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java rename to checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesUnknown.java index 76582b57758..c3716026651 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesUnknown.java @@ -6,7 +6,7 @@ /** * Represents the top of the SQL query tainting qualifier hierarchy. Used to denote a String that - * comprises part of a SQL query, the quoting of which is unknown. SqlQueryUnknown Strings are SQL + * comprises part of a SQL query, the quoting of which is unknown. SqlQuotesUnknown Strings are SQL * injection vulnerabilities and thus unsafe to be passed to query execution methods. * *

Common use cases include unsanitized user input. @@ -16,4 +16,4 @@ @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf({}) @DefaultQualifierInHierarchy -public @interface SqlQueryUnknown {} +public @interface SqlQuotesUnknown {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java index dc35c2064e9..7faf46fa2d2 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -5,7 +5,7 @@ import javax.lang.model.element.AnnotationMirror; import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; import org.checkerframework.checker.sqlquerytainting.qual.SqlOddQuotes; -import org.checkerframework.checker.sqlquerytainting.qual.SqlQueryUnknown; +import org.checkerframework.checker.sqlquerytainting.qual.SqlQuotesUnknown; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.framework.type.AnnotatedTypeFactory; @@ -25,8 +25,8 @@ public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFacto /** The {@code @}{@link SqlOddQuotes} annotation mirror. */ private final AnnotationMirror SQL_ODD_QUOTES; - /** The {@code @}{@link SqlQueryUnknown} annotation mirror. */ - private final AnnotationMirror SQL_QUERY_UNKNOWN; + /** The {@code @}{@link SqlQuotesUnknown} annotation mirror. */ + private final AnnotationMirror SQL_QUOTES_UNKNOWN; /** A singleton set containing the {@code @}{@link SqlEvenQuotes} annotation mirror. */ private final AnnotationMirrorSet setOfSqlEvenQuotes; @@ -40,7 +40,8 @@ public SqlQueryTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); this.SQL_EVEN_QUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlEvenQuotes.class); this.SQL_ODD_QUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlOddQuotes.class); - this.SQL_QUERY_UNKNOWN = AnnotationBuilder.fromClass(getElementUtils(), SqlQueryUnknown.class); + this.SQL_QUOTES_UNKNOWN = + AnnotationBuilder.fromClass(getElementUtils(), SqlQuotesUnknown.class); this.setOfSqlEvenQuotes = AnnotationMirrorSet.singleton(SQL_EVEN_QUOTES); postInit(); } @@ -68,9 +69,9 @@ public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { AnnotatedTypeMirror leftType = getAnnotatedType(tree.getLeftOperand()); AnnotatedTypeMirror rightType = getAnnotatedType(tree.getRightOperand()); - if (leftType.hasPrimaryAnnotation(SQL_QUERY_UNKNOWN) - || rightType.hasPrimaryAnnotation(SQL_QUERY_UNKNOWN)) { - type.replaceAnnotation(SQL_QUERY_UNKNOWN); + if (leftType.hasPrimaryAnnotation(SQL_QUOTES_UNKNOWN) + || rightType.hasPrimaryAnnotation(SQL_QUOTES_UNKNOWN)) { + type.replaceAnnotation(SQL_QUOTES_UNKNOWN); return null; } diff --git a/checker/tests/sqlquerytainting/SqlQualifierConcat.java b/checker/tests/sqlquerytainting/SqlQualifierConcat.java index 05ab410caea..472d9de3c0b 100644 --- a/checker/tests/sqlquerytainting/SqlQualifierConcat.java +++ b/checker/tests/sqlquerytainting/SqlQualifierConcat.java @@ -1,6 +1,6 @@ import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; import org.checkerframework.checker.sqlquerytainting.qual.SqlOddQuotes; -import org.checkerframework.checker.sqlquerytainting.qual.SqlQueryUnknown; +import org.checkerframework.checker.sqlquerytainting.qual.SqlQuotesUnknown; public class SqlQualifierConcat { void oddOddConcat() { @@ -59,7 +59,7 @@ void evenEvenConcat() { @SqlEvenQuotes String evenResult2 = even3 + even4; } - void withTopConcat(@SqlQueryUnknown String top) { + void withTopConcat(@SqlQuotesUnknown String top) { @SqlOddQuotes String odd1 = "'asdf"; // :: error: (assignment) @SqlOddQuotes String oddResult1 = odd1 + top; From 0cd3cca18c597a2526e913b50879d930893de443 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 18 Jul 2024 10:49:34 -0700 Subject: [PATCH 037/184] Rename checker --- .../qual/SqlEvenQuotes.java | 2 +- .../qual/SqlOddQuotes.java | 2 +- .../qual/SqlQuotesBottom.java | 4 ++-- .../qual/SqlQuotesUnknown.java | 8 +++---- .../BCryptPasswordEncoder.astub | 2 +- .../SqlQuotesAnnotatedTypeFactory.java} | 22 +++++++++---------- .../SqlQuotesChecker.java} | 6 ++--- .../SqlQuotesVisitor.java} | 10 ++++----- .../Statement.astub | 2 +- ...ryTaintingTest.java => SqlQuotesTest.java} | 10 ++++----- .../SqlQuotesConcat.java} | 8 +++---- .../SqlQuotesRegex.java} | 6 ++--- 12 files changed, 41 insertions(+), 41 deletions(-) rename checker-qual/src/main/java/org/checkerframework/checker/{sqlquerytainting => sqlquotes}/qual/SqlEvenQuotes.java (94%) rename checker-qual/src/main/java/org/checkerframework/checker/{sqlquerytainting => sqlquotes}/qual/SqlOddQuotes.java (95%) rename checker-qual/src/main/java/org/checkerframework/checker/{sqlquerytainting => sqlquotes}/qual/SqlQuotesBottom.java (86%) rename checker-qual/src/main/java/org/checkerframework/checker/{sqlquerytainting => sqlquotes}/qual/SqlQuotesUnknown.java (54%) rename checker/src/main/java/org/checkerframework/checker/{sqlquerytainting => sqlquotes}/BCryptPasswordEncoder.astub (85%) rename checker/src/main/java/org/checkerframework/checker/{sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java => sqlquotes/SqlQuotesAnnotatedTypeFactory.java} (78%) rename checker/src/main/java/org/checkerframework/checker/{sqlquerytainting/SqlQueryTaintingChecker.java => sqlquotes/SqlQuotesChecker.java} (74%) rename checker/src/main/java/org/checkerframework/checker/{sqlquerytainting/SqlQueryTaintingVisitor.java => sqlquotes/SqlQuotesVisitor.java} (70%) rename checker/src/main/java/org/checkerframework/checker/{sqlquerytainting => sqlquotes}/Statement.astub (72%) rename checker/src/test/java/org/checkerframework/checker/test/junit/{SqlQueryTaintingTest.java => SqlQuotesTest.java} (54%) rename checker/tests/{sqlquerytainting/SqlQualifierConcat.java => sqlquotes/SqlQuotesConcat.java} (92%) rename checker/tests/{sqlquerytainting/SqlQualifierRegex.java => sqlquotes/SqlQuotesRegex.java} (90%) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java similarity index 94% rename from checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java rename to checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java index 5c709040bdc..85758ccb870 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.sqlquerytainting.qual; +package org.checkerframework.checker.sqlquotes.qual; import java.lang.annotation.*; import org.checkerframework.framework.qual.QualifierForLiterals; diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java similarity index 95% rename from checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java rename to checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java index 42731e316a6..957d7eb60af 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.sqlquerytainting.qual; +package org.checkerframework.checker.sqlquotes.qual; import java.lang.annotation.*; import org.checkerframework.framework.qual.QualifierForLiterals; diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java similarity index 86% rename from checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesBottom.java rename to checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java index 7d00e665520..98c45985156 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.sqlquerytainting.qual; +package org.checkerframework.checker.sqlquotes.qual; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -11,7 +11,7 @@ import org.checkerframework.framework.qual.TargetLocations; import org.checkerframework.framework.qual.TypeUseLocation; -/** Represents the bottom of the SQL query tainting qualifier hierarchy. */ +/** Represents the bottom of the SQL Quotes qualifier hierarchy. */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesUnknown.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java similarity index 54% rename from checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesUnknown.java rename to checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java index c3716026651..e54c70772cb 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesUnknown.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java @@ -1,13 +1,13 @@ -package org.checkerframework.checker.sqlquerytainting.qual; +package org.checkerframework.checker.sqlquotes.qual; import java.lang.annotation.*; import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; import org.checkerframework.framework.qual.SubtypeOf; /** - * Represents the top of the SQL query tainting qualifier hierarchy. Used to denote a String that - * comprises part of a SQL query, the quoting of which is unknown. SqlQuotesUnknown Strings are SQL - * injection vulnerabilities and thus unsafe to be passed to query execution methods. + * Represents the top of the SQL Quotes qualifier hierarchy. Used to denote a String that comprises + * part of a SQL query, the quoting of which is unknown. SqlQuotesUnknown Strings are SQL injection + * vulnerabilities and thus unsafe to be passed to query execution methods. * *

Common use cases include unsanitized user input. */ diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/BCryptPasswordEncoder.astub b/checker/src/main/java/org/checkerframework/checker/sqlquotes/BCryptPasswordEncoder.astub similarity index 85% rename from checker/src/main/java/org/checkerframework/checker/sqlquerytainting/BCryptPasswordEncoder.astub rename to checker/src/main/java/org/checkerframework/checker/sqlquotes/BCryptPasswordEncoder.astub index a586ddb2abf..effc721c786 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/BCryptPasswordEncoder.astub +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/BCryptPasswordEncoder.astub @@ -7,7 +7,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.security.crypto.password.PasswordEncoder; -import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; +import org.checkerframework.checker.sqlquotes.qual.SqlEvenQuotes; public class BCryptPasswordEncoder implements PasswordEncoder { @SqlEvenQuotes String encode(CharSequence rawPassword); diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java similarity index 78% rename from checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java rename to checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java index 7faf46fa2d2..24d83dab458 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java @@ -1,11 +1,11 @@ -package org.checkerframework.checker.sqlquerytainting; +package org.checkerframework.checker.sqlquotes; import com.sun.source.tree.BinaryTree; import java.util.Set; import javax.lang.model.element.AnnotationMirror; -import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; -import org.checkerframework.checker.sqlquerytainting.qual.SqlOddQuotes; -import org.checkerframework.checker.sqlquerytainting.qual.SqlQuotesUnknown; +import org.checkerframework.checker.sqlquotes.qual.SqlEvenQuotes; +import org.checkerframework.checker.sqlquotes.qual.SqlOddQuotes; +import org.checkerframework.checker.sqlquotes.qual.SqlQuotesUnknown; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.framework.type.AnnotatedTypeFactory; @@ -16,8 +16,8 @@ import org.checkerframework.javacutil.AnnotationMirrorSet; import org.checkerframework.javacutil.TreeUtils; -/** Annotated type factory for the SQL Query Tainting Checker. */ -public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { +/** Annotated type factory for the SQL Quotes Checker. */ +public class SqlQuotesAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { /** The {@code @}{@link SqlEvenQuotes} annotation mirror. */ private final AnnotationMirror SQL_EVEN_QUOTES; @@ -32,11 +32,11 @@ public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFacto private final AnnotationMirrorSet setOfSqlEvenQuotes; /** - * Creates a {@link SqlQueryTaintingAnnotatedTypeFactory}. + * Creates a {@link SqlQuotesAnnotatedTypeFactory}. * * @param checker the SQL tainting checker */ - public SqlQueryTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { + public SqlQuotesAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); this.SQL_EVEN_QUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlEvenQuotes.class); this.SQL_ODD_QUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlOddQuotes.class); @@ -55,11 +55,11 @@ protected Set getEnumConstructorQualifiers() { public TreeAnnotator createTreeAnnotator() { return new ListTreeAnnotator( super.createTreeAnnotator(), - new SqlQueryTaintingAnnotatedTypeFactory.SqlQueryTaintingTreeAnnotator(this)); + new SqlQuotesAnnotatedTypeFactory.SqlQuotesTreeAnnotator(this)); } - private class SqlQueryTaintingTreeAnnotator extends TreeAnnotator { - public SqlQueryTaintingTreeAnnotator(AnnotatedTypeFactory atypeFactory) { + private class SqlQuotesTreeAnnotator extends TreeAnnotator { + public SqlQuotesTreeAnnotator(AnnotatedTypeFactory atypeFactory) { super(atypeFactory); } diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java similarity index 74% rename from checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java rename to checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java index 5ab2b0c42d9..4dba24a5f7b 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.sqlquerytainting; +package org.checkerframework.checker.sqlquotes; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.framework.qual.StubFiles; @@ -11,6 +11,6 @@ *

It verifies that only SQL-safe embedded query values are trusted and that user input is * sanitized before use. */ -@SuppressWarningsPrefix({"sqlquerysanitized", "sqlquerytainting"}) +@SuppressWarningsPrefix({"sqlquerysanitized", "sqlquotes"}) @StubFiles({"BCryptPasswordEncoder.astub", "Statement.astub"}) -public class SqlQueryTaintingChecker extends BaseTypeChecker {} +public class SqlQuotesChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesVisitor.java similarity index 70% rename from checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java rename to checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesVisitor.java index 4b0aba79624..f4d62e59317 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesVisitor.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.sqlquerytainting; +package org.checkerframework.checker.sqlquotes; import javax.lang.model.element.ExecutableElement; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; @@ -6,15 +6,15 @@ import org.checkerframework.common.basetype.BaseTypeVisitor; import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType; -/** Visitor for the {@link SqlQueryTaintingChecker}. */ -public class SqlQueryTaintingVisitor extends BaseTypeVisitor { +/** Visitor for the {@link SqlQuotesChecker}. */ +public class SqlQuotesVisitor extends BaseTypeVisitor { /** - * Creates a {@link SqlQueryTaintingVisitor}. + * Creates a {@link SqlQuotesVisitor}. * * @param checker the checker that uses this visitor */ - public SqlQueryTaintingVisitor(BaseTypeChecker checker) { + public SqlQuotesVisitor(BaseTypeChecker checker) { super(checker); } diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/Statement.astub b/checker/src/main/java/org/checkerframework/checker/sqlquotes/Statement.astub similarity index 72% rename from checker/src/main/java/org/checkerframework/checker/sqlquerytainting/Statement.astub rename to checker/src/main/java/org/checkerframework/checker/sqlquotes/Statement.astub index 5cd92218614..71b9521c766 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/Statement.astub +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/Statement.astub @@ -2,7 +2,7 @@ package java.sql; import java.util.regex.Pattern; -import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; +import org.checkerframework.checker.sqlquotes.qual.SqlEvenQuotes; public interface Statement extends Wrapper, AutoCloseable { ResultSet executeQuery(@SqlEvenQuotes String var1) throws SQLException; diff --git a/checker/src/test/java/org/checkerframework/checker/test/junit/SqlQueryTaintingTest.java b/checker/src/test/java/org/checkerframework/checker/test/junit/SqlQuotesTest.java similarity index 54% rename from checker/src/test/java/org/checkerframework/checker/test/junit/SqlQueryTaintingTest.java rename to checker/src/test/java/org/checkerframework/checker/test/junit/SqlQuotesTest.java index 8f6d47e28f5..6c966841b37 100644 --- a/checker/src/test/java/org/checkerframework/checker/test/junit/SqlQueryTaintingTest.java +++ b/checker/src/test/java/org/checkerframework/checker/test/junit/SqlQuotesTest.java @@ -2,23 +2,23 @@ import java.io.File; import java.util.List; -import org.checkerframework.checker.sqlquerytainting.SqlQueryTaintingChecker; +import org.checkerframework.checker.sqlquotes.SqlQuotesChecker; import org.checkerframework.framework.test.CheckerFrameworkPerDirectoryTest; import org.junit.runners.Parameterized.Parameters; -public class SqlQueryTaintingTest extends CheckerFrameworkPerDirectoryTest { +public class SqlQuotesTest extends CheckerFrameworkPerDirectoryTest { /** * Create a TaintingTest. * * @param testFiles the files containing test code, which will be type-checked */ - public SqlQueryTaintingTest(List testFiles) { - super(testFiles, SqlQueryTaintingChecker.class, "sqlquerytainting"); + public SqlQuotesTest(List testFiles) { + super(testFiles, SqlQuotesChecker.class, "sqlquotes"); } @Parameters public static String[] getTestDirs() { - return new String[] {"sqlquerytainting", "all-systems"}; + return new String[] {"sqlquotes", "all-systems"}; } } diff --git a/checker/tests/sqlquerytainting/SqlQualifierConcat.java b/checker/tests/sqlquotes/SqlQuotesConcat.java similarity index 92% rename from checker/tests/sqlquerytainting/SqlQualifierConcat.java rename to checker/tests/sqlquotes/SqlQuotesConcat.java index 472d9de3c0b..b2ef3deaab5 100644 --- a/checker/tests/sqlquerytainting/SqlQualifierConcat.java +++ b/checker/tests/sqlquotes/SqlQuotesConcat.java @@ -1,8 +1,8 @@ -import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; -import org.checkerframework.checker.sqlquerytainting.qual.SqlOddQuotes; -import org.checkerframework.checker.sqlquerytainting.qual.SqlQuotesUnknown; +import org.checkerframework.checker.sqlquotes.qual.SqlEvenQuotes; +import org.checkerframework.checker.sqlquotes.qual.SqlOddQuotes; +import org.checkerframework.checker.sqlquotes.qual.SqlQuotesUnknown; -public class SqlQualifierConcat { +public class SqlQuotesConcat { void oddOddConcat() { @SqlOddQuotes String odd1 = "asd\\'f'asdf''\\"; @SqlOddQuotes String odd2 = "''asdf''''asdf'asdf'asdf'asdf"; diff --git a/checker/tests/sqlquerytainting/SqlQualifierRegex.java b/checker/tests/sqlquotes/SqlQuotesRegex.java similarity index 90% rename from checker/tests/sqlquerytainting/SqlQualifierRegex.java rename to checker/tests/sqlquotes/SqlQuotesRegex.java index 0dd114f15a5..72a46bd26f2 100644 --- a/checker/tests/sqlquerytainting/SqlQualifierRegex.java +++ b/checker/tests/sqlquotes/SqlQuotesRegex.java @@ -1,7 +1,7 @@ -import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; -import org.checkerframework.checker.sqlquerytainting.qual.SqlOddQuotes; +import org.checkerframework.checker.sqlquotes.qual.SqlEvenQuotes; +import org.checkerframework.checker.sqlquotes.qual.SqlOddQuotes; -public class SqlQualifierRegex { +public class SqlQuotesRegex { void oddNoEscaped() { // :: error: (assignment) From ab3f4e44cc2bc4fea55b38f1b4a6142343f08129 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 9 Jul 2024 12:14:00 -0700 Subject: [PATCH 038/184] Created sqlquerytainting directory --- .../SqlQueryTaintingAnnotatedTypeFactory.java | 36 +++++++++++++++++++ .../SqlQueryTaintingChecker.java | 14 ++++++++ .../SqlQueryTaintingVisitor.java | 28 +++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java create mode 100644 checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java create mode 100644 checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java new file mode 100644 index 00000000000..a26fc7c1874 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -0,0 +1,36 @@ +package org.checkerframework.checker.sqltainting; + +import java.util.Set; +import javax.lang.model.element.AnnotationMirror; +import org.checkerframework.checker.sqltainting.qual.SqlSanitized; +import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; +import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.javacutil.AnnotationBuilder; +import org.checkerframework.javacutil.AnnotationMirrorSet; + +/** Annotated type factory for the SQL Tainting Checker. */ +public class SqlTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { + + /** The {@code @}{@link SqlSanitized} annotation mirror. */ + private final AnnotationMirror SQLSANITIZED; + + /** A singleton set containing the {@code @}{@link SqlSanitized} annotation mirror. */ + private final AnnotationMirrorSet setOfSqlSanitized; + + /** + * Creates a {@link SqlTaintingAnnotatedTypeFactory}. + * + * @param checker the SQL tainting checker + */ + public SqlTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { + super(checker); + this.SQLSANITIZED = AnnotationBuilder.fromClass(getElementUtils(), SqlSanitized.class); + this.setOfSqlSanitized = AnnotationMirrorSet.singleton(SQLSANITIZED); + postInit(); + } + + @Override + protected Set getEnumConstructorQualifiers() { + return setOfSqlSanitized; + } +} diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java new file mode 100644 index 00000000000..f4559454404 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java @@ -0,0 +1,14 @@ +package org.checkerframework.checker.sqlquerytainting; + +import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.framework.source.SuppressWarningsPrefix; + +/** + * A type-checker plug-in for the SQL Tainting type system qualifier that finds (and verifies the + * absence of) SQL injection bugs in embedded query values. + * + *

It verifies that only SQL-safe embedded query values are trusted and that user input is + * sanitized before use. + */ +@SuppressWarningsPrefix({"sqlquerysanitized", "sqlquerytainting"}) +public class SqlTaintingChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java new file mode 100644 index 00000000000..e0435e0f440 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java @@ -0,0 +1,28 @@ +package org.checkerframework.checker.sqlquerytainting; + +import javax.lang.model.element.ExecutableElement; +import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; +import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.common.basetype.BaseTypeVisitor; +import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType; + +/** Visitor for the {@link SqlTaintingChecker}. */ +public class SqlTaintingVisitor extends BaseTypeVisitor { + + /** + * Creates a {@link SqlTaintingVisitor}. + * + * @param checker the checker that uses this visitor + */ + public SqlTaintingVisitor(BaseTypeChecker checker) { + super(checker); + } + + /** + * Don't check that the constructor result is top. Checking that the super() or this() call is a + * subtype of the constructor result is sufficient. + */ + @Override + protected void checkConstructorResult( + AnnotatedExecutableType constructorType, ExecutableElement constructorElement) {} +} From 10dd0213c07de5f06bf2c63c6b49bf12e9821283 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 9 Jul 2024 12:16:27 -0700 Subject: [PATCH 039/184] Renamed sqlquerytainting files --- .../SqlQueryTaintingAnnotatedTypeFactory.java | 11 +++++------ .../sqlquerytainting/SqlQueryTaintingChecker.java | 2 +- .../sqlquerytainting/SqlQueryTaintingVisitor.java | 8 ++++---- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java index a26fc7c1874..46b5ec71889 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -1,15 +1,14 @@ -package org.checkerframework.checker.sqltainting; +package org.checkerframework.checker.sqlquerytainting; import java.util.Set; import javax.lang.model.element.AnnotationMirror; -import org.checkerframework.checker.sqltainting.qual.SqlSanitized; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.javacutil.AnnotationBuilder; import org.checkerframework.javacutil.AnnotationMirrorSet; -/** Annotated type factory for the SQL Tainting Checker. */ -public class SqlTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { +/** Annotated type factory for the SQL Query Tainting Checker. */ +public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { /** The {@code @}{@link SqlSanitized} annotation mirror. */ private final AnnotationMirror SQLSANITIZED; @@ -18,11 +17,11 @@ public class SqlTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { private final AnnotationMirrorSet setOfSqlSanitized; /** - * Creates a {@link SqlTaintingAnnotatedTypeFactory}. + * Creates a {@link SqlQueryTaintingAnnotatedTypeFactory}. * * @param checker the SQL tainting checker */ - public SqlTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { + public SqlQueryTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); this.SQLSANITIZED = AnnotationBuilder.fromClass(getElementUtils(), SqlSanitized.class); this.setOfSqlSanitized = AnnotationMirrorSet.singleton(SQLSANITIZED); diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java index f4559454404..b69319c5d2a 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java @@ -11,4 +11,4 @@ * sanitized before use. */ @SuppressWarningsPrefix({"sqlquerysanitized", "sqlquerytainting"}) -public class SqlTaintingChecker extends BaseTypeChecker {} +public class SqlQueryTaintingChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java index e0435e0f440..4b0aba79624 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java @@ -6,15 +6,15 @@ import org.checkerframework.common.basetype.BaseTypeVisitor; import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType; -/** Visitor for the {@link SqlTaintingChecker}. */ -public class SqlTaintingVisitor extends BaseTypeVisitor { +/** Visitor for the {@link SqlQueryTaintingChecker}. */ +public class SqlQueryTaintingVisitor extends BaseTypeVisitor { /** - * Creates a {@link SqlTaintingVisitor}. + * Creates a {@link SqlQueryTaintingVisitor}. * * @param checker the checker that uses this visitor */ - public SqlTaintingVisitor(BaseTypeChecker checker) { + public SqlQueryTaintingVisitor(BaseTypeChecker checker) { super(checker); } From a6bd0f547cfe5681d4636cff5a746d296105a44e Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 9 Jul 2024 14:20:21 -0700 Subject: [PATCH 040/184] Added qualifiers SqlQueryComplete, SqlQuerySnippet, SqlQueryUnknown, and SqlSanitizedUser --- .../sqlquerytainting/SqlQueryComplete.java | 16 +++++++ .../sqlquerytainting/SqlQuerySnippet.java | 15 ++++++ .../sqlquerytainting/SqlQueryUnknown.java | 13 +++++ .../sqlquerytainting/SqlSanitizedUser.java | 21 ++++++++ .../SqlQueryTaintingAnnotatedTypeFactory.java | 14 +++--- .../sqlquerytainting/SimpleSqlQuery.java | 48 +++++++++++++++++++ 6 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryComplete.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQuerySnippet.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryUnknown.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlSanitizedUser.java create mode 100644 checker/tests/sqlquerytainting/SimpleSqlQuery.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryComplete.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryComplete.java new file mode 100644 index 00000000000..ce32d7bb90e --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryComplete.java @@ -0,0 +1,16 @@ +package org.checkerframework.checker.sqlquerytainting; + +import java.lang.annotation.*; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Denotes a String that represents a complete, safe SQL query to be executed. Safety from SQL + * injection vulnerabilities is guaranteed as all components of @SqlQueryComplete Strings either + * originate entirely within the author's code, or originate from user input and have been + * sanitized. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(SqlQueryUnknown.class) +public @interface SqlQueryComplete {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQuerySnippet.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQuerySnippet.java new file mode 100644 index 00000000000..ef4feb8469d --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQuerySnippet.java @@ -0,0 +1,15 @@ +package org.checkerframework.checker.sqlquerytainting; + +import java.lang.annotation.*; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Denotes a String that comprises part of a SQL query - commonly, it may be a SQL command fragment, + * a command requiring user input concatenation, or a command with user input requiring end quote + * concatenation. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(SqlQueryUnknown.class) +public @interface SqlQuerySnippet {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryUnknown.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryUnknown.java new file mode 100644 index 00000000000..1c9a229244a --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryUnknown.java @@ -0,0 +1,13 @@ +package org.checkerframework.checker.sqlquerytainting; + +import java.lang.annotation.*; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.SubtypeOf; + +/** Represents the top of the SQL query tainting qualifier hierarchy. */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({}) +@DefaultQualifierInHierarchy +public @interface SqlQueryUnknown {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlSanitizedUser.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlSanitizedUser.java new file mode 100644 index 00000000000..e75ae66f62a --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlSanitizedUser.java @@ -0,0 +1,21 @@ +package org.checkerframework.checker.sqlquerytainting; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.QualifierForLiterals; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Denotes a value to be used in a SQL query originating from user input that has been sanitized + * (i.e. non-alphanumeric characters escaped as necessary) and is thus safe to be embedded as a + * value in a SQL query. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(SqlQueryUnknown.class) +@QualifierForLiterals(stringPatterns = "^(\\w|\\s|(\\\\[-'\"\\\\%_])*)*$") +public @interface SqlSanitizedUser {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java index 46b5ec71889..c785754fe9b 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -10,11 +10,11 @@ /** Annotated type factory for the SQL Query Tainting Checker. */ public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { - /** The {@code @}{@link SqlSanitized} annotation mirror. */ - private final AnnotationMirror SQLSANITIZED; + /** The {@code @}{@link SqlSanitizedUser} annotation mirror. */ + private final AnnotationMirror SQLSANITIZEDUSER; - /** A singleton set containing the {@code @}{@link SqlSanitized} annotation mirror. */ - private final AnnotationMirrorSet setOfSqlSanitized; + /** A singleton set containing the {@code @}{@link SqlSanitizedUser} annotation mirror. */ + private final AnnotationMirrorSet setOfSqlSanitizedUser; /** * Creates a {@link SqlQueryTaintingAnnotatedTypeFactory}. @@ -23,13 +23,13 @@ public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFacto */ public SqlQueryTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); - this.SQLSANITIZED = AnnotationBuilder.fromClass(getElementUtils(), SqlSanitized.class); - this.setOfSqlSanitized = AnnotationMirrorSet.singleton(SQLSANITIZED); + this.SQLSANITIZEDUSER = AnnotationBuilder.fromClass(getElementUtils(), SqlSanitizedUser.class); + this.setOfSqlSanitizedUser = AnnotationMirrorSet.singleton(SQLSANITIZEDUSER); postInit(); } @Override protected Set getEnumConstructorQualifiers() { - return setOfSqlSanitized; + return setOfSqlSanitizedUser; } } diff --git a/checker/tests/sqlquerytainting/SimpleSqlQuery.java b/checker/tests/sqlquerytainting/SimpleSqlQuery.java new file mode 100644 index 00000000000..4302a57e28a --- /dev/null +++ b/checker/tests/sqlquerytainting/SimpleSqlQuery.java @@ -0,0 +1,48 @@ +import org.checkerframework.checker.sqltainting.qual.SqlSanitized; + +public class SimpleSqlQueryValue { + + void execute(@SqlSanitized String s) {} + + void unsanitized(String s) {} + + void stringLiteral() { + execute("ldskjfldj"); + unsanitized("lksjdflkjdf"); + } + + void stringRef(String ref) { + // :: error: (argument) + execute(ref); // error + + unsanitized(ref); + } + + void safeRef(@SqlSanitized String ref) { + execute(ref); + unsanitized(ref); + } + + void concatenation(@SqlSanitized String s1, String s2) { + execute(s1 + s1); + execute(s1 += s1); + execute(s1 + "m"); + // :: error: (argument) + execute(s1 + s2); // error + + // :: error: (argument) + execute(s2 + s1); // error + // :: error: (argument) + execute(s2 + "m"); // error + // :: error: (argument) + execute(s2 + s2); // error + + unsanitized(s1 + s1); + unsanitized(s1 + "m"); + unsanitized(s1 + s2); + + unsanitized(s2 + s1); + unsanitized(s2 + "m"); + unsanitized(s2 + s2); + } +} From 0f71fe5d0b46591ff6fe32b1ac4dc4f11ed9454d Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 11 Jul 2024 16:46:26 -0700 Subject: [PATCH 041/184] Revised qualifiers to SqlEvenQuotes, SqlOddQuotes, SqlQuoteless --- .../sqlquerytainting/SqlQueryComplete.java | 16 ----------- .../sqlquerytainting/SqlQuerySnippet.java | 15 ----------- .../sqlquerytainting/SqlSanitizedUser.java | 21 --------------- .../sqlquerytainting/qual/SqlEvenQuotes.java | 22 +++++++++++++++ .../sqlquerytainting/qual/SqlOddQuotes.java | 27 +++++++++++++++++++ .../{ => qual}/SqlQueryUnknown.java | 2 +- .../sqlquerytainting/qual/SqlQuoteless.java | 26 ++++++++++++++++++ .../SqlQueryTaintingAnnotatedTypeFactory.java | 1 + 8 files changed, 77 insertions(+), 53 deletions(-) delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryComplete.java delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQuerySnippet.java delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlSanitizedUser.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java rename checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/{ => qual}/SqlQueryUnknown.java (87%) create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryComplete.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryComplete.java deleted file mode 100644 index ce32d7bb90e..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryComplete.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.checkerframework.checker.sqlquerytainting; - -import java.lang.annotation.*; -import org.checkerframework.framework.qual.SubtypeOf; - -/** - * Denotes a String that represents a complete, safe SQL query to be executed. Safety from SQL - * injection vulnerabilities is guaranteed as all components of @SqlQueryComplete Strings either - * originate entirely within the author's code, or originate from user input and have been - * sanitized. - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(SqlQueryUnknown.class) -public @interface SqlQueryComplete {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQuerySnippet.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQuerySnippet.java deleted file mode 100644 index ef4feb8469d..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQuerySnippet.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.checkerframework.checker.sqlquerytainting; - -import java.lang.annotation.*; -import org.checkerframework.framework.qual.SubtypeOf; - -/** - * Denotes a String that comprises part of a SQL query - commonly, it may be a SQL command fragment, - * a command requiring user input concatenation, or a command with user input requiring end quote - * concatenation. - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(SqlQueryUnknown.class) -public @interface SqlQuerySnippet {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlSanitizedUser.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlSanitizedUser.java deleted file mode 100644 index e75ae66f62a..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlSanitizedUser.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.checkerframework.checker.sqlquerytainting; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.QualifierForLiterals; -import org.checkerframework.framework.qual.SubtypeOf; - -/** - * Denotes a value to be used in a SQL query originating from user input that has been sanitized - * (i.e. non-alphanumeric characters escaped as necessary) and is thus safe to be embedded as a - * value in a SQL query. - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(SqlQueryUnknown.class) -@QualifierForLiterals(stringPatterns = "^(\\w|\\s|(\\\\[-'\"\\\\%_])*)*$") -public @interface SqlSanitizedUser {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java new file mode 100644 index 00000000000..f3138e84fd8 --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java @@ -0,0 +1,22 @@ +package org.checkerframework.checker.sqlquerytainting.qual; + +import java.lang.annotation.*; +import org.checkerframework.framework.qual.QualifierForLiterals; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Used to denote a String that comprises part of a SQL query and + * contains an even number of unescaped single quotes – i.e., there + * must be an even number of ‘ characters in a SqlEvenQuotes String + * that are not preceded immediately by a / character. SQLEvenQuotes + * Strings are safe to be passed to query execution methods. + * + * Common use cases include: complete SQL queries, such as “SELECT * + * FROM table WHERE field = ‘value’”. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(SqlQueryUnknown.class) +@QualifierForLiterals(stringPatterns = "^(([^\\\\\\']|\\\\.)*\\'){2}([^\\\\\\']|(\\'([^\\\\\\']|\\\\.)*\\')|\\\\.)*\\\\?$") +public @interface SqlEvenQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java new file mode 100644 index 00000000000..70bdf8b6d6a --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java @@ -0,0 +1,27 @@ +package org.checkerframework.checker.sqlquerytainting.qual; + +import java.lang.annotation.*; +import org.checkerframework.framework.qual.QualifierForLiterals; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Used to denote a String that comprises part of a SQL query and + * contains an odd number of unescaped single quotes – i.e., there + * must be an odd number of ‘ characters in a SqlOddQuotes String + * that are not preceded immediately by a / character. SQLOddQuotes + * Strings are not safe to be passed to query execution methods. + * + * Common use cases include: SQL query fragments to be concatenated + * with user input, such as “SELECT * FROM table WHERE field = ‘”; + * SQL query fragments containing user input but missing an ending + * single quote, such as “SELECT * FROM table WHERE field = ‘value”; + * connecting punctuation, such as “’, “; and any combinations of the + * above with paired-off single quotes, such as “SELECT * FROM table + * WHERE field1 = ‘value1’, field2 = ‘value2’, field3 = ‘”. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(SqlQueryUnknown.class) +@QualifierForLiterals(stringPatterns = "^(([^\\\\\\']|\\\\.)*\\')([^\\\\\\']|\\'([^\\\\\\']|\\\\.)*\\'|\\\\.)*\\\\?$") +public @interface SqlOddQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryUnknown.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java similarity index 87% rename from checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryUnknown.java rename to checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java index 1c9a229244a..80962285d2c 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryUnknown.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.sqlquerytainting; +package org.checkerframework.checker.sqlquerytainting.qual; import java.lang.annotation.*; import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java new file mode 100644 index 00000000000..d6af47df514 --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java @@ -0,0 +1,26 @@ +package org.checkerframework.checker.sqlquerytainting.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.QualifierForLiterals; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Used to denote a String that comprises part of a SQL query and + * contains exactly zero unescaped single quotes – i.e., all occurrences + * of the ‘ character in such a String are preceded immediately by a / + * character. SQLQuoteless Strings are safe to be passed to query execution + * methods. + * + * Common use cases include SQL query fragments such as “SELECT * FROM” + * and properly sanitized user input. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(SqlQueryUnknown.class) +@QualifierForLiterals(stringPatterns = "^([^\\']|(\\\\'))*$") +public @interface SqlQuoteless {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java index c785754fe9b..15a7d2247b4 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -2,6 +2,7 @@ import java.util.Set; import javax.lang.model.element.AnnotationMirror; +import org.checkerframework.checker.sqlquerytainting.qual.SqlSanitizedUser; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.javacutil.AnnotationBuilder; From 97b541ffeb982af1c9a6582e328acb8070527bbe Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 11 Jul 2024 16:51:04 -0700 Subject: [PATCH 042/184] Revised qualifiers to SqlOddQuotes, SqlEvenQuotes, SqlQuoteless --- .../sqlquerytainting/qual/SqlEvenQuotes.java | 17 ++++++------- .../sqlquerytainting/qual/SqlOddQuotes.java | 24 +++++++++---------- .../sqlquerytainting/qual/SqlQuoteless.java | 11 ++++----- 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java index f3138e84fd8..fe5c3c8d6ba 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java @@ -5,18 +5,19 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * Used to denote a String that comprises part of a SQL query and - * contains an even number of unescaped single quotes – i.e., there - * must be an even number of ‘ characters in a SqlEvenQuotes String - * that are not preceded immediately by a / character. SQLEvenQuotes - * Strings are safe to be passed to query execution methods. + * Used to denote a String that comprises part of a SQL query and contains an even number of + * unescaped single quotes – i.e., there must be an even number of ‘ characters in a SqlEvenQuotes + * String that are not preceded immediately by a / character. SQLEvenQuotes Strings are safe to be + * passed to query execution methods. * - * Common use cases include: complete SQL queries, such as “SELECT * - * FROM table WHERE field = ‘value’”. + *

Common use cases include: complete SQL queries, such as “SELECT * FROM table WHERE field = + * ‘value’”. */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQueryUnknown.class) -@QualifierForLiterals(stringPatterns = "^(([^\\\\\\']|\\\\.)*\\'){2}([^\\\\\\']|(\\'([^\\\\\\']|\\\\.)*\\')|\\\\.)*\\\\?$") +@QualifierForLiterals( + stringPatterns = + "^(([^\\\\\\']|\\\\.)*\\'){2}([^\\\\\\']|(\\'([^\\\\\\']|\\\\.)*\\')|\\\\.)*\\\\?$") public @interface SqlEvenQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java index 70bdf8b6d6a..94c7c804858 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java @@ -5,23 +5,21 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * Used to denote a String that comprises part of a SQL query and - * contains an odd number of unescaped single quotes – i.e., there - * must be an odd number of ‘ characters in a SqlOddQuotes String - * that are not preceded immediately by a / character. SQLOddQuotes - * Strings are not safe to be passed to query execution methods. + * Used to denote a String that comprises part of a SQL query and contains an odd number of + * unescaped single quotes – i.e., there must be an odd number of ‘ characters in a SqlOddQuotes + * String that are not preceded immediately by a / character. SQLOddQuotes Strings are not safe to + * be passed to query execution methods. * - * Common use cases include: SQL query fragments to be concatenated - * with user input, such as “SELECT * FROM table WHERE field = ‘”; - * SQL query fragments containing user input but missing an ending - * single quote, such as “SELECT * FROM table WHERE field = ‘value”; - * connecting punctuation, such as “’, “; and any combinations of the - * above with paired-off single quotes, such as “SELECT * FROM table - * WHERE field1 = ‘value1’, field2 = ‘value2’, field3 = ‘”. + *

Common use cases include: SQL query fragments to be concatenated with user input, such as + * “SELECT * FROM table WHERE field = ‘”; SQL query fragments containing user input but missing an + * ending single quote, such as “SELECT * FROM table WHERE field = ‘value”; connecting punctuation, + * such as “’, “; and any combinations of the above with paired-off single quotes, such as “SELECT * + * FROM table WHERE field1 = ‘value1’, field2 = ‘value2’, field3 = ‘”. */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQueryUnknown.class) -@QualifierForLiterals(stringPatterns = "^(([^\\\\\\']|\\\\.)*\\')([^\\\\\\']|\\'([^\\\\\\']|\\\\.)*\\'|\\\\.)*\\\\?$") +@QualifierForLiterals( + stringPatterns = "^(([^\\\\\\']|\\\\.)*\\')([^\\\\\\']|\\'([^\\\\\\']|\\\\.)*\\'|\\\\.)*\\\\?$") public @interface SqlOddQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java index d6af47df514..6db1bd62691 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java @@ -9,14 +9,13 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * Used to denote a String that comprises part of a SQL query and - * contains exactly zero unescaped single quotes – i.e., all occurrences - * of the ‘ character in such a String are preceded immediately by a / - * character. SQLQuoteless Strings are safe to be passed to query execution + * Used to denote a String that comprises part of a SQL query and contains exactly zero unescaped + * single quotes – i.e., all occurrences of the ‘ character in such a String are preceded + * immediately by a / character. SQLQuoteless Strings are safe to be passed to query execution * methods. * - * Common use cases include SQL query fragments such as “SELECT * FROM” - * and properly sanitized user input. + *

Common use cases include SQL query fragments such as “SELECT * FROM” and properly sanitized + * user input. */ @Documented @Retention(RetentionPolicy.RUNTIME) From 3dd69a1744ba7d44b0403d8b688c800a128c9afc Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Fri, 12 Jul 2024 15:02:29 -0700 Subject: [PATCH 043/184] Revised documentation and implementation of SQL query qualifiers: combined SqlQuoteless and SqlEvenQuotes; revised documentations --- .../sqlquerytainting/qual/SqlEvenQuotes.java | 17 ++++++------- .../sqlquerytainting/qual/SqlOddQuotes.java | 10 ++++---- .../qual/SqlQueryUnknown.java | 8 +++++- .../sqlquerytainting/qual/SqlQuoteless.java | 25 ------------------- 4 files changed, 20 insertions(+), 40 deletions(-) delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java index fe5c3c8d6ba..abed915b334 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java @@ -5,19 +5,18 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * Used to denote a String that comprises part of a SQL query and contains an even number of - * unescaped single quotes – i.e., there must be an even number of ‘ characters in a SqlEvenQuotes - * String that are not preceded immediately by a / character. SQLEvenQuotes Strings are safe to be - * passed to query execution methods. + * SqlEvenQuotes: Used to denote a String that comprises part of a SQL query and contains either + * zero or an even number of unescaped single quotes – i.e., there must be either zero or an even + * number of ‘ characters in a SqlEvenQuotes String that are not preceded immediately by a \ + * character. SqlEvenQuotes Strings are syntactical and safe to be passed to query execution + * methods. * - *

Common use cases include: complete SQL queries, such as “SELECT * FROM table WHERE field = - * ‘value’”. + *

Common use cases include: SQL query fragments, such as “SELECT * FROM”; properly sanitized + * user input; and complete SQL queries, such as “SELECT * FROM table WHERE field = ‘value’”. */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQueryUnknown.class) -@QualifierForLiterals( - stringPatterns = - "^(([^\\\\\\']|\\\\.)*\\'){2}([^\\\\\\']|(\\'([^\\\\\\']|\\\\.)*\\')|\\\\.)*\\\\?$") +@QualifierForLiterals(stringPatterns = "^((([^\\\\']|\\\\.)*'){2})*([^\\\\']|\\\\.)*\\\\?$") public @interface SqlEvenQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java index 94c7c804858..90bd29e2033 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java @@ -5,10 +5,10 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * Used to denote a String that comprises part of a SQL query and contains an odd number of - * unescaped single quotes – i.e., there must be an odd number of ‘ characters in a SqlOddQuotes - * String that are not preceded immediately by a / character. SQLOddQuotes Strings are not safe to - * be passed to query execution methods. + * SqlOddQuotes: Used to denote a String that comprises part of a SQL query and contains an odd + * number of unescaped single quotes – i.e., there must be an odd number of ‘ characters in a + * SqlOddQuotes String that are not preceded immediately by a \ character. SqlOddQuotes Strings are + * not syntactical to be passed to query execution methods. * *

Common use cases include: SQL query fragments to be concatenated with user input, such as * “SELECT * FROM table WHERE field = ‘”; SQL query fragments containing user input but missing an @@ -21,5 +21,5 @@ @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQueryUnknown.class) @QualifierForLiterals( - stringPatterns = "^(([^\\\\\\']|\\\\.)*\\')([^\\\\\\']|\\'([^\\\\\\']|\\\\.)*\\'|\\\\.)*\\\\?$") + stringPatterns = "^(([^\\\\']|\\\\.)*')([^\\\\']|'([^\\\\']|\\\\.)*'|\\\\.)*\\\\?$") public @interface SqlOddQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java index 80962285d2c..76582b57758 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java @@ -4,7 +4,13 @@ import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; import org.checkerframework.framework.qual.SubtypeOf; -/** Represents the top of the SQL query tainting qualifier hierarchy. */ +/** + * Represents the top of the SQL query tainting qualifier hierarchy. Used to denote a String that + * comprises part of a SQL query, the quoting of which is unknown. SqlQueryUnknown Strings are SQL + * injection vulnerabilities and thus unsafe to be passed to query execution methods. + * + *

Common use cases include unsanitized user input. + */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java deleted file mode 100644 index 6db1bd62691..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuoteless.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.checkerframework.checker.sqlquerytainting.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.QualifierForLiterals; -import org.checkerframework.framework.qual.SubtypeOf; - -/** - * Used to denote a String that comprises part of a SQL query and contains exactly zero unescaped - * single quotes – i.e., all occurrences of the ‘ character in such a String are preceded - * immediately by a / character. SQLQuoteless Strings are safe to be passed to query execution - * methods. - * - *

Common use cases include SQL query fragments such as “SELECT * FROM” and properly sanitized - * user input. - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(SqlQueryUnknown.class) -@QualifierForLiterals(stringPatterns = "^([^\\']|(\\\\'))*$") -public @interface SqlQuoteless {} From 203f99246b43793feca60bf455132522fbc430bd Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Fri, 12 Jul 2024 15:03:05 -0700 Subject: [PATCH 044/184] Added type concatenation rules for SQL query qualifiers --- .../SqlQueryTaintingAnnotatedTypeFactory.java | 70 ++++++++++++++++--- 1 file changed, 62 insertions(+), 8 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java index 15a7d2247b4..8249ebdc8a1 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -1,21 +1,34 @@ package org.checkerframework.checker.sqlquerytainting; +import com.sun.source.tree.BinaryTree; import java.util.Set; import javax.lang.model.element.AnnotationMirror; -import org.checkerframework.checker.sqlquerytainting.qual.SqlSanitizedUser; +import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; +import org.checkerframework.checker.sqlquerytainting.qual.SqlOddQuotes; +import org.checkerframework.checker.sqlquerytainting.qual.SqlQueryUnknown; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.framework.type.AnnotatedTypeFactory; +import org.checkerframework.framework.type.AnnotatedTypeMirror; +import org.checkerframework.framework.type.treeannotator.TreeAnnotator; import org.checkerframework.javacutil.AnnotationBuilder; import org.checkerframework.javacutil.AnnotationMirrorSet; +import org.checkerframework.javacutil.TreeUtils; /** Annotated type factory for the SQL Query Tainting Checker. */ public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { - /** The {@code @}{@link SqlSanitizedUser} annotation mirror. */ - private final AnnotationMirror SQLSANITIZEDUSER; + /** The {@code @}{@link SqlEvenQuotes} annotation mirror. */ + private final AnnotationMirror SQLEVENQUOTES; - /** A singleton set containing the {@code @}{@link SqlSanitizedUser} annotation mirror. */ - private final AnnotationMirrorSet setOfSqlSanitizedUser; + /** The {@code @}{@link SqlOddQuotes} annotation mirror. */ + private final AnnotationMirror SQLODDQUOTES; + + /** The {@code @}{@link SqlQueryUnknown} annotation mirror. */ + private final AnnotationMirror SQLQUERYUNKNOWN; + + /** A singleton set containing the {@code @}{@link SqlEvenQuotes} annotation mirror. */ + private final AnnotationMirrorSet setOfSqlEvenQuotes; /** * Creates a {@link SqlQueryTaintingAnnotatedTypeFactory}. @@ -24,13 +37,54 @@ public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFacto */ public SqlQueryTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); - this.SQLSANITIZEDUSER = AnnotationBuilder.fromClass(getElementUtils(), SqlSanitizedUser.class); - this.setOfSqlSanitizedUser = AnnotationMirrorSet.singleton(SQLSANITIZEDUSER); + this.SQLEVENQUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlEvenQuotes.class); + this.SQLODDQUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlOddQuotes.class); + this.SQLQUERYUNKNOWN = AnnotationBuilder.fromClass(getElementUtils(), SqlQueryUnknown.class); + this.setOfSqlEvenQuotes = AnnotationMirrorSet.singleton(SQLEVENQUOTES); postInit(); } @Override protected Set getEnumConstructorQualifiers() { - return setOfSqlSanitizedUser; + return setOfSqlEvenQuotes; + } + + private class SqlQueryTaintingTreeAnnotator extends TreeAnnotator { + public SqlQueryTaintingTreeAnnotator(AnnotatedTypeFactory atypeFactory) { + super(atypeFactory); + } + + @Override + public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { + if (!type.hasPrimaryAnnotationInHierarchy(SQLQUERYUNKNOWN) + && TreeUtils.isStringConcatenation(tree)) { + AnnotatedTypeMirror leftType = getAnnotatedType(tree.getLeftOperand()); + AnnotatedTypeMirror rightType = getAnnotatedType(tree.getRightOperand()); + + if (leftType.hasPrimaryAnnotation(SQLQUERYUNKNOWN) + || rightType.hasPrimaryAnnotation(SQLQUERYUNKNOWN)) { + type.addAnnotation(SQLQUERYUNKNOWN); + return null; + } + + int leftParity = 0; + if (leftType.hasPrimaryAnnotation(SQLODDQUOTES)) { + leftParity = 1; + } + + int rightParity = 0; + if (rightType.hasPrimaryAnnotation(SQLODDQUOTES)) { + rightParity = 1; + } + + if (leftParity + rightParity % 2 == 0) { + type.addAnnotation(SQLEVENQUOTES); + } else { + type.addAnnotation(SQLODDQUOTES); + } + } + + return null; + } } } From 9ccadde333836ec5c578244845b3be69240407b0 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Fri, 12 Jul 2024 15:54:48 -0700 Subject: [PATCH 045/184] Debugged SQL query type factory --- .../SqlQueryTaintingAnnotatedTypeFactory.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java index 8249ebdc8a1..2212cc046e4 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -10,6 +10,7 @@ import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.framework.type.AnnotatedTypeFactory; import org.checkerframework.framework.type.AnnotatedTypeMirror; +import org.checkerframework.framework.type.treeannotator.ListTreeAnnotator; import org.checkerframework.framework.type.treeannotator.TreeAnnotator; import org.checkerframework.javacutil.AnnotationBuilder; import org.checkerframework.javacutil.AnnotationMirrorSet; @@ -49,6 +50,12 @@ protected Set getEnumConstructorQualifiers() { return setOfSqlEvenQuotes; } + @Override + public TreeAnnotator createTreeAnnotator() { + return new ListTreeAnnotator( + new SqlQueryTaintingAnnotatedTypeFactory.SqlQueryTaintingTreeAnnotator(this)); + } + private class SqlQueryTaintingTreeAnnotator extends TreeAnnotator { public SqlQueryTaintingTreeAnnotator(AnnotatedTypeFactory atypeFactory) { super(atypeFactory); From c5f15a28ec03bb33b8a31ef5848776d9b472dc9d Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Fri, 12 Jul 2024 15:55:10 -0700 Subject: [PATCH 046/184] Added SQL query bottom type --- .../sqlquerytainting/qual/SqlQueryBottom.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryBottom.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryBottom.java new file mode 100644 index 00000000000..8d58e4de03c --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryBottom.java @@ -0,0 +1,22 @@ +package org.checkerframework.checker.sqlquerytainting.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.DefaultFor; +import org.checkerframework.framework.qual.InvisibleQualifier; +import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TargetLocations; +import org.checkerframework.framework.qual.TypeUseLocation; + +/** Represents the bottom of the SQL query tainting qualifier hierarchy. */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@InvisibleQualifier +@SubtypeOf({SqlEvenQuotes.class, SqlOddQuotes.class}) +@DefaultFor(value = {TypeUseLocation.LOWER_BOUND}) +public @interface SqlQueryBottom {} From 0f401db263409ecd20001557266174efacc27e5b Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Fri, 12 Jul 2024 16:23:26 -0700 Subject: [PATCH 047/184] Added test files for SQL query tainting regex --- .../test/junit/SqlQueryTaintingTest.java | 24 ++++++++++ .../sqlquerytainting/SimpleSqlQuery.java | 48 ------------------- .../sqlquerytainting/SqlQualifierRegex.java | 12 +++++ 3 files changed, 36 insertions(+), 48 deletions(-) create mode 100644 checker/src/test/java/org/checkerframework/checker/test/junit/SqlQueryTaintingTest.java delete mode 100644 checker/tests/sqlquerytainting/SimpleSqlQuery.java create mode 100644 checker/tests/sqlquerytainting/SqlQualifierRegex.java diff --git a/checker/src/test/java/org/checkerframework/checker/test/junit/SqlQueryTaintingTest.java b/checker/src/test/java/org/checkerframework/checker/test/junit/SqlQueryTaintingTest.java new file mode 100644 index 00000000000..8f6d47e28f5 --- /dev/null +++ b/checker/src/test/java/org/checkerframework/checker/test/junit/SqlQueryTaintingTest.java @@ -0,0 +1,24 @@ +package org.checkerframework.checker.test.junit; + +import java.io.File; +import java.util.List; +import org.checkerframework.checker.sqlquerytainting.SqlQueryTaintingChecker; +import org.checkerframework.framework.test.CheckerFrameworkPerDirectoryTest; +import org.junit.runners.Parameterized.Parameters; + +public class SqlQueryTaintingTest extends CheckerFrameworkPerDirectoryTest { + + /** + * Create a TaintingTest. + * + * @param testFiles the files containing test code, which will be type-checked + */ + public SqlQueryTaintingTest(List testFiles) { + super(testFiles, SqlQueryTaintingChecker.class, "sqlquerytainting"); + } + + @Parameters + public static String[] getTestDirs() { + return new String[] {"sqlquerytainting", "all-systems"}; + } +} diff --git a/checker/tests/sqlquerytainting/SimpleSqlQuery.java b/checker/tests/sqlquerytainting/SimpleSqlQuery.java deleted file mode 100644 index 4302a57e28a..00000000000 --- a/checker/tests/sqlquerytainting/SimpleSqlQuery.java +++ /dev/null @@ -1,48 +0,0 @@ -import org.checkerframework.checker.sqltainting.qual.SqlSanitized; - -public class SimpleSqlQueryValue { - - void execute(@SqlSanitized String s) {} - - void unsanitized(String s) {} - - void stringLiteral() { - execute("ldskjfldj"); - unsanitized("lksjdflkjdf"); - } - - void stringRef(String ref) { - // :: error: (argument) - execute(ref); // error - - unsanitized(ref); - } - - void safeRef(@SqlSanitized String ref) { - execute(ref); - unsanitized(ref); - } - - void concatenation(@SqlSanitized String s1, String s2) { - execute(s1 + s1); - execute(s1 += s1); - execute(s1 + "m"); - // :: error: (argument) - execute(s1 + s2); // error - - // :: error: (argument) - execute(s2 + s1); // error - // :: error: (argument) - execute(s2 + "m"); // error - // :: error: (argument) - execute(s2 + s2); // error - - unsanitized(s1 + s1); - unsanitized(s1 + "m"); - unsanitized(s1 + s2); - - unsanitized(s2 + s1); - unsanitized(s2 + "m"); - unsanitized(s2 + s2); - } -} diff --git a/checker/tests/sqlquerytainting/SqlQualifierRegex.java b/checker/tests/sqlquerytainting/SqlQualifierRegex.java new file mode 100644 index 00000000000..e728b8b365a --- /dev/null +++ b/checker/tests/sqlquerytainting/SqlQualifierRegex.java @@ -0,0 +1,12 @@ +import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; +import org.checkerframework.checker.sqlquerytainting.qual.SqlOddQuotes; + +public class SqlQualifierRegex { + + void oddQuotes() { + // :: error: (argument) + @SqlOddQuotes String odd1 = ""; // error + + @SqlEvenQuotes String even1 = ""; + } +} From 9092e4c100333f63dcb368ceb698795d8b4b55be Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 12 Jul 2024 16:51:57 -0700 Subject: [PATCH 048/184] Update expected error --- checker/tests/sqlquerytainting/SqlQualifierRegex.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/checker/tests/sqlquerytainting/SqlQualifierRegex.java b/checker/tests/sqlquerytainting/SqlQualifierRegex.java index e728b8b365a..c3e901e77e2 100644 --- a/checker/tests/sqlquerytainting/SqlQualifierRegex.java +++ b/checker/tests/sqlquerytainting/SqlQualifierRegex.java @@ -4,8 +4,8 @@ public class SqlQualifierRegex { void oddQuotes() { - // :: error: (argument) - @SqlOddQuotes String odd1 = ""; // error + // :: error: (assignment) + @SqlOddQuotes String odd1 = ""; @SqlEvenQuotes String even1 = ""; } From 61f745cc0f1abb19276b09ae70a47687f83716cb Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 12 Jul 2024 16:55:36 -0700 Subject: [PATCH 049/184] By convention, all-caps variables use `_` as a word separator --- .../SqlQueryTaintingAnnotatedTypeFactory.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java index 2212cc046e4..6fbda671239 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -20,13 +20,13 @@ public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { /** The {@code @}{@link SqlEvenQuotes} annotation mirror. */ - private final AnnotationMirror SQLEVENQUOTES; + private final AnnotationMirror SQL_EVEN_QUOTES; /** The {@code @}{@link SqlOddQuotes} annotation mirror. */ - private final AnnotationMirror SQLODDQUOTES; + private final AnnotationMirror SQL_ODD_QUOTES; /** The {@code @}{@link SqlQueryUnknown} annotation mirror. */ - private final AnnotationMirror SQLQUERYUNKNOWN; + private final AnnotationMirror SQL_QUERY_UNKNOWN; /** A singleton set containing the {@code @}{@link SqlEvenQuotes} annotation mirror. */ private final AnnotationMirrorSet setOfSqlEvenQuotes; @@ -38,10 +38,10 @@ public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFacto */ public SqlQueryTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); - this.SQLEVENQUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlEvenQuotes.class); - this.SQLODDQUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlOddQuotes.class); - this.SQLQUERYUNKNOWN = AnnotationBuilder.fromClass(getElementUtils(), SqlQueryUnknown.class); - this.setOfSqlEvenQuotes = AnnotationMirrorSet.singleton(SQLEVENQUOTES); + this.SQL_EVEN_QUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlEvenQuotes.class); + this.SQL_ODD_QUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlOddQuotes.class); + this.SQL_QUERY_UNKNOWN = AnnotationBuilder.fromClass(getElementUtils(), SqlQueryUnknown.class); + this.setOfSqlEvenQuotes = AnnotationMirrorSet.singleton(SQL_EVEN_QUOTES); postInit(); } @@ -63,31 +63,31 @@ public SqlQueryTaintingTreeAnnotator(AnnotatedTypeFactory atypeFactory) { @Override public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { - if (!type.hasPrimaryAnnotationInHierarchy(SQLQUERYUNKNOWN) + if (!type.hasPrimaryAnnotationInHierarchy(SQL_QUERY_UNKNOWN) && TreeUtils.isStringConcatenation(tree)) { AnnotatedTypeMirror leftType = getAnnotatedType(tree.getLeftOperand()); AnnotatedTypeMirror rightType = getAnnotatedType(tree.getRightOperand()); - if (leftType.hasPrimaryAnnotation(SQLQUERYUNKNOWN) - || rightType.hasPrimaryAnnotation(SQLQUERYUNKNOWN)) { - type.addAnnotation(SQLQUERYUNKNOWN); + if (leftType.hasPrimaryAnnotation(SQL_QUERY_UNKNOWN) + || rightType.hasPrimaryAnnotation(SQL_QUERY_UNKNOWN)) { + type.addAnnotation(SQL_QUERY_UNKNOWN); return null; } int leftParity = 0; - if (leftType.hasPrimaryAnnotation(SQLODDQUOTES)) { + if (leftType.hasPrimaryAnnotation(SQL_ODD_QUOTES)) { leftParity = 1; } int rightParity = 0; - if (rightType.hasPrimaryAnnotation(SQLODDQUOTES)) { + if (rightType.hasPrimaryAnnotation(SQL_ODD_QUOTES)) { rightParity = 1; } if (leftParity + rightParity % 2 == 0) { - type.addAnnotation(SQLEVENQUOTES); + type.addAnnotation(SQL_EVEN_QUOTES); } else { - type.addAnnotation(SQLODDQUOTES); + type.addAnnotation(SQL_ODD_QUOTES); } } From b08cfc2989f04c296b52fb46fead9136135db10b Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 12 Jul 2024 17:12:59 -0700 Subject: [PATCH 050/184] Include the default tree annotators as well --- .../sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java | 1 + 1 file changed, 1 insertion(+) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java index 6fbda671239..670aa9c585f 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -53,6 +53,7 @@ protected Set getEnumConstructorQualifiers() { @Override public TreeAnnotator createTreeAnnotator() { return new ListTreeAnnotator( + super.createTreeAnnotator(), new SqlQueryTaintingAnnotatedTypeFactory.SqlQueryTaintingTreeAnnotator(this)); } From d64ec6a1be98934565e571efb0c71d093d60bb12 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 12 Jul 2024 17:30:32 -0700 Subject: [PATCH 051/184] Use possessive quantifiers (no backtracking) --- .../checker/sqlquerytainting/qual/SqlEvenQuotes.java | 2 +- .../checker/sqlquerytainting/qual/SqlOddQuotes.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java index abed915b334..62124499c86 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java @@ -18,5 +18,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQueryUnknown.class) -@QualifierForLiterals(stringPatterns = "^((([^\\\\']|\\\\.)*'){2})*([^\\\\']|\\\\.)*\\\\?$") +@QualifierForLiterals(stringPatterns = "^((([^\\\\']|\\\\.)*+'){2})*+([^\\\\']|\\\\.)*+\\\\?$") public @interface SqlEvenQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java index 90bd29e2033..600767ee25e 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java @@ -21,5 +21,5 @@ @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQueryUnknown.class) @QualifierForLiterals( - stringPatterns = "^(([^\\\\']|\\\\.)*')([^\\\\']|'([^\\\\']|\\\\.)*'|\\\\.)*\\\\?$") + stringPatterns = "^(([^\\\\']|\\\\.)*+')([^\\\\']|'([^\\\\']|\\\\.)*+'|\\\\.)*+\\\\?$") public @interface SqlOddQuotes {} From 9a259f8be8d414fed0e541774d1e2dc1793cfca3 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 16 Jul 2024 02:36:03 -0700 Subject: [PATCH 052/184] Added test file for qualifier regex --- .../sqlquerytainting/SqlQualifierRegex.java | 47 +++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/checker/tests/sqlquerytainting/SqlQualifierRegex.java b/checker/tests/sqlquerytainting/SqlQualifierRegex.java index c3e901e77e2..0dd114f15a5 100644 --- a/checker/tests/sqlquerytainting/SqlQualifierRegex.java +++ b/checker/tests/sqlquerytainting/SqlQualifierRegex.java @@ -3,10 +3,51 @@ public class SqlQualifierRegex { - void oddQuotes() { + void oddNoEscaped() { // :: error: (assignment) - @SqlOddQuotes String odd1 = ""; + @SqlOddQuotes String none = "asdf"; + @SqlOddQuotes String one = "asdf'asdf"; + // :: error: (assignment) + @SqlOddQuotes String two = "'asdf'"; + @SqlOddQuotes String three = "'asdf'asdf'"; + // :: error: (assignment) + @SqlOddQuotes String manyEven = "'asdf''asdf'asdf'asdf'''"; + @SqlOddQuotes String manyOdd = "''asdf'asdf'''asdf'asdf''"; + } + + void oddWithBackslashes() { + // :: error: (assignment) + @SqlOddQuotes String none = "asdf\\'"; + @SqlOddQuotes String one = "asdf\\''asdf"; + // :: error: (assignment) + @SqlOddQuotes String two = "'a\\'sdf'"; + @SqlOddQuotes String three = "\\''asdf'\\asdf'"; + // :: error: (assignment) + @SqlOddQuotes String manyEven = "'as\\'df'\\''a\\sdf'asdf'as\\'\\'df'\\'''"; + @SqlOddQuotes String manyOdd = "'\\''a\\sdf'asdf'''as\\df'as\\'df''\\'"; + } - @SqlEvenQuotes String even1 = ""; + void evenNoEscaped() { + @SqlEvenQuotes String none = ""; + // :: error: (assignment) + @SqlEvenQuotes String one = "'asdf"; + @SqlEvenQuotes String two = "''asdf"; + // :: error: (assignment) + @SqlEvenQuotes String three = "asdf'asdf''"; + @SqlEvenQuotes String manyEven = "''asdf''asdf'asdf''asdf'asdf"; + // :: error: (assignment) + @SqlEvenQuotes String manyOdd = "asdf''''asdf'asdf'asdf'asdf"; + } + + void evenWithBackslashes() { + @SqlEvenQuotes String none = "\\'\\'\\'"; + // :: error: (assignment) + @SqlEvenQuotes String one = "'asdf\\'"; + @SqlEvenQuotes String two = "'\\''a\\sdf"; + // :: error: (assignment) + @SqlEvenQuotes String three = "asd\\'f'asdf''"; + @SqlEvenQuotes String manyEven = "\\'''asdf''asd\\f'\\asdf'\\''asdf'asdf\\'"; + // :: error: (assignment) + @SqlEvenQuotes String manyOdd = "asdf''\\'''\\asdf'asdf'a\\'sdf'\\'asdf"; } } From 34f4d558990e5239103d281642c9a82a67afb56a Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 16 Jul 2024 02:36:29 -0700 Subject: [PATCH 053/184] Added test file for qualifier concatenation --- .../sqlquerytainting/SqlQualifierConcat.java | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 checker/tests/sqlquerytainting/SqlQualifierConcat.java diff --git a/checker/tests/sqlquerytainting/SqlQualifierConcat.java b/checker/tests/sqlquerytainting/SqlQualifierConcat.java new file mode 100644 index 00000000000..05ab410caea --- /dev/null +++ b/checker/tests/sqlquerytainting/SqlQualifierConcat.java @@ -0,0 +1,93 @@ +import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; +import org.checkerframework.checker.sqlquerytainting.qual.SqlOddQuotes; +import org.checkerframework.checker.sqlquerytainting.qual.SqlQueryUnknown; + +public class SqlQualifierConcat { + void oddOddConcat() { + @SqlOddQuotes String odd1 = "asd\\'f'asdf''\\"; + @SqlOddQuotes String odd2 = "''asdf''''asdf'asdf'asdf'asdf"; + // :: error: (assignment) + @SqlOddQuotes String oddResult1 = odd1 + odd2; + @SqlEvenQuotes String evenResult1 = odd1 + odd2; + + @SqlOddQuotes String odd3 = "'asdf"; + @SqlOddQuotes String odd4 = "', "; + // :: error: (assignment) + @SqlOddQuotes String oddResult2 = odd3 + odd4; + @SqlEvenQuotes String evenResult2 = odd3 + odd4; + } + + void oddEvenConcat() { + @SqlOddQuotes String odd1 = "asd\\'f'asdf''\\"; + @SqlEvenQuotes String even1 = "'\\''a\\sdf"; + // :: error: (assignment) + @SqlEvenQuotes String evenResult1 = odd1 + even1; + @SqlOddQuotes String oddResult1 = odd1 + even1; + + @SqlOddQuotes String odd2 = "'asdf"; + @SqlEvenQuotes String even2 = "', asdf '"; + // :: error: (assignment) + @SqlEvenQuotes String evenResult2 = odd2 + even2; + @SqlOddQuotes String oddResult2 = odd2 + even2; + } + + void evenOddConcat() { + @SqlOddQuotes String odd1 = "asd\\'f'asdf''\\"; + @SqlEvenQuotes String even1 = "'\\''a\\sdf"; + // :: error: (assignment) + @SqlEvenQuotes String evenResult1 = even1 + odd1; + @SqlOddQuotes String oddResult1 = even1 + odd1; + + @SqlOddQuotes String odd2 = "'asdf"; + @SqlEvenQuotes String even2 = "', asdf '"; + // :: error: (assignment) + @SqlEvenQuotes String evenResult2 = even2 + odd2; + @SqlOddQuotes String oddResult2 = even2 + odd2; + } + + void evenEvenConcat() { + @SqlEvenQuotes String even1 = "\\'''asdf''asd\\f'\\asdf'\\''asdf'asdf\\'"; + @SqlEvenQuotes String even2 = "''asdf"; + // :: error: (assignment) + @SqlOddQuotes String oddResult1 = even1 + even2; + @SqlEvenQuotes String evenResult1 = even1 + even2; + + @SqlEvenQuotes String even3 = "'a\\'sdf'"; + @SqlEvenQuotes String even4 = "'asdf''asdf'asdf'asdf'''"; + // :: error: (assignment) + @SqlOddQuotes String oddResult2 = even3 + even4; + @SqlEvenQuotes String evenResult2 = even3 + even4; + } + + void withTopConcat(@SqlQueryUnknown String top) { + @SqlOddQuotes String odd1 = "'asdf"; + // :: error: (assignment) + @SqlOddQuotes String oddResult1 = odd1 + top; + // :: error: (assignment) + @SqlEvenQuotes String evenResult1 = odd1 + top; + String topResult1 = odd1 + top; + // :: error: (assignment) + @SqlOddQuotes String oddResult2 = top + odd1; + // :: error: (assignment) + @SqlEvenQuotes String evenResult2 = top + odd1; + String topResult2 = top + odd1; + + @SqlEvenQuotes String even1 = "'a\\'sdf'"; + // :: error: (assignment) + @SqlOddQuotes String oddResult3 = even1 + top; + // :: error: (assignment) + @SqlEvenQuotes String evenResult3 = even1 + top; + String topResult3 = even1 + top; + // :: error: (assignment) + @SqlOddQuotes String oddResult4 = top + even1; + // :: error: (assignment) + @SqlEvenQuotes String evenResult4 = top + even1; + String topResult4 = top + even1; + + // :: error: (assignment) + @SqlOddQuotes String oddResult5 = top + top; + // :: error: (assignment) + @SqlEvenQuotes String evenResult5 = top + top; + String topResult5 = top + top; + } +} From 9ae2a22b4a72990a4ecdf425532b718cc4473ae5 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 16 Jul 2024 02:39:41 -0700 Subject: [PATCH 054/184] Revised order of operations bug --- .../SqlQueryTaintingAnnotatedTypeFactory.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java index 670aa9c585f..dc35c2064e9 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -64,14 +64,13 @@ public SqlQueryTaintingTreeAnnotator(AnnotatedTypeFactory atypeFactory) { @Override public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { - if (!type.hasPrimaryAnnotationInHierarchy(SQL_QUERY_UNKNOWN) - && TreeUtils.isStringConcatenation(tree)) { + if (TreeUtils.isStringConcatenation(tree)) { AnnotatedTypeMirror leftType = getAnnotatedType(tree.getLeftOperand()); AnnotatedTypeMirror rightType = getAnnotatedType(tree.getRightOperand()); if (leftType.hasPrimaryAnnotation(SQL_QUERY_UNKNOWN) || rightType.hasPrimaryAnnotation(SQL_QUERY_UNKNOWN)) { - type.addAnnotation(SQL_QUERY_UNKNOWN); + type.replaceAnnotation(SQL_QUERY_UNKNOWN); return null; } @@ -85,10 +84,10 @@ public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { rightParity = 1; } - if (leftParity + rightParity % 2 == 0) { - type.addAnnotation(SQL_EVEN_QUOTES); + if ((leftParity + rightParity) % 2 == 0) { + type.replaceAnnotation(SQL_EVEN_QUOTES); } else { - type.addAnnotation(SQL_ODD_QUOTES); + type.replaceAnnotation(SQL_ODD_QUOTES); } } From ef80d51b1824e454fc342708c7d6e2fe589c2aa7 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 16 Jul 2024 12:56:38 -0700 Subject: [PATCH 055/184] Added stub file for Java SQL executeQuery --- .../checker/sqlquerytainting/Statement.astub | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 checker/src/main/java/org/checkerframework/checker/sqlquerytainting/Statement.astub diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/Statement.astub b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/Statement.astub new file mode 100644 index 00000000000..5cd92218614 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/Statement.astub @@ -0,0 +1,9 @@ +package java.sql; + +import java.util.regex.Pattern; + +import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; + +public interface Statement extends Wrapper, AutoCloseable { + ResultSet executeQuery(@SqlEvenQuotes String var1) throws SQLException; +} From adb57037388ea51ca27b21519bdc77f457f5c672 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 16 Jul 2024 12:57:51 -0700 Subject: [PATCH 056/184] Added stub file for Java base64 encrypt --- .../sqlquerytainting/BCryptPasswordEncoder.astub | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 checker/src/main/java/org/checkerframework/checker/sqlquerytainting/BCryptPasswordEncoder.astub diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/BCryptPasswordEncoder.astub b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/BCryptPasswordEncoder.astub new file mode 100644 index 00000000000..a586ddb2abf --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/BCryptPasswordEncoder.astub @@ -0,0 +1,14 @@ +package org.springframework.security.crypto.bcrypt; + +import java.security.SecureRandom; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.security.crypto.password.PasswordEncoder; + +import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; + +public class BCryptPasswordEncoder implements PasswordEncoder { + @SqlEvenQuotes String encode(CharSequence rawPassword); +} From b3eca81153bcc6d197db5a617bf3868eae9b3cb5 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 16 Jul 2024 13:24:43 -0700 Subject: [PATCH 057/184] Added stub file for ResultSet getString --- .../checker/sqlquerytainting/ResultSet.astub | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 checker/src/main/java/org/checkerframework/checker/sqlquerytainting/ResultSet.astub diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/ResultSet.astub b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/ResultSet.astub new file mode 100644 index 00000000000..d4b41ee7899 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/ResultSet.astub @@ -0,0 +1,7 @@ +package java.sql; + +import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; + +public interface ResultSet extends Wrapper, AutoCloseable { + @SqlEvenQuotes String getString(int var1) throws SQLException; +} From 8efe5b4f48954cab1b5a7a25ae6a637787a3f20a Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 16 Jul 2024 16:35:06 -0700 Subject: [PATCH 058/184] Removed stub file for ResultSet --- .../checker/sqlquerytainting/ResultSet.astub | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 checker/src/main/java/org/checkerframework/checker/sqlquerytainting/ResultSet.astub diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/ResultSet.astub b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/ResultSet.astub deleted file mode 100644 index d4b41ee7899..00000000000 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/ResultSet.astub +++ /dev/null @@ -1,7 +0,0 @@ -package java.sql; - -import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; - -public interface ResultSet extends Wrapper, AutoCloseable { - @SqlEvenQuotes String getString(int var1) throws SQLException; -} From f06da3c97ab5da1e283f59f2172ccba4df651ca3 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 16 Jul 2024 16:44:01 -0700 Subject: [PATCH 059/184] Added stub file annotation --- .../checker/sqlquerytainting/SqlQueryTaintingChecker.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java index b69319c5d2a..5ab2b0c42d9 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java @@ -1,6 +1,7 @@ package org.checkerframework.checker.sqlquerytainting; import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.framework.qual.StubFiles; import org.checkerframework.framework.source.SuppressWarningsPrefix; /** @@ -11,4 +12,5 @@ * sanitized before use. */ @SuppressWarningsPrefix({"sqlquerysanitized", "sqlquerytainting"}) +@StubFiles({"BCryptPasswordEncoder.astub", "Statement.astub"}) public class SqlQueryTaintingChecker extends BaseTypeChecker {} From 26e70014f3f32f69aff6812962d7a48d495cb6c3 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 18 Jul 2024 10:23:23 -0700 Subject: [PATCH 060/184] Rename top and bottom qualifiers --- .../sqlquerytainting/qual/SqlEvenQuotes.java | 2 +- .../sqlquerytainting/qual/SqlOddQuotes.java | 2 +- .../{SqlQueryBottom.java => SqlQuotesBottom.java} | 2 +- ...SqlQueryUnknown.java => SqlQuotesUnknown.java} | 4 ++-- .../SqlQueryTaintingAnnotatedTypeFactory.java | 15 ++++++++------- .../sqlquerytainting/SqlQualifierConcat.java | 4 ++-- 6 files changed, 15 insertions(+), 14 deletions(-) rename checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/{SqlQueryBottom.java => SqlQuotesBottom.java} (96%) rename checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/{SqlQueryUnknown.java => SqlQuotesUnknown.java} (90%) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java index 62124499c86..5c709040bdc 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java @@ -17,6 +17,6 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(SqlQueryUnknown.class) +@SubtypeOf(SqlQuotesUnknown.class) @QualifierForLiterals(stringPatterns = "^((([^\\\\']|\\\\.)*+'){2})*+([^\\\\']|\\\\.)*+\\\\?$") public @interface SqlEvenQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java index 600767ee25e..42731e316a6 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java @@ -19,7 +19,7 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(SqlQueryUnknown.class) +@SubtypeOf(SqlQuotesUnknown.class) @QualifierForLiterals( stringPatterns = "^(([^\\\\']|\\\\.)*+')([^\\\\']|'([^\\\\']|\\\\.)*+'|\\\\.)*+\\\\?$") public @interface SqlOddQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesBottom.java similarity index 96% rename from checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryBottom.java rename to checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesBottom.java index 8d58e4de03c..7d00e665520 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesBottom.java @@ -19,4 +19,4 @@ @InvisibleQualifier @SubtypeOf({SqlEvenQuotes.class, SqlOddQuotes.class}) @DefaultFor(value = {TypeUseLocation.LOWER_BOUND}) -public @interface SqlQueryBottom {} +public @interface SqlQuotesBottom {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesUnknown.java similarity index 90% rename from checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java rename to checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesUnknown.java index 76582b57758..c3716026651 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesUnknown.java @@ -6,7 +6,7 @@ /** * Represents the top of the SQL query tainting qualifier hierarchy. Used to denote a String that - * comprises part of a SQL query, the quoting of which is unknown. SqlQueryUnknown Strings are SQL + * comprises part of a SQL query, the quoting of which is unknown. SqlQuotesUnknown Strings are SQL * injection vulnerabilities and thus unsafe to be passed to query execution methods. * *

Common use cases include unsanitized user input. @@ -16,4 +16,4 @@ @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf({}) @DefaultQualifierInHierarchy -public @interface SqlQueryUnknown {} +public @interface SqlQuotesUnknown {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java index dc35c2064e9..7faf46fa2d2 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java @@ -5,7 +5,7 @@ import javax.lang.model.element.AnnotationMirror; import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; import org.checkerframework.checker.sqlquerytainting.qual.SqlOddQuotes; -import org.checkerframework.checker.sqlquerytainting.qual.SqlQueryUnknown; +import org.checkerframework.checker.sqlquerytainting.qual.SqlQuotesUnknown; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.framework.type.AnnotatedTypeFactory; @@ -25,8 +25,8 @@ public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFacto /** The {@code @}{@link SqlOddQuotes} annotation mirror. */ private final AnnotationMirror SQL_ODD_QUOTES; - /** The {@code @}{@link SqlQueryUnknown} annotation mirror. */ - private final AnnotationMirror SQL_QUERY_UNKNOWN; + /** The {@code @}{@link SqlQuotesUnknown} annotation mirror. */ + private final AnnotationMirror SQL_QUOTES_UNKNOWN; /** A singleton set containing the {@code @}{@link SqlEvenQuotes} annotation mirror. */ private final AnnotationMirrorSet setOfSqlEvenQuotes; @@ -40,7 +40,8 @@ public SqlQueryTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); this.SQL_EVEN_QUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlEvenQuotes.class); this.SQL_ODD_QUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlOddQuotes.class); - this.SQL_QUERY_UNKNOWN = AnnotationBuilder.fromClass(getElementUtils(), SqlQueryUnknown.class); + this.SQL_QUOTES_UNKNOWN = + AnnotationBuilder.fromClass(getElementUtils(), SqlQuotesUnknown.class); this.setOfSqlEvenQuotes = AnnotationMirrorSet.singleton(SQL_EVEN_QUOTES); postInit(); } @@ -68,9 +69,9 @@ public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { AnnotatedTypeMirror leftType = getAnnotatedType(tree.getLeftOperand()); AnnotatedTypeMirror rightType = getAnnotatedType(tree.getRightOperand()); - if (leftType.hasPrimaryAnnotation(SQL_QUERY_UNKNOWN) - || rightType.hasPrimaryAnnotation(SQL_QUERY_UNKNOWN)) { - type.replaceAnnotation(SQL_QUERY_UNKNOWN); + if (leftType.hasPrimaryAnnotation(SQL_QUOTES_UNKNOWN) + || rightType.hasPrimaryAnnotation(SQL_QUOTES_UNKNOWN)) { + type.replaceAnnotation(SQL_QUOTES_UNKNOWN); return null; } diff --git a/checker/tests/sqlquerytainting/SqlQualifierConcat.java b/checker/tests/sqlquerytainting/SqlQualifierConcat.java index 05ab410caea..472d9de3c0b 100644 --- a/checker/tests/sqlquerytainting/SqlQualifierConcat.java +++ b/checker/tests/sqlquerytainting/SqlQualifierConcat.java @@ -1,6 +1,6 @@ import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; import org.checkerframework.checker.sqlquerytainting.qual.SqlOddQuotes; -import org.checkerframework.checker.sqlquerytainting.qual.SqlQueryUnknown; +import org.checkerframework.checker.sqlquerytainting.qual.SqlQuotesUnknown; public class SqlQualifierConcat { void oddOddConcat() { @@ -59,7 +59,7 @@ void evenEvenConcat() { @SqlEvenQuotes String evenResult2 = even3 + even4; } - void withTopConcat(@SqlQueryUnknown String top) { + void withTopConcat(@SqlQuotesUnknown String top) { @SqlOddQuotes String odd1 = "'asdf"; // :: error: (assignment) @SqlOddQuotes String oddResult1 = odd1 + top; From d906611f87a799a0d39f2e498716295cbfbc2cba Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 18 Jul 2024 10:49:34 -0700 Subject: [PATCH 061/184] Rename checker --- .../qual/SqlEvenQuotes.java | 2 +- .../qual/SqlOddQuotes.java | 2 +- .../qual/SqlQuotesBottom.java | 4 ++-- .../qual/SqlQuotesUnknown.java | 8 +++---- .../BCryptPasswordEncoder.astub | 2 +- .../SqlQuotesAnnotatedTypeFactory.java} | 22 +++++++++---------- .../SqlQuotesChecker.java} | 6 ++--- .../SqlQuotesVisitor.java} | 10 ++++----- .../Statement.astub | 2 +- ...ryTaintingTest.java => SqlQuotesTest.java} | 10 ++++----- .../SqlQuotesConcat.java} | 8 +++---- .../SqlQuotesRegex.java} | 6 ++--- 12 files changed, 41 insertions(+), 41 deletions(-) rename checker-qual/src/main/java/org/checkerframework/checker/{sqlquerytainting => sqlquotes}/qual/SqlEvenQuotes.java (94%) rename checker-qual/src/main/java/org/checkerframework/checker/{sqlquerytainting => sqlquotes}/qual/SqlOddQuotes.java (95%) rename checker-qual/src/main/java/org/checkerframework/checker/{sqlquerytainting => sqlquotes}/qual/SqlQuotesBottom.java (86%) rename checker-qual/src/main/java/org/checkerframework/checker/{sqlquerytainting => sqlquotes}/qual/SqlQuotesUnknown.java (54%) rename checker/src/main/java/org/checkerframework/checker/{sqlquerytainting => sqlquotes}/BCryptPasswordEncoder.astub (85%) rename checker/src/main/java/org/checkerframework/checker/{sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java => sqlquotes/SqlQuotesAnnotatedTypeFactory.java} (78%) rename checker/src/main/java/org/checkerframework/checker/{sqlquerytainting/SqlQueryTaintingChecker.java => sqlquotes/SqlQuotesChecker.java} (74%) rename checker/src/main/java/org/checkerframework/checker/{sqlquerytainting/SqlQueryTaintingVisitor.java => sqlquotes/SqlQuotesVisitor.java} (70%) rename checker/src/main/java/org/checkerframework/checker/{sqlquerytainting => sqlquotes}/Statement.astub (72%) rename checker/src/test/java/org/checkerframework/checker/test/junit/{SqlQueryTaintingTest.java => SqlQuotesTest.java} (54%) rename checker/tests/{sqlquerytainting/SqlQualifierConcat.java => sqlquotes/SqlQuotesConcat.java} (92%) rename checker/tests/{sqlquerytainting/SqlQualifierRegex.java => sqlquotes/SqlQuotesRegex.java} (90%) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java similarity index 94% rename from checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java rename to checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java index 5c709040bdc..85758ccb870 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.sqlquerytainting.qual; +package org.checkerframework.checker.sqlquotes.qual; import java.lang.annotation.*; import org.checkerframework.framework.qual.QualifierForLiterals; diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java similarity index 95% rename from checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java rename to checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java index 42731e316a6..957d7eb60af 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.sqlquerytainting.qual; +package org.checkerframework.checker.sqlquotes.qual; import java.lang.annotation.*; import org.checkerframework.framework.qual.QualifierForLiterals; diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java similarity index 86% rename from checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesBottom.java rename to checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java index 7d00e665520..98c45985156 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.sqlquerytainting.qual; +package org.checkerframework.checker.sqlquotes.qual; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -11,7 +11,7 @@ import org.checkerframework.framework.qual.TargetLocations; import org.checkerframework.framework.qual.TypeUseLocation; -/** Represents the bottom of the SQL query tainting qualifier hierarchy. */ +/** Represents the bottom of the SQL Quotes qualifier hierarchy. */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesUnknown.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java similarity index 54% rename from checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesUnknown.java rename to checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java index c3716026651..e54c70772cb 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQuotesUnknown.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java @@ -1,13 +1,13 @@ -package org.checkerframework.checker.sqlquerytainting.qual; +package org.checkerframework.checker.sqlquotes.qual; import java.lang.annotation.*; import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; import org.checkerframework.framework.qual.SubtypeOf; /** - * Represents the top of the SQL query tainting qualifier hierarchy. Used to denote a String that - * comprises part of a SQL query, the quoting of which is unknown. SqlQuotesUnknown Strings are SQL - * injection vulnerabilities and thus unsafe to be passed to query execution methods. + * Represents the top of the SQL Quotes qualifier hierarchy. Used to denote a String that comprises + * part of a SQL query, the quoting of which is unknown. SqlQuotesUnknown Strings are SQL injection + * vulnerabilities and thus unsafe to be passed to query execution methods. * *

Common use cases include unsanitized user input. */ diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/BCryptPasswordEncoder.astub b/checker/src/main/java/org/checkerframework/checker/sqlquotes/BCryptPasswordEncoder.astub similarity index 85% rename from checker/src/main/java/org/checkerframework/checker/sqlquerytainting/BCryptPasswordEncoder.astub rename to checker/src/main/java/org/checkerframework/checker/sqlquotes/BCryptPasswordEncoder.astub index a586ddb2abf..effc721c786 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/BCryptPasswordEncoder.astub +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/BCryptPasswordEncoder.astub @@ -7,7 +7,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.security.crypto.password.PasswordEncoder; -import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; +import org.checkerframework.checker.sqlquotes.qual.SqlEvenQuotes; public class BCryptPasswordEncoder implements PasswordEncoder { @SqlEvenQuotes String encode(CharSequence rawPassword); diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java similarity index 78% rename from checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java rename to checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java index 7faf46fa2d2..24d83dab458 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java @@ -1,11 +1,11 @@ -package org.checkerframework.checker.sqlquerytainting; +package org.checkerframework.checker.sqlquotes; import com.sun.source.tree.BinaryTree; import java.util.Set; import javax.lang.model.element.AnnotationMirror; -import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; -import org.checkerframework.checker.sqlquerytainting.qual.SqlOddQuotes; -import org.checkerframework.checker.sqlquerytainting.qual.SqlQuotesUnknown; +import org.checkerframework.checker.sqlquotes.qual.SqlEvenQuotes; +import org.checkerframework.checker.sqlquotes.qual.SqlOddQuotes; +import org.checkerframework.checker.sqlquotes.qual.SqlQuotesUnknown; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.framework.type.AnnotatedTypeFactory; @@ -16,8 +16,8 @@ import org.checkerframework.javacutil.AnnotationMirrorSet; import org.checkerframework.javacutil.TreeUtils; -/** Annotated type factory for the SQL Query Tainting Checker. */ -public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { +/** Annotated type factory for the SQL Quotes Checker. */ +public class SqlQuotesAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { /** The {@code @}{@link SqlEvenQuotes} annotation mirror. */ private final AnnotationMirror SQL_EVEN_QUOTES; @@ -32,11 +32,11 @@ public class SqlQueryTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFacto private final AnnotationMirrorSet setOfSqlEvenQuotes; /** - * Creates a {@link SqlQueryTaintingAnnotatedTypeFactory}. + * Creates a {@link SqlQuotesAnnotatedTypeFactory}. * * @param checker the SQL tainting checker */ - public SqlQueryTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { + public SqlQuotesAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); this.SQL_EVEN_QUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlEvenQuotes.class); this.SQL_ODD_QUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlOddQuotes.class); @@ -55,11 +55,11 @@ protected Set getEnumConstructorQualifiers() { public TreeAnnotator createTreeAnnotator() { return new ListTreeAnnotator( super.createTreeAnnotator(), - new SqlQueryTaintingAnnotatedTypeFactory.SqlQueryTaintingTreeAnnotator(this)); + new SqlQuotesAnnotatedTypeFactory.SqlQuotesTreeAnnotator(this)); } - private class SqlQueryTaintingTreeAnnotator extends TreeAnnotator { - public SqlQueryTaintingTreeAnnotator(AnnotatedTypeFactory atypeFactory) { + private class SqlQuotesTreeAnnotator extends TreeAnnotator { + public SqlQuotesTreeAnnotator(AnnotatedTypeFactory atypeFactory) { super(atypeFactory); } diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java similarity index 74% rename from checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java rename to checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java index 5ab2b0c42d9..4dba24a5f7b 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.sqlquerytainting; +package org.checkerframework.checker.sqlquotes; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.framework.qual.StubFiles; @@ -11,6 +11,6 @@ *

It verifies that only SQL-safe embedded query values are trusted and that user input is * sanitized before use. */ -@SuppressWarningsPrefix({"sqlquerysanitized", "sqlquerytainting"}) +@SuppressWarningsPrefix({"sqlquerysanitized", "sqlquotes"}) @StubFiles({"BCryptPasswordEncoder.astub", "Statement.astub"}) -public class SqlQueryTaintingChecker extends BaseTypeChecker {} +public class SqlQuotesChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesVisitor.java similarity index 70% rename from checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java rename to checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesVisitor.java index 4b0aba79624..f4d62e59317 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/SqlQueryTaintingVisitor.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesVisitor.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.sqlquerytainting; +package org.checkerframework.checker.sqlquotes; import javax.lang.model.element.ExecutableElement; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; @@ -6,15 +6,15 @@ import org.checkerframework.common.basetype.BaseTypeVisitor; import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType; -/** Visitor for the {@link SqlQueryTaintingChecker}. */ -public class SqlQueryTaintingVisitor extends BaseTypeVisitor { +/** Visitor for the {@link SqlQuotesChecker}. */ +public class SqlQuotesVisitor extends BaseTypeVisitor { /** - * Creates a {@link SqlQueryTaintingVisitor}. + * Creates a {@link SqlQuotesVisitor}. * * @param checker the checker that uses this visitor */ - public SqlQueryTaintingVisitor(BaseTypeChecker checker) { + public SqlQuotesVisitor(BaseTypeChecker checker) { super(checker); } diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/Statement.astub b/checker/src/main/java/org/checkerframework/checker/sqlquotes/Statement.astub similarity index 72% rename from checker/src/main/java/org/checkerframework/checker/sqlquerytainting/Statement.astub rename to checker/src/main/java/org/checkerframework/checker/sqlquotes/Statement.astub index 5cd92218614..71b9521c766 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquerytainting/Statement.astub +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/Statement.astub @@ -2,7 +2,7 @@ package java.sql; import java.util.regex.Pattern; -import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; +import org.checkerframework.checker.sqlquotes.qual.SqlEvenQuotes; public interface Statement extends Wrapper, AutoCloseable { ResultSet executeQuery(@SqlEvenQuotes String var1) throws SQLException; diff --git a/checker/src/test/java/org/checkerframework/checker/test/junit/SqlQueryTaintingTest.java b/checker/src/test/java/org/checkerframework/checker/test/junit/SqlQuotesTest.java similarity index 54% rename from checker/src/test/java/org/checkerframework/checker/test/junit/SqlQueryTaintingTest.java rename to checker/src/test/java/org/checkerframework/checker/test/junit/SqlQuotesTest.java index 8f6d47e28f5..6c966841b37 100644 --- a/checker/src/test/java/org/checkerframework/checker/test/junit/SqlQueryTaintingTest.java +++ b/checker/src/test/java/org/checkerframework/checker/test/junit/SqlQuotesTest.java @@ -2,23 +2,23 @@ import java.io.File; import java.util.List; -import org.checkerframework.checker.sqlquerytainting.SqlQueryTaintingChecker; +import org.checkerframework.checker.sqlquotes.SqlQuotesChecker; import org.checkerframework.framework.test.CheckerFrameworkPerDirectoryTest; import org.junit.runners.Parameterized.Parameters; -public class SqlQueryTaintingTest extends CheckerFrameworkPerDirectoryTest { +public class SqlQuotesTest extends CheckerFrameworkPerDirectoryTest { /** * Create a TaintingTest. * * @param testFiles the files containing test code, which will be type-checked */ - public SqlQueryTaintingTest(List testFiles) { - super(testFiles, SqlQueryTaintingChecker.class, "sqlquerytainting"); + public SqlQuotesTest(List testFiles) { + super(testFiles, SqlQuotesChecker.class, "sqlquotes"); } @Parameters public static String[] getTestDirs() { - return new String[] {"sqlquerytainting", "all-systems"}; + return new String[] {"sqlquotes", "all-systems"}; } } diff --git a/checker/tests/sqlquerytainting/SqlQualifierConcat.java b/checker/tests/sqlquotes/SqlQuotesConcat.java similarity index 92% rename from checker/tests/sqlquerytainting/SqlQualifierConcat.java rename to checker/tests/sqlquotes/SqlQuotesConcat.java index 472d9de3c0b..b2ef3deaab5 100644 --- a/checker/tests/sqlquerytainting/SqlQualifierConcat.java +++ b/checker/tests/sqlquotes/SqlQuotesConcat.java @@ -1,8 +1,8 @@ -import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; -import org.checkerframework.checker.sqlquerytainting.qual.SqlOddQuotes; -import org.checkerframework.checker.sqlquerytainting.qual.SqlQuotesUnknown; +import org.checkerframework.checker.sqlquotes.qual.SqlEvenQuotes; +import org.checkerframework.checker.sqlquotes.qual.SqlOddQuotes; +import org.checkerframework.checker.sqlquotes.qual.SqlQuotesUnknown; -public class SqlQualifierConcat { +public class SqlQuotesConcat { void oddOddConcat() { @SqlOddQuotes String odd1 = "asd\\'f'asdf''\\"; @SqlOddQuotes String odd2 = "''asdf''''asdf'asdf'asdf'asdf"; diff --git a/checker/tests/sqlquerytainting/SqlQualifierRegex.java b/checker/tests/sqlquotes/SqlQuotesRegex.java similarity index 90% rename from checker/tests/sqlquerytainting/SqlQualifierRegex.java rename to checker/tests/sqlquotes/SqlQuotesRegex.java index 0dd114f15a5..72a46bd26f2 100644 --- a/checker/tests/sqlquerytainting/SqlQualifierRegex.java +++ b/checker/tests/sqlquotes/SqlQuotesRegex.java @@ -1,7 +1,7 @@ -import org.checkerframework.checker.sqlquerytainting.qual.SqlEvenQuotes; -import org.checkerframework.checker.sqlquerytainting.qual.SqlOddQuotes; +import org.checkerframework.checker.sqlquotes.qual.SqlEvenQuotes; +import org.checkerframework.checker.sqlquotes.qual.SqlOddQuotes; -public class SqlQualifierRegex { +public class SqlQuotesRegex { void oddNoEscaped() { // :: error: (assignment) From b4418927f96a30ab452f0ce9bc790d25644b8b7f Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 18 Jul 2024 19:48:45 -0700 Subject: [PATCH 062/184] Revised wildcard import --- .../qual/SqlQueryUnknown.java | 23 +++++++++++++++++++ .../checker/sqlquotes/qual/SqlEvenQuotes.java | 6 ++++- .../checker/sqlquotes/qual/SqlOddQuotes.java | 6 ++++- 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java new file mode 100644 index 00000000000..24c44e203b3 --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java @@ -0,0 +1,23 @@ +package org.checkerframework.checker.sqlquerytainting.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Represents the top of the SQL query tainting qualifier hierarchy. Used to denote a String that + * comprises part of a SQL query, the quoting of which is unknown. SqlQueryUnknown Strings are SQL + * injection vulnerabilities and thus unsafe to be passed to query execution methods. + * + *

Common use cases include unsanitized user input. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({}) +@DefaultQualifierInHierarchy +public @interface SqlQueryUnknown {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java index 85758ccb870..d7ef12811bd 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java @@ -1,6 +1,10 @@ package org.checkerframework.checker.sqlquotes.qual; -import java.lang.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import org.checkerframework.framework.qual.QualifierForLiterals; import org.checkerframework.framework.qual.SubtypeOf; diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java index 957d7eb60af..26aba3b31da 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java @@ -1,6 +1,10 @@ package org.checkerframework.checker.sqlquotes.qual; -import java.lang.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import org.checkerframework.framework.qual.QualifierForLiterals; import org.checkerframework.framework.qual.SubtypeOf; From e7ac031ac6683293d9a343bdb93982ad7de89d82 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 18 Jul 2024 19:55:19 -0700 Subject: [PATCH 063/184] Revised wildcard import in correct SqlQuotesUnknown file --- .../qual/SqlQueryUnknown.java | 23 ------------------- .../sqlquotes/qual/SqlQuotesUnknown.java | 6 ++++- 2 files changed, 5 insertions(+), 24 deletions(-) delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java deleted file mode 100644 index 24c44e203b3..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquerytainting/qual/SqlQueryUnknown.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.checkerframework.checker.sqlquerytainting.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; -import org.checkerframework.framework.qual.SubtypeOf; - -/** - * Represents the top of the SQL query tainting qualifier hierarchy. Used to denote a String that - * comprises part of a SQL query, the quoting of which is unknown. SqlQueryUnknown Strings are SQL - * injection vulnerabilities and thus unsafe to be passed to query execution methods. - * - *

Common use cases include unsanitized user input. - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf({}) -@DefaultQualifierInHierarchy -public @interface SqlQueryUnknown {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java index e54c70772cb..3dbfce7ada1 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java @@ -1,6 +1,10 @@ package org.checkerframework.checker.sqlquotes.qual; -import java.lang.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; import org.checkerframework.framework.qual.SubtypeOf; From def3064970aff5bb8b9f4fa6f013b831c1c53686 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 18 Jul 2024 20:33:29 -0700 Subject: [PATCH 064/184] Added call to super.visitBinary() --- .../checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java | 1 + 1 file changed, 1 insertion(+) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java index 24d83dab458..38dac7c193b 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java @@ -65,6 +65,7 @@ public SqlQuotesTreeAnnotator(AnnotatedTypeFactory atypeFactory) { @Override public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { + super.visitBinary(tree, type); if (TreeUtils.isStringConcatenation(tree)) { AnnotatedTypeMirror leftType = getAnnotatedType(tree.getLeftOperand()); AnnotatedTypeMirror rightType = getAnnotatedType(tree.getRightOperand()); From 2f5d4cd101cf13c080a8b649e001a10e851a362e Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 18 Jul 2024 20:38:00 -0700 Subject: [PATCH 065/184] Added check for concatenation to SqlQuotesBottom --- .../sqlquotes/SqlQuotesAnnotatedTypeFactory.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java index 38dac7c193b..b7436996d26 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java @@ -6,6 +6,7 @@ import org.checkerframework.checker.sqlquotes.qual.SqlEvenQuotes; import org.checkerframework.checker.sqlquotes.qual.SqlOddQuotes; import org.checkerframework.checker.sqlquotes.qual.SqlQuotesUnknown; +import org.checkerframework.checker.sqlquotes.qual.SqlQuotesBottom; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.framework.type.AnnotatedTypeFactory; @@ -28,6 +29,9 @@ public class SqlQuotesAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { /** The {@code @}{@link SqlQuotesUnknown} annotation mirror. */ private final AnnotationMirror SQL_QUOTES_UNKNOWN; + /** The {@code @}{@link SqlQuotesBottom} annotation mirror. */ + private final AnnotationMirror SQL_QUOTES_BOTTOM; + /** A singleton set containing the {@code @}{@link SqlEvenQuotes} annotation mirror. */ private final AnnotationMirrorSet setOfSqlEvenQuotes; @@ -42,6 +46,8 @@ public SqlQuotesAnnotatedTypeFactory(BaseTypeChecker checker) { this.SQL_ODD_QUOTES = AnnotationBuilder.fromClass(getElementUtils(), SqlOddQuotes.class); this.SQL_QUOTES_UNKNOWN = AnnotationBuilder.fromClass(getElementUtils(), SqlQuotesUnknown.class); + this.SQL_QUOTES_BOTTOM = + AnnotationBuilder.fromClass(getElementUtils(), SqlQuotesBottom.class); this.setOfSqlEvenQuotes = AnnotationMirrorSet.singleton(SQL_EVEN_QUOTES); postInit(); } @@ -76,6 +82,14 @@ public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { return null; } + if (leftType.hasPrimaryAnnotation(SQL_QUOTES_BOTTOM)) { + type.replaceAnnotation(rightType.getPrimaryAnnotation()); + return null; + } else if (rightType.hasPrimaryAnnotation(SQL_QUOTES_BOTTOM)) { + type.replaceAnnotation(leftType.getPrimaryAnnotation()); + return null; + } + int leftParity = 0; if (leftType.hasPrimaryAnnotation(SQL_ODD_QUOTES)) { leftParity = 1; From a14831968e70b2f382e00ce355c48a7bd0a45b0b Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 18 Jul 2024 20:51:27 -0700 Subject: [PATCH 066/184] Revised documentation for SqlEvenQuotes and SqlOddQuotes --- .../checker/sqlquotes/qual/SqlEvenQuotes.java | 12 +++++++----- .../checker/sqlquotes/qual/SqlOddQuotes.java | 9 +++++---- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java index d7ef12811bd..dc0e5cf89e5 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java @@ -9,11 +9,13 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * SqlEvenQuotes: Used to denote a String that comprises part of a SQL query and contains either - * zero or an even number of unescaped single quotes – i.e., there must be either zero or an even - * number of ‘ characters in a SqlEvenQuotes String that are not preceded immediately by a \ - * character. SqlEvenQuotes Strings are syntactical and safe to be passed to query execution - * methods. + * Used to denote a String that contains either zero or an even number of unescaped + * single quotes – i.e., there must be either zero or an even number of ‘ characters + * in a SqlEvenQuotes String that are not preceded immediately by a SQL \ character. + * (Thus, written in Java, every occurrence of the single quote in a SqlEvenQuotes + * String must be preceded by a double backslash.) SqlEvenQuotes Strings are syntactical + * to be passed to query execution methods and are guaranteed to have no impact on + * whether subsequent concatenations are interpreted as SQL command code or SQL query values. * *

Common use cases include: SQL query fragments, such as “SELECT * FROM”; properly sanitized * user input; and complete SQL queries, such as “SELECT * FROM table WHERE field = ‘value’”. diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java index 26aba3b31da..d0556c080f4 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java @@ -9,10 +9,11 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * SqlOddQuotes: Used to denote a String that comprises part of a SQL query and contains an odd - * number of unescaped single quotes – i.e., there must be an odd number of ‘ characters in a - * SqlOddQuotes String that are not preceded immediately by a \ character. SqlOddQuotes Strings are - * not syntactical to be passed to query execution methods. + * Used to denote a String that contains an odd number of unescaped single quotes – i.e., there must + * be an odd number of ‘ characters in a SqlOddQuotes String that are not preceded immediately by a + * SQL \ character. (Thus, written in Java, every occurrence of the single quote in a SqlEvenQuotes + * String must be preceded by a double backslash.) SqlOddQuotes Strings are not syntactical to be + * passed to query execution methods. * *

Common use cases include: SQL query fragments to be concatenated with user input, such as * “SELECT * FROM table WHERE field = ‘”; SQL query fragments containing user input but missing an From e6212d3ea2956e71e96adeee0e2073b4c212c739 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 18 Jul 2024 23:15:10 -0700 Subject: [PATCH 067/184] spotlessApply formatting --- .../checker/sqlquotes/qual/SqlEvenQuotes.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java index dc0e5cf89e5..01feae0be35 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java @@ -9,13 +9,13 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * Used to denote a String that contains either zero or an even number of unescaped - * single quotes – i.e., there must be either zero or an even number of ‘ characters - * in a SqlEvenQuotes String that are not preceded immediately by a SQL \ character. - * (Thus, written in Java, every occurrence of the single quote in a SqlEvenQuotes - * String must be preceded by a double backslash.) SqlEvenQuotes Strings are syntactical - * to be passed to query execution methods and are guaranteed to have no impact on - * whether subsequent concatenations are interpreted as SQL command code or SQL query values. + * Used to denote a String that contains either zero or an even number of unescaped single quotes – + * i.e., there must be either zero or an even number of ‘ characters in a SqlEvenQuotes String that + * are not preceded immediately by a SQL \ character. (Thus, written in Java, every occurrence of + * the single quote in a SqlEvenQuotes String must be preceded by a double backslash.) SqlEvenQuotes + * Strings are syntactical to be passed to query execution methods and are guaranteed to have no + * impact on whether subsequent concatenations are interpreted as SQL command code or SQL query + * values. * *

Common use cases include: SQL query fragments, such as “SELECT * FROM”; properly sanitized * user input; and complete SQL queries, such as “SELECT * FROM table WHERE field = ‘value’”. From fce611eea5d9c6ae4f559239479c9969d0e33de7 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 19 Jul 2024 12:29:06 -0700 Subject: [PATCH 068/184] Code review improvements --- .../checker/sqlquotes/qual/SqlEvenQuotes.java | 11 ++++++++++- .../checker/sqlquotes/qual/SqlOddQuotes.java | 10 +++++++++- .../sqlquotes/SqlQuotesAnnotatedTypeFactory.java | 14 ++++---------- .../checker/sqlquotes/SqlQuotesChecker.java | 6 ++---- .../sqltainting/BCryptPasswordEncoder.astub | 2 -- .../checker/test/junit/SqlQuotesTest.java | 2 +- 6 files changed, 26 insertions(+), 19 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java index 85758ccb870..b130b53d86a 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java @@ -18,5 +18,14 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQuotesUnknown.class) -@QualifierForLiterals(stringPatterns = "^((([^\\\\']|\\\\.)*+'){2})*+([^\\\\']|\\\\.)*+\\\\?$") +@QualifierForLiterals( + stringPatterns = + "^" + // any number of paired quotes + + "((([^\\\\']|\\\\.)*+'){2})*+" + // no quotes + + "([^\\\\']|\\\\.)*+" + // possible final backslash + + "\\\\?" + + "$") public @interface SqlEvenQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java index 957d7eb60af..b56839fe278 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java @@ -21,5 +21,13 @@ @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQuotesUnknown.class) @QualifierForLiterals( - stringPatterns = "^(([^\\\\']|\\\\.)*+')([^\\\\']|'([^\\\\']|\\\\.)*+'|\\\\.)*+\\\\?$") + stringPatterns = + "^" + // one quote + + "(([^\\\\']|\\\\.)*+')" + // any number of paired quotes + + "([^\\\\']|'([^\\\\']|\\\\.)*+'|\\\\.)*+" + // optional final backslash + + "\\\\?" + + "$") public @interface SqlOddQuotes {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java index 24d83dab458..d51e4f41438 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java @@ -75,17 +75,11 @@ public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { return null; } - int leftParity = 0; - if (leftType.hasPrimaryAnnotation(SQL_ODD_QUOTES)) { - leftParity = 1; - } - - int rightParity = 0; - if (rightType.hasPrimaryAnnotation(SQL_ODD_QUOTES)) { - rightParity = 1; - } + int leftParity = leftType.hasPrimaryAnnotation(SQL_ODD_QUOTES) ? 1 : 0; + int rightParity = rightType.hasPrimaryAnnotation(SQL_ODD_QUOTES) ? 1 : 0; - if ((leftParity + rightParity) % 2 == 0) { + int parity = leftParity + rightParity; + if (parity == 0 || parity == 2) { type.replaceAnnotation(SQL_EVEN_QUOTES); } else { type.replaceAnnotation(SQL_ODD_QUOTES); diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java index 4dba24a5f7b..f59a69a26c3 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java @@ -2,15 +2,13 @@ import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.framework.qual.StubFiles; -import org.checkerframework.framework.source.SuppressWarningsPrefix; /** - * A type-checker plug-in for the SQL Tainting type system qualifier that finds (and verifies the - * absence of) SQL injection bugs in embedded query values. + * A type-checker plug-in for the SQL Quotes type system. It that finds (and verifies the absence + * of) SQL injection bugs. * *

It verifies that only SQL-safe embedded query values are trusted and that user input is * sanitized before use. */ -@SuppressWarningsPrefix({"sqlquerysanitized", "sqlquotes"}) @StubFiles({"BCryptPasswordEncoder.astub", "Statement.astub"}) public class SqlQuotesChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/BCryptPasswordEncoder.astub b/checker/src/main/java/org/checkerframework/checker/sqltainting/BCryptPasswordEncoder.astub index 23e336a95ee..a55c8eb2ef9 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqltainting/BCryptPasswordEncoder.astub +++ b/checker/src/main/java/org/checkerframework/checker/sqltainting/BCryptPasswordEncoder.astub @@ -3,8 +3,6 @@ package org.springframework.security.crypto.bcrypt; import java.security.SecureRandom; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.springframework.security.crypto.password.PasswordEncoder; import org.checkerframework.checker.sqltainting.qual.SqlSanitized; diff --git a/checker/src/test/java/org/checkerframework/checker/test/junit/SqlQuotesTest.java b/checker/src/test/java/org/checkerframework/checker/test/junit/SqlQuotesTest.java index 6c966841b37..189ea274043 100644 --- a/checker/src/test/java/org/checkerframework/checker/test/junit/SqlQuotesTest.java +++ b/checker/src/test/java/org/checkerframework/checker/test/junit/SqlQuotesTest.java @@ -9,7 +9,7 @@ public class SqlQuotesTest extends CheckerFrameworkPerDirectoryTest { /** - * Create a TaintingTest. + * Create a SqlQuotesTest. * * @param testFiles the files containing test code, which will be type-checked */ From d4efe191f9c3a94534f6f6089a7a09abab32c3a1 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 21 Jul 2024 15:21:36 -0700 Subject: [PATCH 069/184] Added Javadoc --- .../sqlquotes/SqlQuotesAnnotatedTypeFactory.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java index 901fedf6f5e..0bcad638976 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java @@ -63,6 +63,17 @@ public TreeAnnotator createTreeAnnotator() { new SqlQuotesAnnotatedTypeFactory.SqlQuotesTreeAnnotator(this)); } + /** + * A TreeAnnotator to enforce SqlQuotes String concatenation rules: + * + *

+ */ private class SqlQuotesTreeAnnotator extends TreeAnnotator { public SqlQuotesTreeAnnotator(AnnotatedTypeFactory atypeFactory) { super(atypeFactory); @@ -99,7 +110,8 @@ public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { rightParity = 1; } - if ((leftParity + rightParity) % 2 == 0) { + int parity = leftParity + rightParity; + if (parity == 0 || parity == 2) { type.replaceAnnotation(SQL_EVEN_QUOTES); } else { type.replaceAnnotation(SQL_ODD_QUOTES); From 3ab582ee7a63f4fb4a7c6f9075fd9c1d06d739fc Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 21 Jul 2024 15:41:51 -0700 Subject: [PATCH 070/184] Removed sqltainting --- .../sqltainting/qual/PolySqlQueryValue.java | 19 -------- .../sqltainting/qual/SqlSanitized.java | 27 ----------- .../sqltainting/qual/SqlUnsanitized.java | 22 --------- .../sqltainting/BCryptPasswordEncoder.astub | 12 ----- .../SqlTaintingAnnotatedTypeFactory.java | 36 -------------- .../sqltainting/SqlTaintingChecker.java | 14 ------ .../sqltainting/SqlTaintingVisitor.java | 28 ----------- .../checker/sqltainting/Statement.astub | 9 ---- .../checker/test/junit/SqltaintingTest.java | 24 ---------- .../sqltainting/SimpleSqlQueryValue.java | 48 ------------------- .../tests/sqltainting/SqlSanitizedRegex.java | 43 ----------------- 11 files changed, 282 deletions(-) delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlQueryValue.java delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSanitized.java delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlUnsanitized.java delete mode 100644 checker/src/main/java/org/checkerframework/checker/sqltainting/BCryptPasswordEncoder.astub delete mode 100644 checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java delete mode 100644 checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java delete mode 100644 checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingVisitor.java delete mode 100644 checker/src/main/java/org/checkerframework/checker/sqltainting/Statement.astub delete mode 100644 checker/src/test/java/org/checkerframework/checker/test/junit/SqltaintingTest.java delete mode 100644 checker/tests/sqltainting/SimpleSqlQueryValue.java delete mode 100644 checker/tests/sqltainting/SqlSanitizedRegex.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlQueryValue.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlQueryValue.java deleted file mode 100644 index 9071a50778b..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/PolySqlQueryValue.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.checkerframework.checker.sqltainting.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.PolymorphicQualifier; - -/** - * A polymorphic qualifier for the SQL Value Tainting type system. - * - * @checker_framework.manual #qualifier-polymorphism Qualifier polymorphism - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@PolymorphicQualifier(SqlUnsanitized.class) -public @interface PolySqlQueryValue {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSanitized.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSanitized.java deleted file mode 100644 index e63f3ea3f05..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlSanitized.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.checkerframework.checker.sqltainting.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultFor; -import org.checkerframework.framework.qual.QualifierForLiterals; -import org.checkerframework.framework.qual.SubtypeOf; -import org.checkerframework.framework.qual.TypeUseLocation; - -/** - * Denotes a value to be used in a SQL query that has been sanitized (i.e. non-alphanumeric - * characters escaped as necessary) and is thus safe to be embedded as a value in a SQL query. - * - *

All empty Strings and String literals consisting solely of alphanumeric characters, - * whitespace, and backslash-escaped sensitive characters (i.e. single/double quotes, backslashes, - * hyphens, percent signs, underscores) are annotated SQLSanitized automatically. - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(SqlUnsanitized.class) -@QualifierForLiterals(stringPatterns = "^(\\w|\\s|(\\\\[-'\"\\\\%_])*)*$") -@DefaultFor(TypeUseLocation.LOWER_BOUND) -public @interface SqlSanitized {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlUnsanitized.java b/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlUnsanitized.java deleted file mode 100644 index f446c06baa5..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqltainting/qual/SqlUnsanitized.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.checkerframework.checker.sqltainting.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; -import org.checkerframework.framework.qual.SubtypeOf; - -/** - * Denotes a value to be used as part of a SQL query. Might be safe for SQL query use or might be - * dangerous. - * - * @see SqlSanitized - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf({}) -@DefaultQualifierInHierarchy -public @interface SqlUnsanitized {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/BCryptPasswordEncoder.astub b/checker/src/main/java/org/checkerframework/checker/sqltainting/BCryptPasswordEncoder.astub deleted file mode 100644 index a55c8eb2ef9..00000000000 --- a/checker/src/main/java/org/checkerframework/checker/sqltainting/BCryptPasswordEncoder.astub +++ /dev/null @@ -1,12 +0,0 @@ -package org.springframework.security.crypto.bcrypt; - -import java.security.SecureRandom; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.springframework.security.crypto.password.PasswordEncoder; - -import org.checkerframework.checker.sqltainting.qual.SqlSanitized; - -public class BCryptPasswordEncoder implements PasswordEncoder { - @SqlSanitized String encode(CharSequence rawPassword); -} diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java deleted file mode 100644 index a26fc7c1874..00000000000 --- a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingAnnotatedTypeFactory.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.checkerframework.checker.sqltainting; - -import java.util.Set; -import javax.lang.model.element.AnnotationMirror; -import org.checkerframework.checker.sqltainting.qual.SqlSanitized; -import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; -import org.checkerframework.common.basetype.BaseTypeChecker; -import org.checkerframework.javacutil.AnnotationBuilder; -import org.checkerframework.javacutil.AnnotationMirrorSet; - -/** Annotated type factory for the SQL Tainting Checker. */ -public class SqlTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { - - /** The {@code @}{@link SqlSanitized} annotation mirror. */ - private final AnnotationMirror SQLSANITIZED; - - /** A singleton set containing the {@code @}{@link SqlSanitized} annotation mirror. */ - private final AnnotationMirrorSet setOfSqlSanitized; - - /** - * Creates a {@link SqlTaintingAnnotatedTypeFactory}. - * - * @param checker the SQL tainting checker - */ - public SqlTaintingAnnotatedTypeFactory(BaseTypeChecker checker) { - super(checker); - this.SQLSANITIZED = AnnotationBuilder.fromClass(getElementUtils(), SqlSanitized.class); - this.setOfSqlSanitized = AnnotationMirrorSet.singleton(SQLSANITIZED); - postInit(); - } - - @Override - protected Set getEnumConstructorQualifiers() { - return setOfSqlSanitized; - } -} diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java deleted file mode 100644 index e9480d35473..00000000000 --- a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingChecker.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.checkerframework.checker.sqltainting; - -import org.checkerframework.common.basetype.BaseTypeChecker; -import org.checkerframework.framework.source.SuppressWarningsPrefix; - -/** - * A type-checker plug-in for the SQL Tainting type system qualifier that finds (and verifies the - * absence of) SQL injection bugs in embedded query values. - * - *

It verifies that only SQL-safe embedded query values are trusted and that user input is - * sanitized before use. - */ -@SuppressWarningsPrefix({"sqlsanitized", "sqltainting"}) -public class SqlTaintingChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingVisitor.java b/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingVisitor.java deleted file mode 100644 index 8502d9be71a..00000000000 --- a/checker/src/main/java/org/checkerframework/checker/sqltainting/SqlTaintingVisitor.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.checkerframework.checker.sqltainting; - -import javax.lang.model.element.ExecutableElement; -import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; -import org.checkerframework.common.basetype.BaseTypeChecker; -import org.checkerframework.common.basetype.BaseTypeVisitor; -import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType; - -/** Visitor for the {@link SqlTaintingChecker}. */ -public class SqlTaintingVisitor extends BaseTypeVisitor { - - /** - * Creates a {@link SqlTaintingVisitor}. - * - * @param checker the checker that uses this visitor - */ - public SqlTaintingVisitor(BaseTypeChecker checker) { - super(checker); - } - - /** - * Don't check that the constructor result is top. Checking that the super() or this() call is a - * subtype of the constructor result is sufficient. - */ - @Override - protected void checkConstructorResult( - AnnotatedExecutableType constructorType, ExecutableElement constructorElement) {} -} diff --git a/checker/src/main/java/org/checkerframework/checker/sqltainting/Statement.astub b/checker/src/main/java/org/checkerframework/checker/sqltainting/Statement.astub deleted file mode 100644 index 3f12141abaa..00000000000 --- a/checker/src/main/java/org/checkerframework/checker/sqltainting/Statement.astub +++ /dev/null @@ -1,9 +0,0 @@ -package java.sql; - -import java.util.regex.Pattern; - -import org.checkerframework.checker.sqltainting.qual.SqlSanitized; - -public interface Statement extends Wrapper, AutoCloseable { - ResultSet executeQuery(@SqlSanitized String var1) throws SQLException; -} diff --git a/checker/src/test/java/org/checkerframework/checker/test/junit/SqltaintingTest.java b/checker/src/test/java/org/checkerframework/checker/test/junit/SqltaintingTest.java deleted file mode 100644 index c84c7345f4c..00000000000 --- a/checker/src/test/java/org/checkerframework/checker/test/junit/SqltaintingTest.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.checkerframework.checker.test.junit; - -import java.io.File; -import java.util.List; -import org.checkerframework.checker.sqltainting.SqlTaintingChecker; -import org.checkerframework.framework.test.CheckerFrameworkPerDirectoryTest; -import org.junit.runners.Parameterized.Parameters; - -public class SqltaintingTest extends CheckerFrameworkPerDirectoryTest { - - /** - * Create a TaintingTest. - * - * @param testFiles the files containing test code, which will be type-checked - */ - public SqltaintingTest(List testFiles) { - super(testFiles, SqlTaintingChecker.class, "sqltainting"); - } - - @Parameters - public static String[] getTestDirs() { - return new String[] {"sqltainting", "all-systems"}; - } -} diff --git a/checker/tests/sqltainting/SimpleSqlQueryValue.java b/checker/tests/sqltainting/SimpleSqlQueryValue.java deleted file mode 100644 index 4302a57e28a..00000000000 --- a/checker/tests/sqltainting/SimpleSqlQueryValue.java +++ /dev/null @@ -1,48 +0,0 @@ -import org.checkerframework.checker.sqltainting.qual.SqlSanitized; - -public class SimpleSqlQueryValue { - - void execute(@SqlSanitized String s) {} - - void unsanitized(String s) {} - - void stringLiteral() { - execute("ldskjfldj"); - unsanitized("lksjdflkjdf"); - } - - void stringRef(String ref) { - // :: error: (argument) - execute(ref); // error - - unsanitized(ref); - } - - void safeRef(@SqlSanitized String ref) { - execute(ref); - unsanitized(ref); - } - - void concatenation(@SqlSanitized String s1, String s2) { - execute(s1 + s1); - execute(s1 += s1); - execute(s1 + "m"); - // :: error: (argument) - execute(s1 + s2); // error - - // :: error: (argument) - execute(s2 + s1); // error - // :: error: (argument) - execute(s2 + "m"); // error - // :: error: (argument) - execute(s2 + s2); // error - - unsanitized(s1 + s1); - unsanitized(s1 + "m"); - unsanitized(s1 + s2); - - unsanitized(s2 + s1); - unsanitized(s2 + "m"); - unsanitized(s2 + s2); - } -} diff --git a/checker/tests/sqltainting/SqlSanitizedRegex.java b/checker/tests/sqltainting/SqlSanitizedRegex.java deleted file mode 100644 index 0781c11f743..00000000000 --- a/checker/tests/sqltainting/SqlSanitizedRegex.java +++ /dev/null @@ -1,43 +0,0 @@ -import org.checkerframework.checker.sqltainting.qual.SqlSanitized; - -public class SqlSanitizedRegex { - - void execute(@SqlSanitized String s) {} - - void emptyString() { - execute(""); - execute(" "); - } - - void alphanumericLiteral() { - execute("0923uoiwej093NSDF9IJdjfs09"); - execute("8YUGKthbJU8yIUou8y7TYg"); - execute("09 23 uoiwej093N SDF9IJdjfs 09"); - execute("8 YUGKthbJU8y IUou 8 y7TYg"); - } - - void escapedLiterals() { - execute("escaped \\\\ \\\\ backslashes"); - execute("escaped \\' \\\" quotes"); - execute("escaped \\- \\- hyphens"); - execute("escaped \\% \\% percents"); - execute("escaped \\_ \\_ underscores"); - - execute("3 escaped \\'\\_\\% characters"); - execute("3 escaped \\\\\\-\\-\\\" characters"); - } - - void unescapedLiterals() { - // :: error: (argument) - execute("unescaped \\' \\\" \" _ \\\\ characters"); // error - // :: error: (argument) - execute("unescaped -- ' \\\\ characters"); // error - } - - void otherChars() { - // :: error: (argument) - execute("109jnsdf;"); // error - // :: error: (argument) - execute("@293081$^&"); // error - } -} From ec579849ed033c9831623fb31926cfdfc6db485b Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 21 Jul 2024 16:07:58 -0700 Subject: [PATCH 071/184] Added Javadoc on constructor --- .../checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java index 0bcad638976..1bc12fda13d 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java @@ -75,6 +75,11 @@ public TreeAnnotator createTreeAnnotator() { * */ private class SqlQuotesTreeAnnotator extends TreeAnnotator { + /** + * Creates a {@link SqlQuotesTreeAnnotator} + * + * @param atypeFactory the annotated type factory + */ public SqlQuotesTreeAnnotator(AnnotatedTypeFactory atypeFactory) { super(atypeFactory); } From b44b5954e002b652aced79d0b3d0f863b582b8fc Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Wed, 24 Jul 2024 00:54:31 -0700 Subject: [PATCH 072/184] Revised SqlEvenQuotes, SqlOddQuotes, and SqlQuotesUnknown docs for clarity --- .../checker/sqlquotes/qual/SqlEvenQuotes.java | 10 +++++----- .../checker/sqlquotes/qual/SqlOddQuotes.java | 6 +++--- .../checker/sqlquotes/qual/SqlQuotesUnknown.java | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java index f6a6d2f737c..be9c724471f 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java @@ -11,11 +11,11 @@ /** * Used to denote a String that contains either zero or an even number of unescaped single quotes – * i.e., there must be either zero or an even number of ‘ characters in a SqlEvenQuotes String that - * are not preceded immediately by a SQL \ character. (Thus, written in Java, every occurrence of - * the single quote in a SqlEvenQuotes String must be preceded by a double backslash.) SqlEvenQuotes - * Strings are syntactical to be passed to query execution methods and are guaranteed to have no - * impact on whether subsequent concatenations are interpreted as SQL command code or SQL query - * values. + * are not preceded immediately by a SQL \ character. (Thus, when written in Java, a SqlEvenQuotes + * String contains an even number of single quotes that are not preceded by a double backslash.) + * SqlEvenQuotes Strings are syntactical to be passed to query execution methods and are guaranteed + * to have no impact on whether subsequent concatenations are interpreted as SQL command code or as + * SQL query values. * *

Common use cases include: SQL query fragments, such as “SELECT * FROM”; properly sanitized * user input; and complete SQL queries, such as “SELECT * FROM table WHERE field = ‘value’”. diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java index b4668f28c9a..25c7ebd3360 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java @@ -11,9 +11,9 @@ /** * Used to denote a String that contains an odd number of unescaped single quotes – i.e., there must * be an odd number of ‘ characters in a SqlOddQuotes String that are not preceded immediately by a - * SQL \ character. (Thus, written in Java, every occurrence of the single quote in a SqlEvenQuotes - * String must be preceded by a double backslash.) SqlOddQuotes Strings are not syntactical to be - * passed to query execution methods. + * SQL \ character. (Thus, when written in Java, a SqlOddQuotes String contains an odd number of + * single quotes that are not preceded by a double backslash.) SqlOddQuotes Strings are not + * syntactical to be passed to query execution methods. * *

Common use cases include: SQL query fragments to be concatenated with user input, such as * “SELECT * FROM table WHERE field = ‘”; SQL query fragments containing user input but missing an diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java index 3dbfce7ada1..6ff03019b2a 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java @@ -9,9 +9,9 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * Represents the top of the SQL Quotes qualifier hierarchy. Used to denote a String that comprises - * part of a SQL query, the quoting of which is unknown. SqlQuotesUnknown Strings are SQL injection - * vulnerabilities and thus unsafe to be passed to query execution methods. + * Represents the top of the SQL Quotes qualifier hierarchy. Used to denote a String of which the + * quoting is unknown. SqlQuotesUnknown Strings are SQL injection vulnerabilities and thus unsafe + * to be passed to query execution methods. * *

Common use cases include unsanitized user input. */ From 8180db57a9e52670cfb7b24a884bbe03c222f9f3 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 25 Jul 2024 01:02:59 -0700 Subject: [PATCH 073/184] Revised SqlEvenQuotes, SqlOddQuotes regex to match ANSI standard for single quote escape --- .../checker/sqlquotes/qual/SqlEvenQuotes.java | 11 +---------- .../checker/sqlquotes/qual/SqlOddQuotes.java | 11 +---------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java index be9c724471f..07d4931f98f 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java @@ -24,14 +24,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQuotesUnknown.class) -@QualifierForLiterals( - stringPatterns = - "^" - // any number of paired quotes - + "((([^\\\\']|\\\\.)*+'){2})*+" - // no quotes - + "([^\\\\']|\\\\.)*+" - // possible final backslash - + "\\\\?" - + "$") +@QualifierForLiterals(stringPatterns = "^([^']*('[^']*'[^']*)*)$") public @interface SqlEvenQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java index 25c7ebd3360..4660deae55a 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java @@ -25,14 +25,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQuotesUnknown.class) -@QualifierForLiterals( - stringPatterns = - "^" - // one quote - + "(([^\\\\']|\\\\.)*+')" - // any number of paired quotes - + "([^\\\\']|'([^\\\\']|\\\\.)*+'|\\\\.)*+" - // optional final backslash - + "\\\\?" - + "$") +@QualifierForLiterals(stringPatterns = "^[^']*('[^']*'[^']*)*'[^']*$") public @interface SqlOddQuotes {} From 0cb570d16d4578120a01fc0d40053c2f9c66f79c Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 25 Jul 2024 01:09:27 -0700 Subject: [PATCH 074/184] Revised SqlEvenQuotes, SqlOddQuotes docs to match new regex --- .../checker/sqlquotes/qual/SqlEvenQuotes.java | 4 ++-- .../checker/sqlquotes/qual/SqlOddQuotes.java | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java index 07d4931f98f..dbfc98c3934 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java @@ -11,8 +11,8 @@ /** * Used to denote a String that contains either zero or an even number of unescaped single quotes – * i.e., there must be either zero or an even number of ‘ characters in a SqlEvenQuotes String that - * are not preceded immediately by a SQL \ character. (Thus, when written in Java, a SqlEvenQuotes - * String contains an even number of single quotes that are not preceded by a double backslash.) + * are not preceded immediately by another ' character. (Thus, all SqlEvenQuotes Strings ultimately + * contain an even number of ' characters, escaped or otherwise.) * SqlEvenQuotes Strings are syntactical to be passed to query execution methods and are guaranteed * to have no impact on whether subsequent concatenations are interpreted as SQL command code or as * SQL query values. diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java index 4660deae55a..483e1d52621 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java @@ -10,10 +10,10 @@ /** * Used to denote a String that contains an odd number of unescaped single quotes – i.e., there must - * be an odd number of ‘ characters in a SqlOddQuotes String that are not preceded immediately by a - * SQL \ character. (Thus, when written in Java, a SqlOddQuotes String contains an odd number of - * single quotes that are not preceded by a double backslash.) SqlOddQuotes Strings are not - * syntactical to be passed to query execution methods. + * be an odd number of ‘ characters in a SqlOddQuotes String that are not preceded immediately by + * another ' character. (Thus, all SqlOddQuotes Strings ultimately contain an odd number of single + * quotes, escaped or otherwise.) SqlOddQuotes Strings are not syntactical to be passed to query + * execution methods. * *

Common use cases include: SQL query fragments to be concatenated with user input, such as * “SELECT * FROM table WHERE field = ‘”; SQL query fragments containing user input but missing an From 839903230b62ed1dbcaf11b007dde7d32b741bd0 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 25 Jul 2024 01:12:23 -0700 Subject: [PATCH 075/184] Revised SqlQuotesRegex tests to match new regex --- checker/tests/sqlquotes/SqlQuotesRegex.java | 28 ++------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/checker/tests/sqlquotes/SqlQuotesRegex.java b/checker/tests/sqlquotes/SqlQuotesRegex.java index 72a46bd26f2..c9263f81512 100644 --- a/checker/tests/sqlquotes/SqlQuotesRegex.java +++ b/checker/tests/sqlquotes/SqlQuotesRegex.java @@ -3,7 +3,7 @@ public class SqlQuotesRegex { - void oddNoEscaped() { + void oddQuotes() { // :: error: (assignment) @SqlOddQuotes String none = "asdf"; @SqlOddQuotes String one = "asdf'asdf"; @@ -15,19 +15,7 @@ void oddNoEscaped() { @SqlOddQuotes String manyOdd = "''asdf'asdf'''asdf'asdf''"; } - void oddWithBackslashes() { - // :: error: (assignment) - @SqlOddQuotes String none = "asdf\\'"; - @SqlOddQuotes String one = "asdf\\''asdf"; - // :: error: (assignment) - @SqlOddQuotes String two = "'a\\'sdf'"; - @SqlOddQuotes String three = "\\''asdf'\\asdf'"; - // :: error: (assignment) - @SqlOddQuotes String manyEven = "'as\\'df'\\''a\\sdf'asdf'as\\'\\'df'\\'''"; - @SqlOddQuotes String manyOdd = "'\\''a\\sdf'asdf'''as\\df'as\\'df''\\'"; - } - - void evenNoEscaped() { + void evenQuotes() { @SqlEvenQuotes String none = ""; // :: error: (assignment) @SqlEvenQuotes String one = "'asdf"; @@ -38,16 +26,4 @@ void evenNoEscaped() { // :: error: (assignment) @SqlEvenQuotes String manyOdd = "asdf''''asdf'asdf'asdf'asdf"; } - - void evenWithBackslashes() { - @SqlEvenQuotes String none = "\\'\\'\\'"; - // :: error: (assignment) - @SqlEvenQuotes String one = "'asdf\\'"; - @SqlEvenQuotes String two = "'\\''a\\sdf"; - // :: error: (assignment) - @SqlEvenQuotes String three = "asd\\'f'asdf''"; - @SqlEvenQuotes String manyEven = "\\'''asdf''asd\\f'\\asdf'\\''asdf'asdf\\'"; - // :: error: (assignment) - @SqlEvenQuotes String manyOdd = "asdf''\\'''\\asdf'asdf'a\\'sdf'\\'asdf"; - } } From 00e624e3d59a0da7a1f0e5b304b906b9ade692a8 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 25 Jul 2024 01:13:23 -0700 Subject: [PATCH 076/184] Revised SqlQuotesConcat tests to match new regex --- checker/tests/sqlquotes/SqlQuotesConcat.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/checker/tests/sqlquotes/SqlQuotesConcat.java b/checker/tests/sqlquotes/SqlQuotesConcat.java index b2ef3deaab5..c4528041c1f 100644 --- a/checker/tests/sqlquotes/SqlQuotesConcat.java +++ b/checker/tests/sqlquotes/SqlQuotesConcat.java @@ -4,7 +4,7 @@ public class SqlQuotesConcat { void oddOddConcat() { - @SqlOddQuotes String odd1 = "asd\\'f'asdf''\\"; + @SqlOddQuotes String odd1 = "asd''f'asdf'''"; @SqlOddQuotes String odd2 = "''asdf''''asdf'asdf'asdf'asdf"; // :: error: (assignment) @SqlOddQuotes String oddResult1 = odd1 + odd2; @@ -18,8 +18,8 @@ void oddOddConcat() { } void oddEvenConcat() { - @SqlOddQuotes String odd1 = "asd\\'f'asdf''\\"; - @SqlEvenQuotes String even1 = "'\\''a\\sdf"; + @SqlOddQuotes String odd1 = "asd''f'asdf'''"; + @SqlEvenQuotes String even1 = "''''a'sdf"; // :: error: (assignment) @SqlEvenQuotes String evenResult1 = odd1 + even1; @SqlOddQuotes String oddResult1 = odd1 + even1; @@ -32,8 +32,8 @@ void oddEvenConcat() { } void evenOddConcat() { - @SqlOddQuotes String odd1 = "asd\\'f'asdf''\\"; - @SqlEvenQuotes String even1 = "'\\''a\\sdf"; + @SqlOddQuotes String odd1 = "asd''f'asdf'''"; + @SqlEvenQuotes String even1 = "''''a'sdf"; // :: error: (assignment) @SqlEvenQuotes String evenResult1 = even1 + odd1; @SqlOddQuotes String oddResult1 = even1 + odd1; @@ -46,13 +46,13 @@ void evenOddConcat() { } void evenEvenConcat() { - @SqlEvenQuotes String even1 = "\\'''asdf''asd\\f'\\asdf'\\''asdf'asdf\\'"; + @SqlEvenQuotes String even1 = "''''asdf''asd'f''asdf''''asdf'asdf''"; @SqlEvenQuotes String even2 = "''asdf"; // :: error: (assignment) @SqlOddQuotes String oddResult1 = even1 + even2; @SqlEvenQuotes String evenResult1 = even1 + even2; - @SqlEvenQuotes String even3 = "'a\\'sdf'"; + @SqlEvenQuotes String even3 = "'a''sdf'"; @SqlEvenQuotes String even4 = "'asdf''asdf'asdf'asdf'''"; // :: error: (assignment) @SqlOddQuotes String oddResult2 = even3 + even4; @@ -72,7 +72,7 @@ void withTopConcat(@SqlQuotesUnknown String top) { @SqlEvenQuotes String evenResult2 = top + odd1; String topResult2 = top + odd1; - @SqlEvenQuotes String even1 = "'a\\'sdf'"; + @SqlEvenQuotes String even1 = "'a''sdf'"; // :: error: (assignment) @SqlOddQuotes String oddResult3 = even1 + top; // :: error: (assignment) From bf373f7c39b531fe4d17584dbdf5291bc645cdd0 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 25 Jul 2024 01:36:17 -0700 Subject: [PATCH 077/184] Fixed quoting typos in SqlQuotesConcat --- checker/tests/sqlquotes/SqlQuotesConcat.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/checker/tests/sqlquotes/SqlQuotesConcat.java b/checker/tests/sqlquotes/SqlQuotesConcat.java index c4528041c1f..fb21ea431aa 100644 --- a/checker/tests/sqlquotes/SqlQuotesConcat.java +++ b/checker/tests/sqlquotes/SqlQuotesConcat.java @@ -4,7 +4,7 @@ public class SqlQuotesConcat { void oddOddConcat() { - @SqlOddQuotes String odd1 = "asd''f'asdf'''"; + @SqlOddQuotes String odd1 = "asd''f'asdf''"; @SqlOddQuotes String odd2 = "''asdf''''asdf'asdf'asdf'asdf"; // :: error: (assignment) @SqlOddQuotes String oddResult1 = odd1 + odd2; @@ -18,8 +18,8 @@ void oddOddConcat() { } void oddEvenConcat() { - @SqlOddQuotes String odd1 = "asd''f'asdf'''"; - @SqlEvenQuotes String even1 = "''''a'sdf"; + @SqlOddQuotes String odd1 = "asd''f'asdf''"; + @SqlEvenQuotes String even1 = "'''a'sdf"; // :: error: (assignment) @SqlEvenQuotes String evenResult1 = odd1 + even1; @SqlOddQuotes String oddResult1 = odd1 + even1; @@ -32,8 +32,8 @@ void oddEvenConcat() { } void evenOddConcat() { - @SqlOddQuotes String odd1 = "asd''f'asdf'''"; - @SqlEvenQuotes String even1 = "''''a'sdf"; + @SqlOddQuotes String odd1 = "asd''f'asdf''"; + @SqlEvenQuotes String even1 = "'''a'sdf"; // :: error: (assignment) @SqlEvenQuotes String evenResult1 = even1 + odd1; @SqlOddQuotes String oddResult1 = even1 + odd1; From 1a35b7e4be9d8e877d107185b374c06429ac5910 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 25 Jul 2024 01:36:37 -0700 Subject: [PATCH 078/184] Ran spotlessApply --- .../checker/sqlquotes/qual/SqlEvenQuotes.java | 7 +++---- .../checker/sqlquotes/qual/SqlQuotesUnknown.java | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java index dbfc98c3934..0105fc81497 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java @@ -12,10 +12,9 @@ * Used to denote a String that contains either zero or an even number of unescaped single quotes – * i.e., there must be either zero or an even number of ‘ characters in a SqlEvenQuotes String that * are not preceded immediately by another ' character. (Thus, all SqlEvenQuotes Strings ultimately - * contain an even number of ' characters, escaped or otherwise.) - * SqlEvenQuotes Strings are syntactical to be passed to query execution methods and are guaranteed - * to have no impact on whether subsequent concatenations are interpreted as SQL command code or as - * SQL query values. + * contain an even number of ' characters, escaped or otherwise.) SqlEvenQuotes Strings are + * syntactical to be passed to query execution methods and are guaranteed to have no impact on + * whether subsequent concatenations are interpreted as SQL command code or as SQL query values. * *

Common use cases include: SQL query fragments, such as “SELECT * FROM”; properly sanitized * user input; and complete SQL queries, such as “SELECT * FROM table WHERE field = ‘value’”. diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java index 6ff03019b2a..c762fa289ad 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java @@ -10,8 +10,8 @@ /** * Represents the top of the SQL Quotes qualifier hierarchy. Used to denote a String of which the - * quoting is unknown. SqlQuotesUnknown Strings are SQL injection vulnerabilities and thus unsafe - * to be passed to query execution methods. + * quoting is unknown. SqlQuotesUnknown Strings are SQL injection vulnerabilities and thus unsafe to + * be passed to query execution methods. * *

Common use cases include unsanitized user input. */ From 399903dadebda26de40d958efc2339545fc0fe2d Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 25 Jul 2024 14:54:36 -0700 Subject: [PATCH 079/184] Added references to checker manual --- .../checker/sqlquotes/qual/SqlEvenQuotes.java | 2 ++ .../checker/sqlquotes/qual/SqlOddQuotes.java | 2 ++ .../checker/sqlquotes/qual/SqlQuotesBottom.java | 7 ++++++- .../checker/sqlquotes/qual/SqlQuotesUnknown.java | 2 ++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java index 0105fc81497..35be478110b 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java @@ -18,6 +18,8 @@ * *

Common use cases include: SQL query fragments, such as “SELECT * FROM”; properly sanitized * user input; and complete SQL queries, such as “SELECT * FROM table WHERE field = ‘value’”. + * + * @checker_framework.manual #sql-quotes-checker SQL Quotes Checker */ @Documented @Retention(RetentionPolicy.RUNTIME) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java index 483e1d52621..aa99396473f 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java @@ -20,6 +20,8 @@ * ending single quote, such as “SELECT * FROM table WHERE field = ‘value”; connecting punctuation, * such as “’, “; and any combinations of the above with paired-off single quotes, such as “SELECT * * FROM table WHERE field1 = ‘value1’, field2 = ‘value2’, field3 = ‘”. + * + * @checker_framework.manual #sql-quotes-checker SQL Quotes Checker */ @Documented @Retention(RetentionPolicy.RUNTIME) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java index 98c45985156..41acaca1641 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesBottom.java @@ -11,7 +11,12 @@ import org.checkerframework.framework.qual.TargetLocations; import org.checkerframework.framework.qual.TypeUseLocation; -/** Represents the bottom of the SQL Quotes qualifier hierarchy. */ +/** + * Represents the bottom of the SQL Quotes qualifier hierarchy. + * + * @checker_framework.manual #sql-quotes-checker SQL Quotes Checker + * @checker_framework.manual #bottom-type the bottom type + */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java index c762fa289ad..9959e9b4916 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java @@ -14,6 +14,8 @@ * be passed to query execution methods. * *

Common use cases include unsanitized user input. + * + * @checker_framework.manual #sql-quotes-checker SQL Quotes Checker */ @Documented @Retention(RetentionPolicy.RUNTIME) From f9a3d528d599b21197c0ed3ab7a5b1e666fe5ba5 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 25 Jul 2024 14:55:22 -0700 Subject: [PATCH 080/184] Added SQL Quotes chapter --- docs/manual/figures/sql-quotes.svg | 325 +++++++++++++++++++++++++++++ docs/manual/sql-quotes-checker.tex | 89 ++++++++ 2 files changed, 414 insertions(+) create mode 100644 docs/manual/figures/sql-quotes.svg create mode 100644 docs/manual/sql-quotes-checker.tex diff --git a/docs/manual/figures/sql-quotes.svg b/docs/manual/figures/sql-quotes.svg new file mode 100644 index 00000000000..9612dd2b2b7 --- /dev/null +++ b/docs/manual/figures/sql-quotes.svg @@ -0,0 +1,325 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + @SqlEvenQuotes + + @SqlOddQuotes + + + + + @SqlQuotesUnknown + + + + + @SqlQuotesBottom + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/manual/sql-quotes-checker.tex b/docs/manual/sql-quotes-checker.tex new file mode 100644 index 00000000000..4e369af75b7 --- /dev/null +++ b/docs/manual/sql-quotes-checker.tex @@ -0,0 +1,89 @@ +\htmlhr +\chapterAndLabel{SQL Quotes Checker}{sql-quotes-checker} + +The SQL Quotes Checker helps prevent SQL injection vulnerabilities. Many +\href{https://en.wikipedia.org/wiki/Sql_injection}{SQL injection} attacks +involve malicious user input containing unescaped special characters such as the +single quote, which can change whether subsequent concatenations are interpreted +as SQL command code or as SQL query values. (Some databases support the use of the +backslash as an escape character for single quotes. However, ANSI standard determines +that single quotes in SQL queries should be escaped by \emph{doubling-up}: +immediately preceding or following it with another single quote. The SQL Quotes Checker +follows ANSI standard and considers doubled-up single quotes as one escaped single quote.) + +Consequently, the checker qualifies String literals by the parity of unescaped single +quotes present. Furthermore, it marks user-supplied Strings as unsafe for SQL query +use, as their quoting is unknown; the program must \emph{sanitize} all such values +before concatenating them to a SQL query for execution. Sanitization can be done by +parsing and quoting user input as necessary to ensure special characters are properly +escaped. The SQL Quotes Checker guarantees that no unchecked values are passed to a +SQL query execution statement. It is \emph{unable} to guarantee that hard-coded SQL +queries written by the code author are safe for execution; e.g., the checker will not +warn at compile time about improper uses of \code{DELETE} or \code{DROP} statements. + +It should be noted that using SQL parameters rather than direct concatenation of +SQL query values onto SQL commands mitigates the danger of SQL injection attacks, +as parameterized values are, by design, unable to be misinterpreted as part of a SQL +command. Developers should strive to use parameterized queries when possible; the +SQL Quotes Checker is at its most applicable when retrospectively securing existing +programs involving user input concatenation. + +To run the SQL Quotes Checker, supply the +\code{-processor SqlQuotesChecker} +or +\code{-processor org.checkerframework.checker.sqlquotes.SqlQuotesChecker} +command-line option to javac. +% for examples + +\sectionAndLabel{SQL quotes annotations}{sql-quotes-annotations} + +The SQL Quotes type system uses the following annotations: + +\begin{description} +\item[\refqualclass{checker/sqlquotes/qual}{SqlEvenQuotes}] + indicates a String literal that contains zero or an even number of + single quotes. +\item[\refqualclass{checker/sqlquotes/qual}{SqlOddQuotes}] + indicates a String literal that contains an odd number of single + quotes. +\item[\refqualclass{checker/sqlquotes/qual}{SqlQuotesUnknown}] + indicates a String whose quoting is unknown. + \code{@SqlQuotesUnknown} is a supertype of \code{@SqlEvenQuotes} + and \code{@SqlOddQuotes}. It is the default qualifier for non-literal + Strings. +\end{description} + +The subtyping hierarchy of the SQL Quotes Checker's qualifiers is shown in +Figure~\ref{fig-sql-quotes-hierarchy}. + +\begin{figure} +\includeimage{sql-quotes}{5.5cm} +\caption{The subtyping relationship of the SQL Quotes Checker's qualifiers. + The type qualifiers are applicable to Strings. Qualifiers in gray are + used internally by the type system but should never be written by a programmer.} +\label{fig-sql-quotes-hierarchy} +\end{figure} + +\sectionAndLabel{What the SQL Quotes Checker checker}{sql-quotes-checks} + +Concatenation of \code{@SqlEvenQuotes} and \code{@SqlOddQuotes} Strings parallels +integer parity over addition. In other words, concatenation of \code{@SqlOddQuotes} +and \code{@SqlEvenQuotes} Strings are most narrowly typed as follows: + +\begin{verbatim} + @SqlOddQuotes + @SqlOddQuotes = @SqlEvenQuotes + @SqlOddQuotes + @SqlEvenQuotes = @SqlOddQuotes + @SqlEvenQuotes + @SqlOddQuotes = @SqlOddQuotes + @SqlEvenQuotes + @SqlEvenQuotes = @SqlEvenQuotes +\end{verbatim} + +SQL query execution methods such as \code{Statement.executeQuery} will only accept +the \code{@SqlEvenQuotes} qualifier as a parameter. Attempting to pass any other type to +the method will throw a type mismatch error, as \code{@SqlQuotesUnknown} Strings contain +unsanitized material that pose SQL injection risks and \code{@SqlOddQuotes} Strings will not +evaluate syntactically. + +Similarly, when writing annotations with the SQL Quotes Checker, methods that access +sensitive data (i.e., methods that query databases) should be annotated with the +\code{@SqlEvenQuotes} qualifier to prohibit unsanitized values from interacting with +said data. From 426e01f2b14b319ded7b715510ea97639f518984 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 25 Jul 2024 15:00:41 -0700 Subject: [PATCH 081/184] Added necessary references to SQL Quotes chapter --- docs/manual/Makefile | 1 + docs/manual/advanced-features.tex | 4 ++++ docs/manual/introduction.tex | 4 ++++ docs/manual/manual.tex | 1 + 4 files changed, 10 insertions(+) diff --git a/docs/manual/Makefile b/docs/manual/Makefile index a99a2bb9061..a7a37b6301b 100644 --- a/docs/manual/Makefile +++ b/docs/manual/Makefile @@ -24,6 +24,7 @@ propkey-checker.tex \ signature-checker.tex \ guieffect-checker.tex \ units-checker.tex \ +sql-quotes-checker.tex \ signedness-checker.tex \ purity-checker.tex \ constant-value-checker.tex \ diff --git a/docs/manual/advanced-features.tex b/docs/manual/advanced-features.tex index 7c3e175ab47..2d2331ab9d2 100644 --- a/docs/manual/advanced-features.tex +++ b/docs/manual/advanced-features.tex @@ -993,6 +993,10 @@ \ahrefloc{units-checker}{Units Checker} to ensure operations are performed on correct units of measurement (see \chapterpageref{units-checker}) +\item + \ahrefloc{sql-quotes-checker}{SQL Quotes Checker} to mitigate SQL injection + attacks + (see \chapterpageref{units-checker}) \item \ahrefloc{signedness-checker}{Signedness Checker} to ensure unsigned and signed values are not mixed diff --git a/docs/manual/introduction.tex b/docs/manual/introduction.tex index e4bd9281e4c..123a0d1c400 100644 --- a/docs/manual/introduction.tex +++ b/docs/manual/introduction.tex @@ -88,6 +88,10 @@ \ahrefloc{units-checker}{Units Checker} to ensure operations are performed on correct units of measurement (see \chapterpageref{units-checker}) +\item + \ahrefloc{sql-quotes-checker}{SQL Quotes Checker} to mitigate SQL injection + attacks + (see \chapterpageref{units-checker}) \item \ahrefloc{signedness-checker}{Signedness Checker} to ensure unsigned and signed values are not mixed diff --git a/docs/manual/manual.tex b/docs/manual/manual.tex index d22bfd7668e..742291f88dc 100644 --- a/docs/manual/manual.tex +++ b/docs/manual/manual.tex @@ -69,6 +69,7 @@ \input{signature-checker.tex} \input{guieffect-checker.tex} \input{units-checker.tex} +\input{sql-quotes-checker.tex} % These are focused on ints: \input{signedness-checker.tex} From 4f2670067d004247577ce963a2499a008a632544 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 26 Jul 2024 11:33:01 -0700 Subject: [PATCH 082/184] Document the zero-argument constructor --- .../checkerframework/checker/sqlquotes/SqlQuotesChecker.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java index f59a69a26c3..c43aee7ec93 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java @@ -11,4 +11,7 @@ * sanitized before use. */ @StubFiles({"BCryptPasswordEncoder.astub", "Statement.astub"}) -public class SqlQuotesChecker extends BaseTypeChecker {} +public class SqlQuotesChecker extends BaseTypeChecker { + /** Creates a SqlQuotesChecker. */ + public SqlQuotesChecker() {} +} From 4c1a336656b2ca94301659f9facc07c61e80f661 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 26 Jul 2024 12:36:28 -0700 Subject: [PATCH 083/184] Code review improvements --- .../checker/sqlquotes/qual/SqlEvenQuotes.java | 14 +++++++------- .../checker/sqlquotes/qual/SqlOddQuotes.java | 10 +++++----- .../checker/sqlquotes/qual/SqlQuotesUnknown.java | 4 ++-- .../checker/sqlquotes/SqlQuotesChecker.java | 4 ++-- .../checker/sqlquotes/SqlQuotesVisitor.java | 4 ++-- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java index 35be478110b..89030f0dc86 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java @@ -9,15 +9,15 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * Used to denote a String that contains either zero or an even number of unescaped single quotes – - * i.e., there must be either zero or an even number of ‘ characters in a SqlEvenQuotes String that - * are not preceded immediately by another ' character. (Thus, all SqlEvenQuotes Strings ultimately - * contain an even number of ' characters, escaped or otherwise.) SqlEvenQuotes Strings are - * syntactical to be passed to query execution methods and are guaranteed to have no impact on - * whether subsequent concatenations are interpreted as SQL command code or as SQL query values. + * Denotes a String that contains either zero or an even number of unescaped single quotes — + * i.e., there must be either zero or an even number of {@code ‘} characters in a SqlEvenQuotes + * String that are not preceded immediately by another {@code ‘} character. (Thus, all SqlEvenQuotes + * Strings ultimately contain an even number of {@code '} characters.) A SqlEvenQuotes String is + * syntactical to be passed to query execution methods and is guaranteed not to affect whether + * subsequent concatenations are interpreted as SQL command code or as SQL query values. * *

Common use cases include: SQL query fragments, such as “SELECT * FROM”; properly sanitized - * user input; and complete SQL queries, such as “SELECT * FROM table WHERE field = ‘value’”. + * user input; and complete SQL queries, such as “SELECT * FROM table WHERE field = 'value'”. * * @checker_framework.manual #sql-quotes-checker SQL Quotes Checker */ diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java index aa99396473f..fb82c197f29 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java @@ -9,11 +9,11 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * Used to denote a String that contains an odd number of unescaped single quotes – i.e., there must - * be an odd number of ‘ characters in a SqlOddQuotes String that are not preceded immediately by - * another ' character. (Thus, all SqlOddQuotes Strings ultimately contain an odd number of single - * quotes, escaped or otherwise.) SqlOddQuotes Strings are not syntactical to be passed to query - * execution methods. + * Denotes a String that contains an odd number of unescaped single quotes – i.e., there must be an + * odd number of ‘ characters in a SqlOddQuotes String that are not preceded immediately by another + * ' character. (Thus, all SqlOddQuotes Strings ultimately contain an odd number of single quotes, + * escaped or otherwise.) SqlOddQuotes Strings are not syntactical to be passed to query execution + * methods. * *

Common use cases include: SQL query fragments to be concatenated with user input, such as * “SELECT * FROM table WHERE field = ‘”; SQL query fragments containing user input but missing an diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java index 9959e9b4916..ad3cb4ff049 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlQuotesUnknown.java @@ -10,8 +10,8 @@ /** * Represents the top of the SQL Quotes qualifier hierarchy. Used to denote a String of which the - * quoting is unknown. SqlQuotesUnknown Strings are SQL injection vulnerabilities and thus unsafe to - * be passed to query execution methods. + * quoting is unknown. Using a SqlQuotesUnknown Strings within a SQL query may be, or lead to, a SQL + * injection vulnerability. * *

Common use cases include unsanitized user input. * diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java index c43aee7ec93..74decb739fc 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java @@ -4,8 +4,8 @@ import org.checkerframework.framework.qual.StubFiles; /** - * A type-checker plug-in for the SQL Quotes type system. It that finds (and verifies the absence - * of) SQL injection bugs. + * A type-checker plug-in for the SQL Quotes type system. It finds (and verifies the absence of) SQL + * injection bugs. * *

It verifies that only SQL-safe embedded query values are trusted and that user input is * sanitized before use. diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesVisitor.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesVisitor.java index f4d62e59317..8cf51245ff3 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesVisitor.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesVisitor.java @@ -19,8 +19,8 @@ public SqlQuotesVisitor(BaseTypeChecker checker) { } /** - * Don't check that the constructor result is top. Checking that the super() or this() call is a - * subtype of the constructor result is sufficient. + * This override does not check that the constructor result is top. Checking that the super() or + * this() call is a subtype of the constructor result is sufficient. */ @Override protected void checkConstructorResult( From 1afc6b876014df94b53380ee84ea8fbe4b6672e5 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 26 Jul 2024 14:10:55 -0700 Subject: [PATCH 084/184] Add Ivory Wang as contributor --- docs/manual/contributors.tex | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/manual/contributors.tex b/docs/manual/contributors.tex index 007b403ec0a..c6514822ba3 100644 --- a/docs/manual/contributors.tex +++ b/docs/manual/contributors.tex @@ -47,6 +47,7 @@ Haifeng Shi, Hamed Taghani, Heath Borders, +Ivory Wang, Jakub Vr\'ana, James Yoo, Jason Waataja, From 34ee739f8405a3b8a21f46a67a1ad377162e3253 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 26 Jul 2024 16:14:34 -0700 Subject: [PATCH 085/184] Improve regex efficiency; reorder chapters --- .../checker/sqlquotes/qual/SqlEvenQuotes.java | 2 +- .../checker/sqlquotes/qual/SqlOddQuotes.java | 2 +- docs/manual/Makefile | 2 +- docs/manual/advanced-features.tex | 10 ++++++---- docs/manual/introduction.tex | 8 ++++---- docs/manual/manual.tex | 6 ++++-- docs/manual/sql-quotes-checker.tex | 4 ++-- 7 files changed, 19 insertions(+), 15 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java index 89030f0dc86..02bbdf1fe33 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlEvenQuotes.java @@ -25,5 +25,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQuotesUnknown.class) -@QualifierForLiterals(stringPatterns = "^([^']*('[^']*'[^']*)*)$") +@QualifierForLiterals(stringPatterns = "^[^']*+('[^']*+'[^']*+)*+$") public @interface SqlEvenQuotes {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java index fb82c197f29..057119325aa 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/sqlquotes/qual/SqlOddQuotes.java @@ -27,5 +27,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(SqlQuotesUnknown.class) -@QualifierForLiterals(stringPatterns = "^[^']*('[^']*'[^']*)*'[^']*$") +@QualifierForLiterals(stringPatterns = "^[^']*+'[^']*+('[^']*+'[^']*+)*+$") public @interface SqlOddQuotes {} diff --git a/docs/manual/Makefile b/docs/manual/Makefile index a7a37b6301b..91aecd7b991 100644 --- a/docs/manual/Makefile +++ b/docs/manual/Makefile @@ -17,6 +17,7 @@ index-checker.tex \ called-methods-checker.tex \ fenum-checker.tex \ tainting-checker.tex \ +sql-quotes-checker.tex \ regex-checker.tex \ formatter-checker.tex \ i18n-format-checker.tex \ @@ -24,7 +25,6 @@ propkey-checker.tex \ signature-checker.tex \ guieffect-checker.tex \ units-checker.tex \ -sql-quotes-checker.tex \ signedness-checker.tex \ purity-checker.tex \ constant-value-checker.tex \ diff --git a/docs/manual/advanced-features.tex b/docs/manual/advanced-features.tex index 2d2331ab9d2..6a4db2d9e7c 100644 --- a/docs/manual/advanced-features.tex +++ b/docs/manual/advanced-features.tex @@ -901,6 +901,8 @@ % Keep these lists in sync with the list in introduction.tex . +% Anything that has "@QualifierForLiterals(stringPatterns = "...")" belongs +% in this section. Type systems that support a run-time test are: \begin{itemize} \item @@ -926,6 +928,10 @@ \item \ahrefloc{resource-leak-checker}{Resource Leak Checker} for ensuring that resources are disposed of properly (see \chapterpageref{resource-leak-checker}) +\item + \ahrefloc{sql-quotes-checker}{SQL Quotes Checker} to mitigate SQL injection + attacks + (see \chapterpageref{sql-quotes-checker}) \item \ahrefloc{regex-checker}{Regex Checker} to prevent use of syntactically invalid regular expressions (see \chapterpageref{regex-checker}) @@ -993,10 +999,6 @@ \ahrefloc{units-checker}{Units Checker} to ensure operations are performed on correct units of measurement (see \chapterpageref{units-checker}) -\item - \ahrefloc{sql-quotes-checker}{SQL Quotes Checker} to mitigate SQL injection - attacks - (see \chapterpageref{units-checker}) \item \ahrefloc{signedness-checker}{Signedness Checker} to ensure unsigned and signed values are not mixed diff --git a/docs/manual/introduction.tex b/docs/manual/introduction.tex index 123a0d1c400..a19c7ffac35 100644 --- a/docs/manual/introduction.tex +++ b/docs/manual/introduction.tex @@ -43,6 +43,10 @@ \item \ahrefloc{tainting-checker}{Tainting Checker} for trust and security errors (see \chapterpageref{tainting-checker}) +\item + \ahrefloc{sql-quotes-checker}{SQL Quotes Checker} to mitigate SQL injection + attacks + (see \chapterpageref{sql-quotes-checker}) \item \ahrefloc{lock-checker}{Lock Checker} for concurrency and lock errors (see \chapterpageref{lock-checker}) @@ -88,10 +92,6 @@ \ahrefloc{units-checker}{Units Checker} to ensure operations are performed on correct units of measurement (see \chapterpageref{units-checker}) -\item - \ahrefloc{sql-quotes-checker}{SQL Quotes Checker} to mitigate SQL injection - attacks - (see \chapterpageref{units-checker}) \item \ahrefloc{signedness-checker}{Signedness Checker} to ensure unsigned and signed values are not mixed diff --git a/docs/manual/manual.tex b/docs/manual/manual.tex index 742291f88dc..eac954db1fa 100644 --- a/docs/manual/manual.tex +++ b/docs/manual/manual.tex @@ -55,12 +55,15 @@ \input{called-methods-checker} \input{resource-leak-checker} \input{fenum-checker.tex} -\input{tainting-checker.tex} \input{lock-checker.tex} \input{index-checker.tex} % TODO: Uncomment when the Non-Empty Checker is ready to be publicized. % \input{non-empty-checker.tex} +% These are related to tainting: +\input{tainting-checker.tex} +\input{sql-quotes-checker.tex} + % These are focused on strings: \input{regex-checker.tex} \input{formatter-checker.tex} @@ -69,7 +72,6 @@ \input{signature-checker.tex} \input{guieffect-checker.tex} \input{units-checker.tex} -\input{sql-quotes-checker.tex} % These are focused on ints: \input{signedness-checker.tex} diff --git a/docs/manual/sql-quotes-checker.tex b/docs/manual/sql-quotes-checker.tex index 4e369af75b7..d3f6f0d53b5 100644 --- a/docs/manual/sql-quotes-checker.tex +++ b/docs/manual/sql-quotes-checker.tex @@ -41,8 +41,8 @@ \begin{description} \item[\refqualclass{checker/sqlquotes/qual}{SqlEvenQuotes}] - indicates a String literal that contains zero or an even number of - single quotes. + indicates a String literal that contains an even number of + single quotes (possibly zero). \item[\refqualclass{checker/sqlquotes/qual}{SqlOddQuotes}] indicates a String literal that contains an odd number of single quotes. From 5eab56f47b7cbba153da6635403d0bacf193d40f Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 28 Jul 2024 00:13:47 -0700 Subject: [PATCH 086/184] Updated Statement.astub with executeUpdate --- .../java/org/checkerframework/checker/sqlquotes/Statement.astub | 1 + 1 file changed, 1 insertion(+) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquotes/Statement.astub b/checker/src/main/java/org/checkerframework/checker/sqlquotes/Statement.astub index 71b9521c766..6ac263cd275 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquotes/Statement.astub +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/Statement.astub @@ -6,4 +6,5 @@ import org.checkerframework.checker.sqlquotes.qual.SqlEvenQuotes; public interface Statement extends Wrapper, AutoCloseable { ResultSet executeQuery(@SqlEvenQuotes String var1) throws SQLException; + int executeUpdate(@SqlEvenQuotes String var1) throws SQLException; } From 86dea85080bf5c48a74b9cb413cc5ae5707b7b58 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 30 Jul 2024 15:33:54 -0700 Subject: [PATCH 087/184] Removed calls to super() in visitBinary --- .../checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java | 1 - 1 file changed, 1 deletion(-) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java index 1bc12fda13d..50c5be0fa06 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java @@ -86,7 +86,6 @@ public SqlQuotesTreeAnnotator(AnnotatedTypeFactory atypeFactory) { @Override public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { - super.visitBinary(tree, type); if (TreeUtils.isStringConcatenation(tree)) { AnnotatedTypeMirror leftType = getAnnotatedType(tree.getLeftOperand()); AnnotatedTypeMirror rightType = getAnnotatedType(tree.getRightOperand()); From cb80d8be6678bc63d3d1a124b9e26689c73b4330 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 30 Jul 2024 15:35:06 -0700 Subject: [PATCH 088/184] Added concatenation assignment tests --- checker/tests/sqlquotes/SqlQuotesConcat.java | 31 ++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/checker/tests/sqlquotes/SqlQuotesConcat.java b/checker/tests/sqlquotes/SqlQuotesConcat.java index fb21ea431aa..13b78068fa1 100644 --- a/checker/tests/sqlquotes/SqlQuotesConcat.java +++ b/checker/tests/sqlquotes/SqlQuotesConcat.java @@ -9,12 +9,20 @@ void oddOddConcat() { // :: error: (assignment) @SqlOddQuotes String oddResult1 = odd1 + odd2; @SqlEvenQuotes String evenResult1 = odd1 + odd2; + // :: error: (compound.assignment) + odd1 += odd2; + // :: error: (compound.assignment) + odd2 += odd1; @SqlOddQuotes String odd3 = "'asdf"; @SqlOddQuotes String odd4 = "', "; // :: error: (assignment) @SqlOddQuotes String oddResult2 = odd3 + odd4; @SqlEvenQuotes String evenResult2 = odd3 + odd4; + // :: error: (compound.assignment) + odd3 += odd4; + // :: error: (compound.assignment) + odd4 += odd3; } void oddEvenConcat() { @@ -23,12 +31,18 @@ void oddEvenConcat() { // :: error: (assignment) @SqlEvenQuotes String evenResult1 = odd1 + even1; @SqlOddQuotes String oddResult1 = odd1 + even1; + odd1 += even1; + // :: error: (compound.assignment) + even1 += odd1; @SqlOddQuotes String odd2 = "'asdf"; @SqlEvenQuotes String even2 = "', asdf '"; // :: error: (assignment) @SqlEvenQuotes String evenResult2 = odd2 + even2; @SqlOddQuotes String oddResult2 = odd2 + even2; + odd2 += even2; + // :: error: (compound.assignment) + even2 += odd2; } void evenOddConcat() { @@ -37,12 +51,18 @@ void evenOddConcat() { // :: error: (assignment) @SqlEvenQuotes String evenResult1 = even1 + odd1; @SqlOddQuotes String oddResult1 = even1 + odd1; + odd1 += even1; + // :: error: (compound.assignment) + even1 += odd1; @SqlOddQuotes String odd2 = "'asdf"; @SqlEvenQuotes String even2 = "', asdf '"; // :: error: (assignment) @SqlEvenQuotes String evenResult2 = even2 + odd2; @SqlOddQuotes String oddResult2 = even2 + odd2; + odd2 += even2; + // :: error: (compound.assignment) + even2 += odd2; } void evenEvenConcat() { @@ -51,12 +71,16 @@ void evenEvenConcat() { // :: error: (assignment) @SqlOddQuotes String oddResult1 = even1 + even2; @SqlEvenQuotes String evenResult1 = even1 + even2; + even1 += even2; + even2 += even1; @SqlEvenQuotes String even3 = "'a''sdf'"; @SqlEvenQuotes String even4 = "'asdf''asdf'asdf'asdf'''"; // :: error: (assignment) @SqlOddQuotes String oddResult2 = even3 + even4; @SqlEvenQuotes String evenResult2 = even3 + even4; + even3 += even4; + even4 += even3; } void withTopConcat(@SqlQuotesUnknown String top) { @@ -71,6 +95,9 @@ void withTopConcat(@SqlQuotesUnknown String top) { // :: error: (assignment) @SqlEvenQuotes String evenResult2 = top + odd1; String topResult2 = top + odd1; + // :: error: (compound.assignment) + odd1 += top; + top += odd1; @SqlEvenQuotes String even1 = "'a''sdf'"; // :: error: (assignment) @@ -83,11 +110,15 @@ void withTopConcat(@SqlQuotesUnknown String top) { // :: error: (assignment) @SqlEvenQuotes String evenResult4 = top + even1; String topResult4 = top + even1; + // :: error: (compound.assignment) + even1 += top; + top += even1; // :: error: (assignment) @SqlOddQuotes String oddResult5 = top + top; // :: error: (assignment) @SqlEvenQuotes String evenResult5 = top + top; String topResult5 = top + top; + top += top; } } From 6f43fa5671bab3aa956db7135a8db9506441ff05 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Wed, 31 Jul 2024 12:45:23 -0700 Subject: [PATCH 089/184] Added compound assignment visitor --- .../SqlQuotesAnnotatedTypeFactory.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java index 50c5be0fa06..c7f47add775 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java @@ -1,6 +1,7 @@ package org.checkerframework.checker.sqlquotes; import com.sun.source.tree.BinaryTree; +import com.sun.source.tree.CompoundAssignmentTree; import java.util.Set; import javax.lang.model.element.AnnotationMirror; import org.checkerframework.checker.sqlquotes.qual.SqlEvenQuotes; @@ -124,5 +125,44 @@ public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { return null; } + + @Override + public Void visitCompoundAssignment(CompoundAssignmentTree tree, AnnotatedTypeMirror type) { + if (TreeUtils.isStringCompoundConcatenation(tree)) { + AnnotatedTypeMirror leftType = getAnnotatedType(tree.getVariable()); + AnnotatedTypeMirror rightType = getAnnotatedType(tree.getExpression()); + + if (leftType.hasPrimaryAnnotation(SQL_QUOTES_UNKNOWN)) { + return null; + } + + if (rightType.hasPrimaryAnnotation(SQL_QUOTES_UNKNOWN)) { + type.replaceAnnotation(SQL_QUOTES_UNKNOWN); + return null; + } + + if (leftType.hasPrimaryAnnotation(SQL_QUOTES_BOTTOM)) { + type.replaceAnnotation(rightType.getPrimaryAnnotation()); + return null; + } else if (rightType.hasPrimaryAnnotation(SQL_QUOTES_BOTTOM)) { + type.replaceAnnotation(leftType.getPrimaryAnnotation()); + return null; + } + + if (leftType.hasPrimaryAnnotation(SQL_EVEN_QUOTES)) { + type.replaceAnnotation(rightType.getPrimaryAnnotation()); + } else { + if (rightType.hasPrimaryAnnotation(SQL_ODD_QUOTES)) { + type.replaceAnnotation(SQL_EVEN_QUOTES); + } else { + type.replaceAnnotation(SQL_ODD_QUOTES); + } + } + + return null; + } + + return null; + } } } From ee22b58700329cc72bfd84655e73e6585b729ad1 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Mon, 5 Aug 2024 09:18:47 -0700 Subject: [PATCH 090/184] Add `@RelevantJavaTypes` --- .../checkerframework/checker/sqlquotes/SqlQuotesChecker.java | 2 ++ .../framework/type/treeannotator/TreeAnnotator.java | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java index 74decb739fc..bfaa9c32c23 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesChecker.java @@ -1,6 +1,7 @@ package org.checkerframework.checker.sqlquotes; import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.framework.qual.RelevantJavaTypes; import org.checkerframework.framework.qual.StubFiles; /** @@ -11,6 +12,7 @@ * sanitized before use. */ @StubFiles({"BCryptPasswordEncoder.astub", "Statement.astub"}) +@RelevantJavaTypes(CharSequence.class) public class SqlQuotesChecker extends BaseTypeChecker { /** Creates a SqlQuotesChecker. */ public SqlQuotesChecker() {} diff --git a/framework/src/main/java/org/checkerframework/framework/type/treeannotator/TreeAnnotator.java b/framework/src/main/java/org/checkerframework/framework/type/treeannotator/TreeAnnotator.java index 93e140d7bc8..127d8dcbb3a 100644 --- a/framework/src/main/java/org/checkerframework/framework/type/treeannotator/TreeAnnotator.java +++ b/framework/src/main/java/org/checkerframework/framework/type/treeannotator/TreeAnnotator.java @@ -76,8 +76,8 @@ public Void visitMethod(MethodTree tree, AnnotatedTypeMirror p) { /** * When overriding this method, getAnnotatedType on the left and right operands should only be - * called when absolutely necessary. Otherwise, the checker will be very slow on heavily nested - * binary trees. (For example, a + b + c + d + e + f + g + h.) + * called when absolutely necessary. Otherwise, the checker will be very slow on heavily + * nested binary trees. (For example, a + b + c + d + e + f + g + h.) * *

If a checker's performance is still too slow, the types of binary trees could be computed in * a subclass of {@link org.checkerframework.framework.flow.CFTransfer}. When computing the types From 417b0dd2ae5ee64e2acc0073a5e814399e77c827 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 5 Aug 2024 11:53:37 -0700 Subject: [PATCH 091/184] Abstracted visitCompoundAssignment and visitBinary logic into separate method --- .../SqlQuotesAnnotatedTypeFactory.java | 100 +++++++----------- 1 file changed, 39 insertions(+), 61 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java index c7f47add775..b8a4d5e543b 100644 --- a/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/sqlquotes/SqlQuotesAnnotatedTypeFactory.java @@ -90,39 +90,8 @@ public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { if (TreeUtils.isStringConcatenation(tree)) { AnnotatedTypeMirror leftType = getAnnotatedType(tree.getLeftOperand()); AnnotatedTypeMirror rightType = getAnnotatedType(tree.getRightOperand()); - - if (leftType.hasPrimaryAnnotation(SQL_QUOTES_UNKNOWN) - || rightType.hasPrimaryAnnotation(SQL_QUOTES_UNKNOWN)) { - type.replaceAnnotation(SQL_QUOTES_UNKNOWN); - return null; - } - - if (leftType.hasPrimaryAnnotation(SQL_QUOTES_BOTTOM)) { - type.replaceAnnotation(rightType.getPrimaryAnnotation()); - return null; - } else if (rightType.hasPrimaryAnnotation(SQL_QUOTES_BOTTOM)) { - type.replaceAnnotation(leftType.getPrimaryAnnotation()); - return null; - } - - int leftParity = 0; - if (leftType.hasPrimaryAnnotation(SQL_ODD_QUOTES)) { - leftParity = 1; - } - - int rightParity = 0; - if (rightType.hasPrimaryAnnotation(SQL_ODD_QUOTES)) { - rightParity = 1; - } - - int parity = leftParity + rightParity; - if (parity == 0 || parity == 2) { - type.replaceAnnotation(SQL_EVEN_QUOTES); - } else { - type.replaceAnnotation(SQL_ODD_QUOTES); - } + type.replaceAnnotation(getResultingType(leftType, rightType)); } - return null; } @@ -131,38 +100,47 @@ public Void visitCompoundAssignment(CompoundAssignmentTree tree, AnnotatedTypeMi if (TreeUtils.isStringCompoundConcatenation(tree)) { AnnotatedTypeMirror leftType = getAnnotatedType(tree.getVariable()); AnnotatedTypeMirror rightType = getAnnotatedType(tree.getExpression()); + type.replaceAnnotation(getResultingType(leftType, rightType)); + } + return null; + } + + /** + * Returns the type of concatenating leftType and rightType. + * + * @param leftType the type on the left of the expression + * @param rightType the type on the right of the expression + * @return the resulting type after concatenation + */ + private AnnotationMirror getResultingType( + AnnotatedTypeMirror leftType, AnnotatedTypeMirror rightType) { + if (leftType.hasPrimaryAnnotation(SQL_QUOTES_UNKNOWN) + || rightType.hasPrimaryAnnotation(SQL_QUOTES_UNKNOWN)) { + return SQL_QUOTES_UNKNOWN; + } - if (leftType.hasPrimaryAnnotation(SQL_QUOTES_UNKNOWN)) { - return null; - } - - if (rightType.hasPrimaryAnnotation(SQL_QUOTES_UNKNOWN)) { - type.replaceAnnotation(SQL_QUOTES_UNKNOWN); - return null; - } - - if (leftType.hasPrimaryAnnotation(SQL_QUOTES_BOTTOM)) { - type.replaceAnnotation(rightType.getPrimaryAnnotation()); - return null; - } else if (rightType.hasPrimaryAnnotation(SQL_QUOTES_BOTTOM)) { - type.replaceAnnotation(leftType.getPrimaryAnnotation()); - return null; - } - - if (leftType.hasPrimaryAnnotation(SQL_EVEN_QUOTES)) { - type.replaceAnnotation(rightType.getPrimaryAnnotation()); - } else { - if (rightType.hasPrimaryAnnotation(SQL_ODD_QUOTES)) { - type.replaceAnnotation(SQL_EVEN_QUOTES); - } else { - type.replaceAnnotation(SQL_ODD_QUOTES); - } - } - - return null; + if (leftType.hasPrimaryAnnotation(SQL_QUOTES_BOTTOM)) { + return rightType.getPrimaryAnnotation(); + } else if (rightType.hasPrimaryAnnotation(SQL_QUOTES_BOTTOM)) { + return leftType.getPrimaryAnnotation(); } - return null; + int leftParity = 0; + if (leftType.hasPrimaryAnnotation(SQL_ODD_QUOTES)) { + leftParity = 1; + } + + int rightParity = 0; + if (rightType.hasPrimaryAnnotation(SQL_ODD_QUOTES)) { + rightParity = 1; + } + + int parity = leftParity + rightParity; + if (parity == 0 || parity == 2) { + return SQL_EVEN_QUOTES; + } else { + return SQL_ODD_QUOTES; + } } } } From c1bea0483879f14f00e954b47f573ea36dfecf5b Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 15 Aug 2024 10:24:17 -0700 Subject: [PATCH 092/184] Edits to manual --- docs/CHANGELOG.md | 3 + docs/manual/sql-quotes-checker.tex | 91 ++++++++++++++++++------------ 2 files changed, 57 insertions(+), 37 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index fc1b9d5967d..03ff131dd74 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -3,6 +3,9 @@ Version 3.46.0 (August 1, 2024) **User-visible changes:** +The new SqlQuotesChecker prevents errors in quoting in SQL queries. It prevents +injection attacks that exploit quoting errors. + Renamed `@EnsuresCalledMethodsVarArgs`to `@EnsuresCalledMethodsVarargs`. **Closed issues:** diff --git a/docs/manual/sql-quotes-checker.tex b/docs/manual/sql-quotes-checker.tex index d3f6f0d53b5..455f7476b23 100644 --- a/docs/manual/sql-quotes-checker.tex +++ b/docs/manual/sql-quotes-checker.tex @@ -5,37 +5,38 @@ \href{https://en.wikipedia.org/wiki/Sql_injection}{SQL injection} attacks involve malicious user input containing unescaped special characters such as the single quote, which can change whether subsequent concatenations are interpreted -as SQL command code or as SQL query values. (Some databases support the use of the -backslash as an escape character for single quotes. However, ANSI standard determines -that single quotes in SQL queries should be escaped by \emph{doubling-up}: -immediately preceding or following it with another single quote. The SQL Quotes Checker -follows ANSI standard and considers doubled-up single quotes as one escaped single quote.) - -Consequently, the checker qualifies String literals by the parity of unescaped single -quotes present. Furthermore, it marks user-supplied Strings as unsafe for SQL query -use, as their quoting is unknown; the program must \emph{sanitize} all such values -before concatenating them to a SQL query for execution. Sanitization can be done by -parsing and quoting user input as necessary to ensure special characters are properly -escaped. The SQL Quotes Checker guarantees that no unchecked values are passed to a -SQL query execution statement. It is \emph{unable} to guarantee that hard-coded SQL -queries written by the code author are safe for execution; e.g., the checker will not -warn at compile time about improper uses of \code{DELETE} or \code{DROP} statements. - -It should be noted that using SQL parameters rather than direct concatenation of -SQL query values onto SQL commands mitigates the danger of SQL injection attacks, -as parameterized values are, by design, unable to be misinterpreted as part of a SQL -command. Developers should strive to use parameterized queries when possible; the -SQL Quotes Checker is at its most applicable when retrospectively securing existing -programs involving user input concatenation. +as SQL command code or as SQL query values. + +The SQL Quotes Checker helps classifies Strings by the parity of unescaped +single quotes. Furthermore, it marks user-supplied Strings as unsafe for +SQL query use, as their quoting is unknown; the program must +\emph{sanitize} or \emph{validate} all such values before concatenating +them to a SQL query for execution. Sanitization can be done by quoting user +input as necessary to ensure special characters are properly escaped. The +SQL Quotes Checker follows ANSI standard and considers doubled-up single +quotes as one escaped single quote. (Some databases support the use of the +backslash as an escape character for single quotes, but this is not safe +for all SQL database implementations.) + +The SQL Quotes Checker guarantees that no unchecked values are passed to a +SQL query execution statement. It does \emph{not} to guarantee that SQL +queries written by the code author are safe for execution; e.g., the +checker will not warn at compile time about syntax errors or improper uses +of \code{DELETE} or \code{DROP} statements. + +When possible, it is better to use a prepared statement or other mechanisms +that automatically handle quoting without the need for the programmer to do +any work. The SQL Quotes Checker is useful for the large quantity of code +that still uses string concatenation to create SQL queries. To run the SQL Quotes Checker, supply the \code{-processor SqlQuotesChecker} or \code{-processor org.checkerframework.checker.sqlquotes.SqlQuotesChecker} command-line option to javac. -% for examples -\sectionAndLabel{SQL quotes annotations}{sql-quotes-annotations} + +\sectionAndLabel{SQL Quotes annotations}{sql-quotes-annotations} The SQL Quotes type system uses the following annotations: @@ -51,6 +52,8 @@ \code{@SqlQuotesUnknown} is a supertype of \code{@SqlEvenQuotes} and \code{@SqlOddQuotes}. It is the default qualifier for non-literal Strings. +\item[\refqualclass{checker/sqlquotes/qual}{SqlQuotesBottom}] + is the bottom qualifier. Programmers rarely need to write it. \end{description} The subtyping hierarchy of the SQL Quotes Checker's qualifiers is shown in @@ -64,26 +67,40 @@ \label{fig-sql-quotes-hierarchy} \end{figure} + \sectionAndLabel{What the SQL Quotes Checker checker}{sql-quotes-checks} Concatenation of \code{@SqlEvenQuotes} and \code{@SqlOddQuotes} Strings parallels integer parity over addition. In other words, concatenation of \code{@SqlOddQuotes} and \code{@SqlEvenQuotes} Strings are most narrowly typed as follows: -\begin{verbatim} +\begin{Verbatim} @SqlOddQuotes + @SqlOddQuotes = @SqlEvenQuotes @SqlOddQuotes + @SqlEvenQuotes = @SqlOddQuotes @SqlEvenQuotes + @SqlOddQuotes = @SqlOddQuotes @SqlEvenQuotes + @SqlEvenQuotes = @SqlEvenQuotes -\end{verbatim} - -SQL query execution methods such as \code{Statement.executeQuery} will only accept -the \code{@SqlEvenQuotes} qualifier as a parameter. Attempting to pass any other type to -the method will throw a type mismatch error, as \code{@SqlQuotesUnknown} Strings contain -unsanitized material that pose SQL injection risks and \code{@SqlOddQuotes} Strings will not -evaluate syntactically. - -Similarly, when writing annotations with the SQL Quotes Checker, methods that access -sensitive data (i.e., methods that query databases) should be annotated with the -\code{@SqlEvenQuotes} qualifier to prohibit unsanitized values from interacting with -said data. +\end{Verbatim} + + +\sectionAndLabel{Library annotations}{sql-quotes-library-annotations} + +The programmer needs to write trusted annotations on SQL-related methods. +This is already done for you, for commonly-used libraries such as +\ and +\. +(If you annotate other libraries, please contribute them to the Checker +Framework project. Thanks!) + +A SQL query execution method such as \code{Statement.executeQuery} must be +annotated to take a \code{@SqlEvenQuotes} string as a parameter. + +A sanitization or quoting method should be annotated to take a +\refqualclass{checker/sqlquotes/qual}{SqlQuotesUnknown} parameter and to +return a \refqualclass{checker/sqlquotes/qual}{SqlEvenQuotes} result. + +Given such annotations, the type system will issue an error if an +un-sanitized value can ever flow into a database query. +(You might need to write some annotations in your own code as well.) + +% LocalWords: unescaped SqlQuotesChecker sql SqlEvenQuotes SqlOddQuotes +% LocalWords: SqlQuotesUnknown SqlQuotesBottom executeQuery un From 1b78fdecac237ccc28a0730f6ed74241feb46c78 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 18 Aug 2024 20:09:21 -0700 Subject: [PATCH 093/184] Added base template for confidential qualifiers and classes --- .../checker/confidential/Confidential.java | 23 ++++++++++++ .../checker/confidential/NonConfidential.java | 25 +++++++++++++ .../confidential/PolyConfidential.java | 20 +++++++++++ .../checker/private/PolyPrivate.java | 20 +++++++++++ .../checker/private/Private.java | 23 ++++++++++++ .../checker/private/Public.java | 25 +++++++++++++ .../ConfidentialAnnotatedTypeFactory.java | 36 +++++++++++++++++++ .../confidential/ConfidentialChecker.java | 15 ++++++++ .../confidential/ConfidentialVisitor.java | 28 +++++++++++++++ 9 files changed, 215 insertions(+) create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/confidential/Confidential.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/confidential/NonConfidential.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/confidential/PolyConfidential.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/private/PolyPrivate.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/private/Private.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/private/Public.java create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialVisitor.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/Confidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/Confidential.java new file mode 100644 index 00000000000..b0ad26dc49e --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/Confidential.java @@ -0,0 +1,23 @@ +package org.checkerframework.checker.tainting.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Denotes a possibly-tainted value: at run time, the value might be tainted or might be untainted. + * + * @see Untainted + * @see org.checkerframework.checker.tainting.TaintingChecker + * @checker_framework.manual #tainting-checker Tainting Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({}) +@DefaultQualifierInHierarchy +public @interface Tainted {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/NonConfidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/NonConfidential.java new file mode 100644 index 00000000000..83d48f5186b --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/NonConfidential.java @@ -0,0 +1,25 @@ +package org.checkerframework.checker.tainting.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.DefaultFor; +import org.checkerframework.framework.qual.LiteralKind; +import org.checkerframework.framework.qual.QualifierForLiterals; +import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TypeUseLocation; + +/** + * Denotes a reference that is untainted, i.e. can be trusted. + * + * @checker_framework.manual #tainting-checker Tainting Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(Tainted.class) +@QualifierForLiterals(LiteralKind.STRING) +@DefaultFor(TypeUseLocation.LOWER_BOUND) +public @interface Untainted {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/PolyConfidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/PolyConfidential.java new file mode 100644 index 00000000000..0f481e6ab56 --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/PolyConfidential.java @@ -0,0 +1,20 @@ +package org.checkerframework.checker.tainting.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.PolymorphicQualifier; + +/** + * A polymorphic qualifier for the Tainting type system. + * + * @checker_framework.manual #tainting-checker Tainting Checker + * @checker_framework.manual #qualifier-polymorphism Qualifier polymorphism + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@PolymorphicQualifier(Tainted.class) +public @interface PolyTainted {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/private/PolyPrivate.java b/checker-qual/src/main/java/org/checkerframework/checker/private/PolyPrivate.java new file mode 100644 index 00000000000..0f481e6ab56 --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/private/PolyPrivate.java @@ -0,0 +1,20 @@ +package org.checkerframework.checker.tainting.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.PolymorphicQualifier; + +/** + * A polymorphic qualifier for the Tainting type system. + * + * @checker_framework.manual #tainting-checker Tainting Checker + * @checker_framework.manual #qualifier-polymorphism Qualifier polymorphism + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@PolymorphicQualifier(Tainted.class) +public @interface PolyTainted {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/private/Private.java b/checker-qual/src/main/java/org/checkerframework/checker/private/Private.java new file mode 100644 index 00000000000..b0ad26dc49e --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/private/Private.java @@ -0,0 +1,23 @@ +package org.checkerframework.checker.tainting.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.SubtypeOf; + +/** + * Denotes a possibly-tainted value: at run time, the value might be tainted or might be untainted. + * + * @see Untainted + * @see org.checkerframework.checker.tainting.TaintingChecker + * @checker_framework.manual #tainting-checker Tainting Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf({}) +@DefaultQualifierInHierarchy +public @interface Tainted {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/private/Public.java b/checker-qual/src/main/java/org/checkerframework/checker/private/Public.java new file mode 100644 index 00000000000..83d48f5186b --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/private/Public.java @@ -0,0 +1,25 @@ +package org.checkerframework.checker.tainting.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.DefaultFor; +import org.checkerframework.framework.qual.LiteralKind; +import org.checkerframework.framework.qual.QualifierForLiterals; +import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TypeUseLocation; + +/** + * Denotes a reference that is untainted, i.e. can be trusted. + * + * @checker_framework.manual #tainting-checker Tainting Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(Tainted.class) +@QualifierForLiterals(LiteralKind.STRING) +@DefaultFor(TypeUseLocation.LOWER_BOUND) +public @interface Untainted {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java new file mode 100644 index 00000000000..186a44113f8 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java @@ -0,0 +1,36 @@ +package org.checkerframework.checker.tainting; + +import java.util.Set; +import javax.lang.model.element.AnnotationMirror; +import org.checkerframework.checker.tainting.qual.Untainted; +import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; +import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.javacutil.AnnotationBuilder; +import org.checkerframework.javacutil.AnnotationMirrorSet; + +/** Annotated type factory for the Tainting Checker. */ +public class TaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { + + /** The {@code @}{@link Untainted} annotation mirror. */ + private final AnnotationMirror UNTAINTED; + + /** A singleton set containing the {@code @}{@link Untainted} annotation mirror. */ + private final AnnotationMirrorSet setOfUntainted; + + /** + * Creates a {@link TaintingAnnotatedTypeFactory}. + * + * @param checker the tainting checker + */ + public TaintingAnnotatedTypeFactory(BaseTypeChecker checker) { + super(checker); + this.UNTAINTED = AnnotationBuilder.fromClass(getElementUtils(), Untainted.class); + this.setOfUntainted = AnnotationMirrorSet.singleton(UNTAINTED); + postInit(); + } + + @Override + protected Set getEnumConstructorQualifiers() { + return setOfUntainted; + } +} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java new file mode 100644 index 00000000000..91fb23fb813 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -0,0 +1,15 @@ +package org.checkerframework.checker.tainting; + +import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.framework.source.SuppressWarningsPrefix; + +/** + * A type-checker plug-in for the Tainting type system qualifier that finds (and verifies the + * absence of) trust bugs. + * + *

It verifies that only verified values are trusted and that user-input is sanitized before use. + * + * @checker_framework.manual #tainting-checker Tainting Checker + */ +@SuppressWarningsPrefix({"untainted", "tainting"}) +public class TaintingChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialVisitor.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialVisitor.java new file mode 100644 index 00000000000..40f78e18ce5 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialVisitor.java @@ -0,0 +1,28 @@ +package org.checkerframework.checker.tainting; + +import javax.lang.model.element.ExecutableElement; +import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; +import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.common.basetype.BaseTypeVisitor; +import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType; + +/** Visitor for the {@link TaintingChecker}. */ +public class TaintingVisitor extends BaseTypeVisitor { + + /** + * Creates a {@link TaintingVisitor}. + * + * @param checker the checker that uses this visitor + */ + public TaintingVisitor(BaseTypeChecker checker) { + super(checker); + } + + /** + * Don't check that the constructor result is top. Checking that the super() or this() call is a + * subtype of the constructor result is sufficient. + */ + @Override + protected void checkConstructorResult( + AnnotatedExecutableType constructorType, ExecutableElement constructorElement) {} +} From 56bd10d1d3fc5d8b95a4d149360fd67bde144fb8 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 18 Aug 2024 20:21:35 -0700 Subject: [PATCH 094/184] Moved qualifiers to correct directory --- .../confidential/{ => qual}/Confidential.java | 12 ++++++------ .../confidential/{ => qual}/NonConfidential.java | 10 +++++----- .../confidential/{ => qual}/PolyConfidential.java | 10 +++++----- 3 files changed, 16 insertions(+), 16 deletions(-) rename checker-qual/src/main/java/org/checkerframework/checker/confidential/{ => qual}/Confidential.java (60%) rename checker-qual/src/main/java/org/checkerframework/checker/confidential/{ => qual}/NonConfidential.java (74%) rename checker-qual/src/main/java/org/checkerframework/checker/confidential/{ => qual}/PolyConfidential.java (65%) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/Confidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java similarity index 60% rename from checker-qual/src/main/java/org/checkerframework/checker/confidential/Confidential.java rename to checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java index b0ad26dc49e..718fbcf2321 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/confidential/Confidential.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.tainting.qual; +package org.checkerframework.checker.confidential; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -9,15 +9,15 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * Denotes a possibly-tainted value: at run time, the value might be tainted or might be untainted. + * TODO * - * @see Untainted - * @see org.checkerframework.checker.tainting.TaintingChecker - * @checker_framework.manual #tainting-checker Tainting Checker + * @see NonConfidential + * @see org.checkerframework.checker.tainting.ConfidentialChecker + * @checker_framework.manual TODO */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf({}) @DefaultQualifierInHierarchy -public @interface Tainted {} +public @interface Confidential {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/NonConfidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java similarity index 74% rename from checker-qual/src/main/java/org/checkerframework/checker/confidential/NonConfidential.java rename to checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java index 83d48f5186b..5027958ac4b 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/confidential/NonConfidential.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.tainting.qual; +package org.checkerframework.checker.confidential; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -12,14 +12,14 @@ import org.checkerframework.framework.qual.TypeUseLocation; /** - * Denotes a reference that is untainted, i.e. can be trusted. + * TODO * - * @checker_framework.manual #tainting-checker Tainting Checker + * @checker_framework.manual TODO */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(Tainted.class) +@SubtypeOf(Confidential.class) @QualifierForLiterals(LiteralKind.STRING) @DefaultFor(TypeUseLocation.LOWER_BOUND) -public @interface Untainted {} +public @interface NonConfidential {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/PolyConfidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/PolyConfidential.java similarity index 65% rename from checker-qual/src/main/java/org/checkerframework/checker/confidential/PolyConfidential.java rename to checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/PolyConfidential.java index 0f481e6ab56..ab1f0d3583d 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/confidential/PolyConfidential.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/PolyConfidential.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.tainting.qual; +package org.checkerframework.checker.confidential; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -8,13 +8,13 @@ import org.checkerframework.framework.qual.PolymorphicQualifier; /** - * A polymorphic qualifier for the Tainting type system. + * A polymorphic qualifier for the Confidential type system. * - * @checker_framework.manual #tainting-checker Tainting Checker + * @checker_framework.manual TODO * @checker_framework.manual #qualifier-polymorphism Qualifier polymorphism */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@PolymorphicQualifier(Tainted.class) -public @interface PolyTainted {} +@PolymorphicQualifier(Confidential.class) +public @interface PolyConfidential {} From f1f1e178da0cd0ee3c5cd5c5c8185db2e8b29c67 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 18 Aug 2024 23:06:40 -0700 Subject: [PATCH 095/184] Revised Javadocs --- .../confidential/qual/Confidential.java | 10 ++++--- .../confidential/qual/NonConfidential.java | 10 ++++--- .../confidential/qual/PolyConfidential.java | 2 +- .../ConfidentialAnnotatedTypeFactory.java | 28 +++++++++---------- .../confidential/ConfidentialChecker.java | 14 +++++----- .../confidential/ConfidentialVisitor.java | 10 +++---- 6 files changed, 39 insertions(+), 35 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java index 718fbcf2321..639d600fc80 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.confidential; +package org.checkerframework.checker.confidential.qual; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -9,11 +9,13 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * TODO + * Denotes a value that should not be exposed to end users (i.e., PII, passwords, and private keys) + * or a location (i.e., a file or database) that should not be able to be accessed by end users. + * Confidential locations can contain Confidential or NonConfidential information. * * @see NonConfidential - * @see org.checkerframework.checker.tainting.ConfidentialChecker - * @checker_framework.manual TODO + * @see org.checkerframework.checker.confidential.ConfidentialChecker + * @checker_framework.manual #confidential-checker Confidential Checker */ @Documented @Retention(RetentionPolicy.RUNTIME) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java index 5027958ac4b..91719ef1bb7 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.confidential; +package org.checkerframework.checker.confidential.qual; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -12,14 +12,16 @@ import org.checkerframework.framework.qual.TypeUseLocation; /** - * TODO + * Denotes a value that can be exposed to end users, or a location that can be accessed by end + * users. NonConfidential locations can only contain NonConfidential information, not Confidential + * information. * - * @checker_framework.manual TODO + * @checker_framework.manual #confidential-checker Confidential Checker */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(Confidential.class) -@QualifierForLiterals(LiteralKind.STRING) +@QualifierForLiterals(LiteralKind.ALL) @DefaultFor(TypeUseLocation.LOWER_BOUND) public @interface NonConfidential {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/PolyConfidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/PolyConfidential.java index ab1f0d3583d..7c48586a0a5 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/PolyConfidential.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/PolyConfidential.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.confidential; +package org.checkerframework.checker.confidential.qual; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java index 186a44113f8..4e3393b407b 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java @@ -1,36 +1,36 @@ -package org.checkerframework.checker.tainting; +package org.checkerframework.checker.confidential; import java.util.Set; import javax.lang.model.element.AnnotationMirror; -import org.checkerframework.checker.tainting.qual.Untainted; +import org.checkerframework.checker.confidential.qual.NonConfidential; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.javacutil.AnnotationBuilder; import org.checkerframework.javacutil.AnnotationMirrorSet; -/** Annotated type factory for the Tainting Checker. */ -public class TaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { +/** Annotated type factory for the Confidential Checker. */ +public class ConfidentialAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { - /** The {@code @}{@link Untainted} annotation mirror. */ - private final AnnotationMirror UNTAINTED; + /** The {@code @}{@link NonConfidential} annotation mirror. */ + private final AnnotationMirror NONCONFIDENTIAL; - /** A singleton set containing the {@code @}{@link Untainted} annotation mirror. */ - private final AnnotationMirrorSet setOfUntainted; + /** A singleton set containing the {@code @}{@link NonConfidential} annotation mirror. */ + private final AnnotationMirrorSet setOfNonConfidential; /** - * Creates a {@link TaintingAnnotatedTypeFactory}. + * Creates a {@link ConfidentialAnnotatedTypeFactory}. * - * @param checker the tainting checker + * @param checker the confidential checker */ - public TaintingAnnotatedTypeFactory(BaseTypeChecker checker) { + public ConfidentialAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); - this.UNTAINTED = AnnotationBuilder.fromClass(getElementUtils(), Untainted.class); - this.setOfUntainted = AnnotationMirrorSet.singleton(UNTAINTED); + this.NONCONFIDENTIAL = AnnotationBuilder.fromClass(getElementUtils(), NonConfidential.class); + this.setOfNonConfidential = AnnotationMirrorSet.singleton(NONCONFIDENTIAL); postInit(); } @Override protected Set getEnumConstructorQualifiers() { - return setOfUntainted; + return setOfNonConfidential; } } diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 91fb23fb813..a66538db1cf 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -1,15 +1,15 @@ -package org.checkerframework.checker.tainting; +package org.checkerframework.checker.confidential; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.framework.source.SuppressWarningsPrefix; /** - * A type-checker plug-in for the Tainting type system qualifier that finds (and verifies the - * absence of) trust bugs. + * A type-checker plug-in for the Confidential type system qualifier that finds (and verifies the + * absence of) information leakage bugs. * - *

It verifies that only verified values are trusted and that user-input is sanitized before use. + *

It verifies that no confidential values are passed to user-facing methods. * - * @checker_framework.manual #tainting-checker Tainting Checker + * @checker_framework.manual #confidential-checker Confidential Checker */ -@SuppressWarningsPrefix({"untainted", "tainting"}) -public class TaintingChecker extends BaseTypeChecker {} +@SuppressWarningsPrefix({"confidential"}) +public class ConfidentialChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialVisitor.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialVisitor.java index 40f78e18ce5..e9a0ec3cda9 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialVisitor.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialVisitor.java @@ -1,4 +1,4 @@ -package org.checkerframework.checker.tainting; +package org.checkerframework.checker.confidential; import javax.lang.model.element.ExecutableElement; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; @@ -6,15 +6,15 @@ import org.checkerframework.common.basetype.BaseTypeVisitor; import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType; -/** Visitor for the {@link TaintingChecker}. */ -public class TaintingVisitor extends BaseTypeVisitor { +/** Visitor for the {@link ConfidentialChecker}. */ +public class ConfidentialVisitor extends BaseTypeVisitor { /** - * Creates a {@link TaintingVisitor}. + * Creates a {@link ConfidentialVisitor}. * * @param checker the checker that uses this visitor */ - public TaintingVisitor(BaseTypeChecker checker) { + public ConfidentialVisitor(BaseTypeChecker checker) { super(checker); } From a2d86810185338323b892a205c46d598a666f20c Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 18 Aug 2024 23:07:33 -0700 Subject: [PATCH 096/184] Added basic test for literal default qualifier --- .../checker/test/junit/ConfidentialTest.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 checker/src/test/java/org/checkerframework/checker/test/junit/ConfidentialTest.java diff --git a/checker/src/test/java/org/checkerframework/checker/test/junit/ConfidentialTest.java b/checker/src/test/java/org/checkerframework/checker/test/junit/ConfidentialTest.java new file mode 100644 index 00000000000..cb34dfd75e5 --- /dev/null +++ b/checker/src/test/java/org/checkerframework/checker/test/junit/ConfidentialTest.java @@ -0,0 +1,24 @@ +package org.checkerframework.checker.test.junit; + +import java.io.File; +import java.util.List; +import org.checkerframework.checker.confidential.ConfidentialChecker; +import org.checkerframework.framework.test.CheckerFrameworkPerDirectoryTest; +import org.junit.runners.Parameterized.Parameters; + +public class ConfidentialTest extends CheckerFrameworkPerDirectoryTest { + + /** + * Create a ConfidentialTest. + * + * @param testFiles the files containing test code, which will be type-checked + */ + public ConfidentialTest(List testFiles) { + super(testFiles, ConfidentialChecker.class, "confidential"); + } + + @Parameters + public static String[] getTestDirs() { + return new String[] {"confidential", "all-systems"}; + } +} From 42349c3855134a48472a2c90a0d061fc80225036 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 18 Aug 2024 23:41:57 -0700 Subject: [PATCH 097/184] Added basic tests for confidential checker --- .../ConfidentialConcatenation.java | 32 ++++++++ .../confidential/NonConfidentialLiterals.java | 81 +++++++++++++++++++ .../confidential/SimpleConfidential.java | 19 +++++ 3 files changed, 132 insertions(+) create mode 100644 checker/tests/confidential/ConfidentialConcatenation.java create mode 100644 checker/tests/confidential/NonConfidentialLiterals.java create mode 100644 checker/tests/confidential/SimpleConfidential.java diff --git a/checker/tests/confidential/ConfidentialConcatenation.java b/checker/tests/confidential/ConfidentialConcatenation.java new file mode 100644 index 00000000000..141a628d299 --- /dev/null +++ b/checker/tests/confidential/ConfidentialConcatenation.java @@ -0,0 +1,32 @@ +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public class ConfidentialConcatenation { + + void executeNonConfidential(@NonConfidential String s) {} + + void executeConfidential(String s) {} + + void concatenation(@NonConfidential String s1, String s2) { + executeNonConfidential(s1 + s1); + // :: error: (argument) + executeNonConfidential(s1 + s2); + // :: error: (argument) + executeNonConfidential(s2 + s1); + // :: error: (argument) + executeNonConfidential(s2 + s2); + + executeConfidential(s1 + s1); + executeConfidential(s1 + s2); + executeConfidential(s2 + s1); + executeConfidential(s2 + s2); + } + + void compoundConcatenation(@NonConfidential String s1, String s2) { + s1 += s1; + // :: error: (compound.assignment) + s1 += s2; + + s2 += s2; + s2 += s1; + } +} diff --git a/checker/tests/confidential/NonConfidentialLiterals.java b/checker/tests/confidential/NonConfidentialLiterals.java new file mode 100644 index 00000000000..ee920512fef --- /dev/null +++ b/checker/tests/confidential/NonConfidentialLiterals.java @@ -0,0 +1,81 @@ +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public class NonConfidentialLiterals { + + void executeString(@NonConfidential String s) {} + + void confidentialString(String s) {} + + void stringLiteral() { + executeString("asdf"); + confidentialString("asdf"); + executeString("132ijkdsf0wenj va2i3"); + confidentialString("132ijkdsf0wenj va2i3"); + } + + void executeBool(@NonConfidential boolean b) {} + + void confidentialBool(boolean b) {} + + void boolLiteral() { + executeBool(true); + confidentialBool(true); + executeBool(false); + confidentialBool(false); + } + + void executeChar(@NonConfidential char c) {} + + void confidentialChar(char c) {} + + void charLiteral() { + executeChar('f'); + confidentialChar('f'); + executeChar('a'); + confidentialChar('a'); + } + + void executeDouble(@NonConfidential double d) {} + + void confidentialDouble(double d) {} + + void doubleLiteral() { + executeDouble(1.204398); + confidentialDouble(1.204398); + executeDouble(-0.5209384); + confidentialDouble(-0.5209384); + } + + void executeFloat(@NonConfidential float f) {} + + void confidentialFloat(float f) {} + + void floatLiteral() { + executeFloat(198232.412730f); + confidentialFloat(198232.412730f); + executeFloat(-0.10938728f); + confidentialFloat(-0.10938728f); + } + + void executeInt(@NonConfidential int i) {} + + void confidentialInt(int i) {} + + void intLiteral() { + executeInt(20987654); + confidentialInt(20987654); + executeInt(-9598653); + confidentialInt(-9598653); + } + + void executeLong(@NonConfidential long l) {} + + void confidentialLong(long l) {} + + void longLiteral() { + executeLong(20987654l); + confidentialLong(20987654l); + executeLong(-9598653l); + confidentialLong(-9598653l); + } +} diff --git a/checker/tests/confidential/SimpleConfidential.java b/checker/tests/confidential/SimpleConfidential.java new file mode 100644 index 00000000000..7694e7c1a6f --- /dev/null +++ b/checker/tests/confidential/SimpleConfidential.java @@ -0,0 +1,19 @@ +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public class SimpleConfidential { + + void executeNonConfidential(@NonConfidential String s) {} + + void executeConfidential(String s) {} + + void nonConfidentialRef(@NonConfidential String s) { + executeNonConfidential(s); + executeConfidential(s); + } + + void confidentialRef(String s) { + // :: error: (argument) + executeNonConfidential(s); + executeConfidential(s); + } +} From 994352bd8454a4d8f0c382ef34414793bbd3dad4 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 22 Aug 2024 14:03:52 -0700 Subject: [PATCH 098/184] Added stub file for Apache log4j Logger --- .../confidential/ConfidentialChecker.java | 2 + .../checker/confidential/Logger.astub | 1124 +++++++++++++++++ 2 files changed, 1126 insertions(+) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/Logger.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index a66538db1cf..d30e1bb03d4 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -1,6 +1,7 @@ package org.checkerframework.checker.confidential; import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.framework.qual.StubFiles; import org.checkerframework.framework.source.SuppressWarningsPrefix; /** @@ -11,5 +12,6 @@ * * @checker_framework.manual #confidential-checker Confidential Checker */ +@StubFiles({"Logger.astub"}) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/Logger.astub b/checker/src/main/java/org/checkerframework/checker/confidential/Logger.astub new file mode 100644 index 00000000000..1b85cdeeedb --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/Logger.astub @@ -0,0 +1,1124 @@ +package org.apache.logging.log4j; + +import org.apache.logging.log4j.message.EntryMessage; +import org.apache.logging.log4j.message.FlowMessageFactory; +import org.apache.logging.log4j.message.Message; +import org.apache.logging.log4j.message.MessageFactory; +import org.apache.logging.log4j.message.MessageFactory2; +import org.apache.logging.log4j.util.MessageSupplier; +import org.apache.logging.log4j.util.Supplier; + +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public interface Logger { + + void error(@NonConfidential Marker marker, @NonConfidential Message message); + + void error(@NonConfidential Marker marker, @NonConfidential Message message, @NonConfidential Throwable throwable); + + void error(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier); + + void error(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + + void error(@NonConfidential Marker marker, @NonConfidential CharSequence message); + + void error(@NonConfidential Marker marker, @NonConfidential CharSequence message, @NonConfidential Throwable throwable); + + void error(@NonConfidential Marker marker, @NonConfidential Object message); + + void error(@NonConfidential Marker marker, @NonConfidential Object message, @NonConfidential Throwable throwable); + + void error(@NonConfidential Marker marker, @NonConfidential String message); + + void error(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Object... params); + + void error(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + + void error(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Throwable throwable); + + void error(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier); + + void error(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + + void error(@NonConfidential Message message); + + void error(@NonConfidential Message message, @NonConfidential Throwable throwable); + + void error(@NonConfidential MessageSupplier messageSupplier); + + void error(@NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + + void error(@NonConfidential CharSequence message); + + void error(@NonConfidential CharSequence message, @NonConfidential Throwable throwable); + + void error(@NonConfidential Object message); + + void error(@NonConfidential Object message, @NonConfidential Throwable throwable); + + void error(@NonConfidential String message); + + void error(@NonConfidential String message, @NonConfidential Object... params); + + void error(@NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + + void error(@NonConfidential String message, @NonConfidential Throwable throwable); + + void error(@NonConfidential Supplier messageSupplier); + + void error(@NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + + void error(@NonConfidential Marker marker, @NonConfidential String message, Object p0); + + void error(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1); + + void error(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2); + + void error(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + + void error(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + + void error(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + + void error( + @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + + void error( + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7); + + void error( + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8); + + void error( + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8, + Object p9); + + void error(@NonConfidential String message, Object p0); + + void error(@NonConfidential String message, Object p0, Object p1); + + void error(@NonConfidential String message, Object p0, Object p1, Object p2); + + void error(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + + void error(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + + void error(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + + void error(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + + void error(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7); + + void error( + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8); + + void error( + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8, + Object p9); + + void info(@NonConfidential Marker marker, @NonConfidential Message message); + + void info(@NonConfidential Marker marker, @NonConfidential Message message, @NonConfidential Throwable throwable); + + void info(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier); + + void info(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + + void info(@NonConfidential Marker marker, @NonConfidential CharSequence message); + + void info(@NonConfidential Marker marker, @NonConfidential CharSequence message, @NonConfidential Throwable throwable); + + void info(@NonConfidential Marker marker, @NonConfidential Object message); + + void info(@NonConfidential Marker marker, @NonConfidential Object message, @NonConfidential Throwable throwable); + + void info(@NonConfidential Marker marker, @NonConfidential String message); + + void info(@NonConfidential Marker marker, @NonConfidential String message, Object... params); + + void info(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + + void info(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Throwable throwable); + + void info(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier); + + void info(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + + void info(@NonConfidential Message message); + + void info(@NonConfidential Message message, @NonConfidential Throwable throwable); + + void info(@NonConfidential MessageSupplier messageSupplier); + + void info(@NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + + void info(@NonConfidential CharSequence message); + + void info(@NonConfidential CharSequence message, @NonConfidential Throwable throwable); + + void info(@NonConfidential Object message); + + void info(@NonConfidential Object message, @NonConfidential Throwable throwable); + + void info(@NonConfidential String message); + + void info(@NonConfidential String message, Object... params); + + void info(@NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + + void info(@NonConfidential String message, @NonConfidential Throwable throwable); + + void info(@NonConfidential Supplier messageSupplier); + + void info(@NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + + void info(@NonConfidential Marker marker, @NonConfidential String message, Object p0); + + void info(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1); + + void info(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2); + + void info(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + + void info(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + + void info(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + + void info( + @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + + void info( + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7); + + void info( + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8); + + void info( + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8, + Object p9); + + void info(@NonConfidential String message, Object p0); + + void info(@NonConfidential String message, Object p0, Object p1); + + void info(@NonConfidential String message, Object p0, Object p1, Object p2); + + void info(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + + void info(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + + void info(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + + void info(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + + void info(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7); + + void info( + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8); + + void info( + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8, + Object p9); + + void catching(Level level, @NonConfidential Throwable throwable); + + void catching(@NonConfidential Throwable throwable); + + void debug(@NonConfidential Marker marker, @NonConfidential Message message); + + void debug(@NonConfidential Marker marker, @NonConfidential Message message, @NonConfidential Throwable throwable); + + void debug(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier); + + void debug(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + + void debug(@NonConfidential Marker marker, @NonConfidential CharSequence message); + + void debug(@NonConfidential Marker marker, @NonConfidential CharSequence message, @NonConfidential Throwable throwable); + + void debug(@NonConfidential Marker marker, @NonConfidential Object message); + + void debug(@NonConfidential Marker marker, @NonConfidential Object message, @NonConfidential Throwable throwable); + + void debug(@NonConfidential Marker marker, @NonConfidential String message); + + void debug(@NonConfidential Marker marker, @NonConfidential String message, Object... params); + + void debug(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + + void debug(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Throwable throwable); + + void debug(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier); + + void debug(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + + void debug(@NonConfidential Message message); + + void debug(@NonConfidential Message message, @NonConfidential Throwable throwable); + + void debug(@NonConfidential MessageSupplier messageSupplier); + + void debug(@NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + + void debug(@NonConfidential CharSequence message); + + void debug(@NonConfidential CharSequence message, @NonConfidential Throwable throwable); + + void debug(@NonConfidential Object message); + + void debug(@NonConfidential Object message, @NonConfidential Throwable throwable); + + void debug(@NonConfidential String message); + + void debug(@NonConfidential String message, Object... params); + + void debug(@NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + + void debug(@NonConfidential String message, @NonConfidential Throwable throwable); + + void debug(@NonConfidential Supplier messageSupplier); + + void debug(@NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + + void debug(@NonConfidential Marker marker, @NonConfidential String message, Object p0); + + void debug(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1); + + void debug(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2); + + void debug(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + + void debug(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + + void debug(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + + void debug( + @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + + void debug( + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7); + + void debug( + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8); + + void debug( + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8, + Object p9); + + void debug(@NonConfidential String message, Object p0); + + void debug(@NonConfidential String message, Object p0, Object p1); + + void debug(@NonConfidential String message, Object p0, Object p1, Object p2); + + void debug(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + + void debug(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + + void debug(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + + void debug(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + + void debug(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7); + + void debug( + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8); + + void debug( + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8, + Object p9); + + void fatal(@NonConfidential Marker marker, @NonConfidential Message message); + + void fatal(@NonConfidential Marker marker, @NonConfidential Message message, @NonConfidential Throwable throwable); + + void fatal(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier); + + void fatal(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + + void fatal(@NonConfidential Marker marker, @NonConfidential CharSequence message); + + void fatal(@NonConfidential Marker marker, @NonConfidential CharSequence message, @NonConfidential Throwable throwable); + + void fatal(@NonConfidential Marker marker, @NonConfidential Object message); + + void fatal(@NonConfidential Marker marker, @NonConfidential Object message, @NonConfidential Throwable throwable); + + void fatal(@NonConfidential Marker marker, @NonConfidential String message); + + void fatal(@NonConfidential Marker marker, @NonConfidential String message, Object... params); + + void fatal(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + + void fatal(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Throwable throwable); + + void fatal(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier); + + void fatal(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + + void fatal(@NonConfidential Message message); + + void fatal(@NonConfidential Message message, @NonConfidential Throwable throwable); + + void fatal(@NonConfidential MessageSupplier messageSupplier); + + void fatal(@NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + + void fatal(@NonConfidential CharSequence message); + + void fatal(@NonConfidential CharSequence message, @NonConfidential Throwable throwable); + + void fatal(@NonConfidential Object message); + + void fatal(@NonConfidential Object message, @NonConfidential Throwable throwable); + + void fatal(@NonConfidential String message); + + void fatal(@NonConfidential String message, Object... params); + + void fatal(@NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + + void fatal(@NonConfidential String message, @NonConfidential Throwable throwable); + + void fatal(@NonConfidential Supplier messageSupplier); + + void fatal(@NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + + void fatal(@NonConfidential Marker marker, @NonConfidential String message, Object p0); + + void fatal(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1); + + void fatal(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2); + + void fatal(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + + void fatal(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + + void fatal(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + + void fatal( + @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + + void fatal( + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7); + + void fatal( + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8); + + void fatal( + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8, + Object p9); + + void fatal(@NonConfidential String message, Object p0); + + void fatal(@NonConfidential String message, Object p0, Object p1); + + void fatal(@NonConfidential String message, Object p0, Object p1, Object p2); + + void fatal(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + + void fatal(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + + void fatal(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + + void fatal(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + + void fatal(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7); + + void fatal( + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8); + + void fatal( + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8, + Object p9); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential Message message); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential Message message, @NonConfidential Throwable throwable); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential CharSequence message); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential CharSequence message, @NonConfidential Throwable throwable); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential Object message); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential Object message, @NonConfidential Throwable throwable); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential String message); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential String message, Object... params); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Throwable throwable); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential Supplier messageSupplier); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + + void log(Level level, @NonConfidential Message message); + + void log(Level level, @NonConfidential Message message, @NonConfidential Throwable throwable); + + void log(Level level, @NonConfidential MessageSupplier messageSupplier); + + void log(Level level, @NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + + void log(Level level, @NonConfidential CharSequence message); + + void log(Level level, @NonConfidential CharSequence message, @NonConfidential Throwable throwable); + + void log(Level level, @NonConfidential Object message); + + void log(Level level, @NonConfidential Object message, @NonConfidential Throwable throwable); + + void log(Level level, @NonConfidential String message); + + void log(Level level, @NonConfidential String message, Object... params); + + void log(Level level, @NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + + void log(Level level, @NonConfidential String message, @NonConfidential Throwable throwable); + + void log(Level level, @NonConfidential Supplier messageSupplier); + + void log(Level level, @NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential String message, Object p0); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + + void log(Level level, @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + + void log( + Level level, + Marker marker, + String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5); + + void log( + Level level, + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6); + + void log( + Level level, + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7); + + void log( + Level level, + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8); + + void log( + Level level, + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8, + Object p9); + + void log(Level level, @NonConfidential String message, Object p0); + + void log(Level level, @NonConfidential String message, Object p0, Object p1); + + void log(Level level, @NonConfidential String message, Object p0, Object p1, Object p2); + + void log(Level level, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + + void log(Level level, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + + void log(Level level, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + + void log(Level level, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + + void log( + Level level, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7); + + void log( + Level level, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8); + + void log( + Level level, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8, + Object p9); + + default void logMessage( + final Level level, + final @NonConfidential Marker marker, + final @NonConfidential String fqcn, + final @NonConfidential StackTraceElement location, + final @NonConfidential Message message, + final @NonConfidential Throwable throwable); + + void printf(Level level, @NonConfidential Marker marker, @NonConfidential String format, Object... params); + + void printf(Level level, @NonConfidential String format, Object... params); + + void trace(@NonConfidential Marker marker, @NonConfidential Message message); + + void trace(@NonConfidential Marker marker, @NonConfidential Message message, @NonConfidential Throwable throwable); + + void trace(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier); + + void trace(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + + void trace(@NonConfidential Marker marker, @NonConfidential CharSequence message); + + void trace(@NonConfidential Marker marker, @NonConfidential CharSequence message, @NonConfidential Throwable throwable); + + void trace(@NonConfidential Marker marker, @NonConfidential Object message); + + void trace(@NonConfidential Marker marker, @NonConfidential Object message, @NonConfidential Throwable throwable); + + void trace(@NonConfidential Marker marker, @NonConfidential String message); + + void trace(@NonConfidential Marker marker, @NonConfidential String message, Object... params); + + void trace(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + + void trace(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Throwable throwable); + + void trace(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier); + + void trace(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + + void trace(@NonConfidential Message message); + + void trace(@NonConfidential Message message, @NonConfidential Throwable throwable); + + void trace(@NonConfidential MessageSupplier messageSupplier); + + void trace(@NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + + void trace(@NonConfidential CharSequence message); + + void trace(@NonConfidential CharSequence message, @NonConfidential Throwable throwable); + + void trace(@NonConfidential Object message); + + void trace(@NonConfidential Object message, @NonConfidential Throwable throwable); + + void trace(@NonConfidential String message); + + void trace(@NonConfidential String message, Object... params); + + void trace(@NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + + void trace(@NonConfidential String message, @NonConfidential Throwable throwable); + + void trace(@NonConfidential Supplier messageSupplier); + + void trace(@NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + + void trace(@NonConfidential Marker marker, @NonConfidential String message, Object p0); + + void trace(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1); + + void trace(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2); + + void trace(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + + void trace(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + + void trace(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + + void trace( + @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + + void trace( + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7); + + void trace( + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8); + + void trace( + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8, + Object p9); + + void trace(@NonConfidential String message, Object p0); + + void trace(@NonConfidential String message, Object p0, Object p1); + + void trace(@NonConfidential String message, Object p0, Object p1, Object p2); + + void trace(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + + void trace(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + + void trace(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + + void trace(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + + void trace(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7); + + void trace( + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8); + + void trace( + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8, + Object p9); + + void warn(@NonConfidential Marker marker, @NonConfidential Message message); + + void warn(@NonConfidential Marker marker, @NonConfidential Message message, @NonConfidential Throwable throwable); + + void warn(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier); + + void warn(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + + void warn(@NonConfidential Marker marker, @NonConfidential CharSequence message); + + void warn(@NonConfidential Marker marker, @NonConfidential CharSequence message, @NonConfidential Throwable throwable); + + void warn(@NonConfidential Marker marker, @NonConfidential Object message); + + void warn(@NonConfidential Marker marker, @NonConfidential Object message, @NonConfidential Throwable throwable); + + void warn(@NonConfidential Marker marker, @NonConfidential String message); + + void warn(@NonConfidential Marker marker, @NonConfidential String message, Object... params); + + void warn(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + + void warn(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Throwable throwable); + + void warn(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier); + + void warn(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + + void warn(@NonConfidential Message message); + + void warn(@NonConfidential Message message, @NonConfidential Throwable throwable); + + void warn(@NonConfidential MessageSupplier messageSupplier); + + void warn(@NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + + void warn(@NonConfidential CharSequence message); + + void warn(@NonConfidential CharSequence message, @NonConfidential Throwable throwable); + + void warn(@NonConfidential Object message); + + void warn(@NonConfidential Object message, @NonConfidential Throwable throwable); + + void warn(@NonConfidential String message); + + void warn(@NonConfidential String message, Object... params); + + void warn(@NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + + void warn(@NonConfidential String message, @NonConfidential Throwable throwable); + + void warn(@NonConfidential Supplier messageSupplier); + + void warn(@NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + + void warn(@NonConfidential Marker marker, @NonConfidential String message, Object p0); + + void warn(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1); + + void warn(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2); + + void warn(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + + void warn(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + + void warn(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + + void warn( + @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + + void warn( + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7); + + void warn( + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8); + + void warn( + @NonConfidential Marker marker, + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8, + Object p9); + + void warn(@NonConfidential String message, Object p0); + + void warn(@NonConfidential String message, Object p0, Object p1); + + void warn(@NonConfidential String message, Object p0, Object p1, Object p2); + + void warn(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + + void warn(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + + void warn(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + + void warn(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + + void warn(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7); + + void warn( + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8); + + void warn( + @NonConfidential String message, + Object p0, + Object p1, + Object p2, + Object p3, + Object p4, + Object p5, + Object p6, + Object p7, + Object p8, + Object p9); + + T throwing(Level level, @NonConfidential T throwable); + + T throwing(@NonConfidential T throwable); +} From 723486abcf012fd0cc99929717aab239c5709fdd Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 22 Aug 2024 14:21:26 -0700 Subject: [PATCH 099/184] Added stub file for Android Log --- .../confidential/ConfidentialChecker.java | 2 +- .../checker/confidential/Log.astub | 44 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/Log.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index d30e1bb03d4..0dc7d8d6f72 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -12,6 +12,6 @@ * * @checker_framework.manual #confidential-checker Confidential Checker */ -@StubFiles({"Logger.astub"}) +@StubFiles({"Logger.astub", "Log.astub"}) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/Log.astub b/checker/src/main/java/org/checkerframework/checker/confidential/Log.astub new file mode 100644 index 00000000000..afbe2c27478 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/Log.astub @@ -0,0 +1,44 @@ +package android.util; +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.compat.annotation.UnsupportedAppUsage; +import android.os.DeadSystemException; +import com.android.internal.os.RuntimeInit; +import com.android.internal.util.FastPrintWriter; +import com.android.internal.util.LineBreakBufferedWriter; +import dalvik.annotation.optimization.FastNative; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.net.UnknownHostException; + +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public final class Log { + + public static int d(@Nullable @NonConfidential String tag, @NonNull @NonConfidential String msg); + + public static int d(@Nullable @NonConfidential String tag, @Nullable @NonConfidential String msg, @Nullable @NonConfidential Throwable tr); + + public static int w(@Nullable @NonConfidential String tag, @NonNull @NonConfidential String msg); + + public static int w(@Nullable @NonConfidential String tag, @Nullable @NonConfidential String msg, @Nullable @NonConfidential Throwable tr); + + public static int w(@Nullable @NonConfidential String tag, @Nullable @NonConfidential Throwable tr); + + public static int v(@Nullable @NonConfidential String tag, @NonNull @NonConfidential String msg); + + public static int v(@Nullable @NonConfidential String tag, @Nullable @NonConfidential String msg, @Nullable @NonConfidential Throwable tr); + + public static int i(@Nullable @NonConfidential String tag, @NonNull @NonConfidential String msg); + + public static int i(@Nullable @NonConfidential String tag, @Nullable @NonConfidential String msg, @Nullable @NonConfidential Throwable tr); + + public static int e(@Nullable @NonConfidential String tag, @NonNull @NonConfidential String msg); + + public static int e(@Nullable @NonConfidential String tag, @Nullable @NonConfidential String msg, @Nullable @NonConfidential Throwable tr); +} From 03ae9ee46cde8f15d064c4d4bf4f38bcfb178b52 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Fri, 23 Aug 2024 13:02:48 -0700 Subject: [PATCH 100/184] Renamed Apache logger to avoid overlapping file names --- .../checker/confidential/ConfidentialChecker.java | 2 +- .../checker/confidential/{Logger.astub => Log4jLogger.astub} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename checker/src/main/java/org/checkerframework/checker/confidential/{Logger.astub => Log4jLogger.astub} (100%) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 0dc7d8d6f72..26614298615 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -12,6 +12,6 @@ * * @checker_framework.manual #confidential-checker Confidential Checker */ -@StubFiles({"Logger.astub", "Log.astub"}) +@StubFiles({"Log4jLogger.astub", "Log.astub"}) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/Logger.astub b/checker/src/main/java/org/checkerframework/checker/confidential/Log4jLogger.astub similarity index 100% rename from checker/src/main/java/org/checkerframework/checker/confidential/Logger.astub rename to checker/src/main/java/org/checkerframework/checker/confidential/Log4jLogger.astub From 3490306acf97e5443e545c4a07b53c4a493be8c5 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Fri, 23 Aug 2024 13:19:46 -0700 Subject: [PATCH 101/184] Added slf4j Logger --- .../confidential/ConfidentialChecker.java | 2 +- .../checker/confidential/Slf4jLogger.astub | 123 ++++++++++++++++++ 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/Slf4jLogger.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 26614298615..9d107ffe8e2 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -12,6 +12,6 @@ * * @checker_framework.manual #confidential-checker Confidential Checker */ -@StubFiles({"Log4jLogger.astub", "Log.astub"}) +@StubFiles({"Log4jLogger.astub", "Log.astub", "Slf4jLogger.astub"}) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/Slf4jLogger.astub b/checker/src/main/java/org/checkerframework/checker/confidential/Slf4jLogger.astub new file mode 100644 index 00000000000..d7b49ae5a56 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/Slf4jLogger.astub @@ -0,0 +1,123 @@ +package org.slf4j; + +import static org.slf4j.event.EventConstants.DEBUG_INT; +import static org.slf4j.event.EventConstants.ERROR_INT; +import static org.slf4j.event.EventConstants.INFO_INT; +import static org.slf4j.event.EventConstants.TRACE_INT; +import static org.slf4j.event.EventConstants.WARN_INT; +import static org.slf4j.event.Level.DEBUG; +import static org.slf4j.event.Level.ERROR; +import static org.slf4j.event.Level.INFO; +import static org.slf4j.event.Level.TRACE; +import static org.slf4j.event.Level.WARN; + +import org.slf4j.event.Level; +import org.slf4j.helpers.CheckReturnValue; +import org.slf4j.spi.DefaultLoggingEventBuilder; +import org.slf4j.spi.LoggingEventBuilder; +import org.slf4j.spi.NOPLoggingEventBuilder; + +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public interface Logger { + + public void error(@NonConfidential String msg); + + public void error(@NonConfidential String format, Object arg); + + public void error(@NonConfidential String format, Object arg1, Object arg2); + + public void error(@NonConfidential String format, Object... arguments); + + public void error(@NonConfidential String msg, @NonConfidential Throwable t); + + public void error(@NonConfidential Marker marker, @NonConfidential String msg); + + public void error(@NonConfidential Marker marker, @NonConfidential String format, Object arg); + + public void error(@NonConfidential Marker marker, @NonConfidential String format, Object arg1, Object arg2); + + public void error(@NonConfidential Marker marker, @NonConfidential String format, Object... arguments); + + public void error(@NonConfidential Marker marker, @NonConfidential String msg, @NonConfidential Throwable t); + + public void info(@NonConfidential String msg); + + public void info(@NonConfidential String format, Object arg); + + public void info(@NonConfidential String format, Object arg1, Object arg2); + + public void info(@NonConfidential String format, Object... arguments); + + public void info(@NonConfidential String msg, @NonConfidential Throwable t); + + public void info(@NonConfidential Marker marker, @NonConfidential String msg); + + public void info(@NonConfidential Marker marker, @NonConfidential String format, Object arg); + + public void info(@NonConfidential Marker marker, @NonConfidential String format, Object arg1, Object arg2); + + public void info(@NonConfidential Marker marker, @NonConfidential String format, Object... arguments); + + public void info(@NonConfidential Marker marker, @NonConfidential String msg, @NonConfidential Throwable t); + + public void debug(@NonConfidential String msg); + + public void debug(@NonConfidential String format, Object arg); + + public void debug(@NonConfidential String format, Object arg1, Object arg2); + + public void debug(@NonConfidential String format, Object... arguments); + + public void debug(@NonConfidential String msg, @NonConfidential Throwable t); + + public void debug(@NonConfidential Marker marker, @NonConfidential String msg); + + public void debug(@NonConfidential Marker marker, @NonConfidential String format, Object arg); + + public void debug(@NonConfidential Marker marker, @NonConfidential String format, Object arg1, Object arg2); + + public void debug(@NonConfidential Marker marker, @NonConfidential String format, Object... arguments); + + public void debug(@NonConfidential Marker marker, @NonConfidential String msg, @NonConfidential Throwable t); + + public void trace(@NonConfidential String msg); + + public void trace(@NonConfidential String format, Object arg); + + public void trace(@NonConfidential String format, Object arg1, Object arg2); + + public void trace(@NonConfidential String format, Object... arguments); + + public void trace(@NonConfidential String msg, @NonConfidential Throwable t); + + public void trace(@NonConfidential Marker marker, @NonConfidential String msg); + + public void trace(@NonConfidential Marker marker, @NonConfidential String format, Object arg); + + public void trace(@NonConfidential Marker marker, @NonConfidential String format, Object arg1, Object arg2); + + public void trace(@NonConfidential Marker marker, @NonConfidential String format, Object... argArray); + + public void trace(@NonConfidential Marker marker, @NonConfidential String msg, @NonConfidential Throwable t); + + public void warn(@NonConfidential String msg); + + public void warn(@NonConfidential String format, Object arg); + + public void warn(@NonConfidential String format, Object... arguments); + + public void warn(@NonConfidential String format, Object arg1, Object arg2); + + public void warn(@NonConfidential String msg, @NonConfidential Throwable t); + + public void warn(@NonConfidential Marker marker, @NonConfidential String msg); + + public void warn(@NonConfidential Marker marker, @NonConfidential String format, Object arg); + + public void warn(@NonConfidential Marker marker, @NonConfidential String format, Object arg1, Object arg2); + + public void warn(@NonConfidential Marker marker, @NonConfidential String format, Object... arguments); + + public void warn(@NonConfidential Marker marker, @NonConfidential String msg, @NonConfidential Throwable t); +} From 8c214affedb844e6da1dd623b0c1301f29d4a9ea Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Fri, 23 Aug 2024 13:34:46 -0700 Subject: [PATCH 102/184] Added java.util.logging.Handler stub file --- .../confidential/ConfidentialChecker.java | 2 +- .../checker/confidential/Handler.astub | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/Handler.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 9d107ffe8e2..11486e5dd95 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -12,6 +12,6 @@ * * @checker_framework.manual #confidential-checker Confidential Checker */ -@StubFiles({"Log4jLogger.astub", "Log.astub", "Slf4jLogger.astub"}) +@StubFiles({"Log4jLogger.astub", "Log.astub", "Slf4jLogger.astub", "Handler.astub"}) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/Handler.astub b/checker/src/main/java/org/checkerframework/checker/confidential/Handler.astub new file mode 100644 index 00000000000..a81d2af6d0a --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/Handler.astub @@ -0,0 +1,16 @@ +package java.util.logging; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Objects; + +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public abstract class Handler { + + public abstract void publish(@NonConfidential LogRecord var1); +} From 2ceb141aa0d9225fbceaa9097f7e6b7aa319d5b9 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Fri, 23 Aug 2024 13:48:50 -0700 Subject: [PATCH 103/184] Added java.util.logging.Logger stub file --- .../confidential/ConfidentialChecker.java | 8 +- .../checker/confidential/JavaLogger.astub | 85 +++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/JavaLogger.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 11486e5dd95..ab48a6861f0 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -12,6 +12,12 @@ * * @checker_framework.manual #confidential-checker Confidential Checker */ -@StubFiles({"Log4jLogger.astub", "Log.astub", "Slf4jLogger.astub", "Handler.astub"}) +@StubFiles({ + "Log4jLogger.astub", + "Log.astub", + "Slf4jLogger.astub", + "Handler.astub", + "JavaLogger.astub" +}) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/JavaLogger.astub b/checker/src/main/java/org/checkerframework/checker/confidential/JavaLogger.astub new file mode 100644 index 00000000000..1027520f048 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/JavaLogger.astub @@ -0,0 +1,85 @@ +package java.util.logging; + +import java.lang.ref.WeakReference; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.Objects; +import java.util.ResourceBundle; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Supplier; +import jdk.internal.logger.DefaultLoggerFinder; +import jdk.internal.misc.JavaUtilResourceBundleAccess; +import jdk.internal.misc.SharedSecrets; +import jdk.internal.reflect.CallerSensitive; +import jdk.internal.reflect.Reflection; + +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public class Logger { + + public void config(@NonConfidential String msg); + + public void config(@NonConfidential Supplier msgSupplier); + + public void fine(@NonConfidential String msg); + + public void fine(@NonConfidential Supplier msgSupplier); + + public void finer(@NonConfidential String msg); + + public void finer(@NonConfidential Supplier msgSupplier); + + public void finest(@NonConfidential String msg); + + public void finest(@NonConfidential Supplier msgSupplier); + + public void info(@NonConfidential String msg); + + public void info(@NonConfidential Supplier msgSupplier); + + public void log(@NonConfidential LogRecord record); + + public void log(Level level, @NonConfidential String msg); + + public void log(Level level, @NonConfidential Supplier msgSupplier); + + public void log(Level level, @NonConfidential String msg, Object param1); + + public void log(Level level, @NonConfidential String msg, Object[] params); + + public void log(Level level, @NonConfidential String msg, @NonConfidential Throwable thrown); + + public void log(Level level, @NonConfidential Throwable thrown, @NonConfidential Supplier msgSupplier); + + public void logp(Level level, @NonConfidential String sourceClass, @NonConfidential String sourceMethod, @NonConfidential String msg); + + public void logp(Level level, @NonConfidential String sourceClass, @NonConfidential String sourceMethod, @NonConfidential Supplier msgSupplier); + + public void logp(Level level, @NonConfidential String sourceClass, @NonConfidential String sourceMethod, @NonConfidential String msg, Object param1); + + public void logp(Level level, @NonConfidential String sourceClass, @NonConfidential String sourceMethod, @NonConfidential String msg, Object[] params); + + public void logp(Level level, @NonConfidential String sourceClass, @NonConfidential String sourceMethod, @NonConfidential String msg, @NonConfidential Throwable thrown); + + public void logp(Level level, @NonConfidential String sourceClass, @NonConfidential String sourceMethod, @NonConfidential Throwable thrown, @NonConfidential Supplier msgSupplier); + + public void logrb(Level level, @NonConfidential String sourceClass, @NonConfidential String sourceMethod, ResourceBundle bundle, @NonConfidential String msg, Object... params); + + public void logrb(Level level, ResourceBundle bundle, @NonConfidential String msg, Object... params); + + public void logrb(Level level, @NonConfidential String sourceClass, @NonConfidential String sourceMethod, ResourceBundle bundle, @NonConfidential String msg, @NonConfidential Throwable thrown); + + public void logrb(Level level, ResourceBundle bundle, @NonConfidential String msg, @NonConfidential Throwable thrown); + + public void severe(@NonConfidential String msg); + + public void severe(@NonConfidential Supplier msgSupplier); + + public void warning(@NonConfidential String msg); + + public void warning(@NonConfidential Supplier msgSupplier); +} From 09417b82c7a65828f73ebcad50d14df496162ca6 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Fri, 23 Aug 2024 13:52:50 -0700 Subject: [PATCH 104/184] Added java.util.logging.Formatter stub file --- .../checker/confidential/ConfidentialChecker.java | 3 ++- .../checker/confidential/Formatter.astub | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/Formatter.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index ab48a6861f0..76a4ea8fafc 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -17,7 +17,8 @@ "Log.astub", "Slf4jLogger.astub", "Handler.astub", - "JavaLogger.astub" + "JavaLogger.astub", + "Formatter.astub" }) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/Formatter.astub b/checker/src/main/java/org/checkerframework/checker/confidential/Formatter.astub new file mode 100644 index 00000000000..cfb0ceaff96 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/Formatter.astub @@ -0,0 +1,12 @@ +package java.util.logging; + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public abstract class Formatter { + + public abstract String format(@NonConfidential LogRecord var1); +} From 653706be1d2deb83bef4c85250544d12d79c5f6c Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 25 Aug 2024 12:49:10 -0700 Subject: [PATCH 105/184] Renamed Android Log astub to avoid ambiguity --- .../checker/confidential/{Log.astub => AndroidLog.astub} | 0 .../checker/confidential/ConfidentialChecker.java | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename checker/src/main/java/org/checkerframework/checker/confidential/{Log.astub => AndroidLog.astub} (100%) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/Log.astub b/checker/src/main/java/org/checkerframework/checker/confidential/AndroidLog.astub similarity index 100% rename from checker/src/main/java/org/checkerframework/checker/confidential/Log.astub rename to checker/src/main/java/org/checkerframework/checker/confidential/AndroidLog.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 76a4ea8fafc..ec8a62f4935 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -14,7 +14,7 @@ */ @StubFiles({ "Log4jLogger.astub", - "Log.astub", + "AndroidLog.astub", "Slf4jLogger.astub", "Handler.astub", "JavaLogger.astub", From 14d843515c1cb30a4272265e9b7eb9c9c17b174e Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 25 Aug 2024 12:52:26 -0700 Subject: [PATCH 106/184] Added Apache commons Log stub file --- .../checker/confidential/ApacheLog.astub | 30 +++++++++++++++++++ .../confidential/ConfidentialChecker.java | 3 +- 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/ApacheLog.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ApacheLog.astub b/checker/src/main/java/org/checkerframework/checker/confidential/ApacheLog.astub new file mode 100644 index 00000000000..cdfb443e45b --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ApacheLog.astub @@ -0,0 +1,30 @@ +package org.apache.commons.logging; + +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public interface Log { + + void debug(@NonConfidential Object var1); + + void debug(@NonConfidential Object var1, @NonConfidential Throwable var2); + + void error(@NonConfidential Object var1); + + void error(@NonConfidential Object var1, @NonConfidential Throwable var2); + + void fatal(@NonConfidential Object var1); + + void fatal(@NonConfidential Object var1, @NonConfidential Throwable var2); + + void info(@NonConfidential Object var1); + + void info(@NonConfidential Object var1, @NonConfidential Throwable var2); + + void trace(@NonConfidential Object var1); + + void trace(@NonConfidential Object var1, @NonConfidential Throwable var2); + + void warn(@NonConfidential Object var1); + + void warn(@NonConfidential Object var1, @NonConfidential Throwable var2); +} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index ec8a62f4935..4a58616a5ee 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -18,7 +18,8 @@ "Slf4jLogger.astub", "Handler.astub", "JavaLogger.astub", - "Formatter.astub" + "Formatter.astub", + "ApacheLog.astub" }) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker {} From 583a4a46e2d55cae1c54609010fda5acc0c46840 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 25 Aug 2024 13:03:33 -0700 Subject: [PATCH 107/184] Added Android Toast stub file --- .../confidential/ConfidentialChecker.java | 3 +- .../checker/confidential/Toast.astub | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/Toast.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 4a58616a5ee..533ddf52d09 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -19,7 +19,8 @@ "Handler.astub", "JavaLogger.astub", "Formatter.astub", - "ApacheLog.astub" + "ApacheLog.astub", + "Toast.astub" }) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/Toast.astub b/checker/src/main/java/org/checkerframework/checker/confidential/Toast.astub new file mode 100644 index 00000000000..0007069f21f --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/Toast.astub @@ -0,0 +1,32 @@ +package android.widget; +import android.annotation.IntDef; +import android.annotation.StringRes; +import android.app.INotificationManager; +import android.app.ITransientNotification; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.graphics.PixelFormat; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public class Toast { + + public static Toast makeText(Context context, @NonConfidential CharSequence text, @Duration int duration); + + public void setText(@NonConfidential CharSequence s); +} From 6c2a4b4d5727c5ed8adda70f968134d7555f8769 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 25 Aug 2024 13:09:51 -0700 Subject: [PATCH 108/184] Added Android TextView stub file --- .../confidential/ConfidentialChecker.java | 3 +- .../checker/confidential/TextView.astub | 150 ++++++++++++++++++ 2 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/TextView.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 533ddf52d09..00213c26236 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -20,7 +20,8 @@ "JavaLogger.astub", "Formatter.astub", "ApacheLog.astub", - "Toast.astub" + "Toast.astub", + "TextView.astub" }) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/TextView.astub b/checker/src/main/java/org/checkerframework/checker/confidential/TextView.astub new file mode 100644 index 00000000000..a645830ac83 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/TextView.astub @@ -0,0 +1,150 @@ +package android.widget; +import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; +import android.R; +import android.annotation.ColorInt; +import android.annotation.DrawableRes; +import android.annotation.FloatRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.Size; +import android.annotation.StringRes; +import android.annotation.StyleRes; +import android.annotation.XmlRes; +import android.app.Activity; +import android.app.assist.AssistStructure; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.content.Intent; +import android.content.UndoManager; +import android.content.res.ColorStateList; +import android.content.res.CompatibilityInfo; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.graphics.Canvas; +import android.graphics.Insets; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.LocaleList; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.ParcelableParcel; +import android.os.SystemClock; +import android.os.UserHandle; +import android.provider.Settings; +import android.text.BoringLayout; +import android.text.DynamicLayout; +import android.text.Editable; +import android.text.GetChars; +import android.text.GraphicsOperations; +import android.text.InputFilter; +import android.text.InputType; +import android.text.Layout; +import android.text.ParcelableSpan; +import android.text.Selection; +import android.text.SpanWatcher; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.SpannedString; +import android.text.StaticLayout; +import android.text.TextDirectionHeuristic; +import android.text.TextDirectionHeuristics; +import android.text.TextPaint; +import android.text.TextUtils; +import android.text.TextUtils.TruncateAt; +import android.text.TextWatcher; +import android.text.method.AllCapsTransformationMethod; +import android.text.method.ArrowKeyMovementMethod; +import android.text.method.DateKeyListener; +import android.text.method.DateTimeKeyListener; +import android.text.method.DialerKeyListener; +import android.text.method.DigitsKeyListener; +import android.text.method.KeyListener; +import android.text.method.LinkMovementMethod; +import android.text.method.MetaKeyKeyListener; +import android.text.method.MovementMethod; +import android.text.method.PasswordTransformationMethod; +import android.text.method.SingleLineTransformationMethod; +import android.text.method.TextKeyListener; +import android.text.method.TimeKeyListener; +import android.text.method.TransformationMethod; +import android.text.method.TransformationMethod2; +import android.text.method.WordIterator; +import android.text.style.CharacterStyle; +import android.text.style.ClickableSpan; +import android.text.style.ParagraphStyle; +import android.text.style.SpellCheckSpan; +import android.text.style.SuggestionSpan; +import android.text.style.URLSpan; +import android.text.style.UpdateAppearance; +import android.text.util.Linkify; +import android.util.AttributeSet; +import android.util.Log; +import android.util.TypedValue; +import android.view.AccessibilityIterators.TextSegmentIterator; +import android.view.ActionMode; +import android.view.Choreographer; +import android.view.ContextMenu; +import android.view.DragEvent; +import android.view.Gravity; +import android.view.HapticFeedbackConstants; +import android.view.KeyCharacterMap; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.PointerIcon; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewDebug; +import android.view.ViewGroup.LayoutParams; +import android.view.ViewHierarchyEncoder; +import android.view.ViewParent; +import android.view.ViewRootImpl; +import android.view.ViewStructure; +import android.view.ViewTreeObserver; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityNodeInfo; +import android.view.animation.AnimationUtils; +import android.view.inputmethod.BaseInputConnection; +import android.view.inputmethod.CompletionInfo; +import android.view.inputmethod.CorrectionInfo; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.ExtractedText; +import android.view.inputmethod.ExtractedTextRequest; +import android.view.inputmethod.InputConnection; +import android.view.inputmethod.InputMethodManager; +import android.view.textservice.SpellCheckerSubtype; +import android.view.textservice.TextServicesManager; +import android.widget.RemoteViews.RemoteView; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.FastMath; +import com.android.internal.widget.EditableInputConnection; +import org.xmlpull.v1.XmlPullParserException; +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Locale; + +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public class TextView extends View implements ViewTreeObserver.OnPreDrawListener { + + public final void setText(@NonConfidential CharSequence text); + + public void setText(@NonConfidential CharSequence text, BufferType type); + + private void setText(@NonConfidential CharSequence text, BufferType type, boolean notifyBefore, int oldlen); + + public final void setText(@NonConfidential char[] text, int start, int len); +} From f1fd797599738368dbc315dce4c1f73ce33c07bf Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 26 Aug 2024 13:43:44 -0700 Subject: [PATCH 109/184] Edited Android TextView stub file --- .../org/checkerframework/checker/confidential/TextView.astub | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/TextView.astub b/checker/src/main/java/org/checkerframework/checker/confidential/TextView.astub index a645830ac83..e8f68a4bae0 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/TextView.astub +++ b/checker/src/main/java/org/checkerframework/checker/confidential/TextView.astub @@ -147,4 +147,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private void setText(@NonConfidential CharSequence text, BufferType type, boolean notifyBefore, int oldlen); public final void setText(@NonConfidential char[] text, int start, int len); + + public void setError(@NonConfidential CharSequence error); + + public void setError(@NonConfidential CharSequence error, Drawable icon); } From 49e80fd648fec7afaccc01fc0a8152bc3780a398 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 26 Aug 2024 14:10:11 -0700 Subject: [PATCH 110/184] Added Android AlertDialog stub file --- .../checker/confidential/AlertDialog.astub | 37 +++++++++++++++++++ .../confidential/ConfidentialChecker.java | 3 +- 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/AlertDialog.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/AlertDialog.astub b/checker/src/main/java/org/checkerframework/checker/confidential/AlertDialog.astub new file mode 100644 index 00000000000..475b9b868d5 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/AlertDialog.astub @@ -0,0 +1,37 @@ +package android.app; + +import android.annotation.ArrayRes; +import android.annotation.AttrRes; +import android.annotation.DrawableRes; +import android.annotation.StringRes; +import android.annotation.StyleRes; +import android.compat.annotation.UnsupportedAppUsage; +import android.content.Context; +import android.content.DialogInterface; +import android.content.res.ResourceId; +import android.content.res.Resources; +import android.database.Cursor; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.Message; +import android.text.Layout; +import android.text.method.MovementMethod; +import android.util.TypedValue; +import android.view.ContextThemeWrapper; +import android.view.KeyEvent; +import android.view.View; +import android.widget.AdapterView; +import android.widget.Button; +import android.widget.ListAdapter; +import android.widget.ListView; +import com.android.internal.R; +import com.android.internal.app.AlertController; + +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public class AlertDialog extends Dialog implements DialogInterface { + + public void setMessage(@NonConfidential CharSequence message); + + public Builder setMessage(@NonConfidential CharSequence message); +} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 00213c26236..f80147a2d41 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -21,7 +21,8 @@ "Formatter.astub", "ApacheLog.astub", "Toast.astub", - "TextView.astub" + "TextView.astub", + "AlertDialog.astub" }) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker {} From a75afce24266e677a0370e7ddc33648c6753f7f1 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 26 Aug 2024 14:21:00 -0700 Subject: [PATCH 111/184] Added Spring URL Handler stub file --- ...uthenticationTargetUrlRequestHandler.astub | 26 +++++++++++++++++++ .../confidential/ConfidentialChecker.java | 3 ++- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/AbstractAuthenticationTargetUrlRequestHandler.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/AbstractAuthenticationTargetUrlRequestHandler.astub b/checker/src/main/java/org/checkerframework/checker/confidential/AbstractAuthenticationTargetUrlRequestHandler.astub new file mode 100644 index 00000000000..d653501c249 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/AbstractAuthenticationTargetUrlRequestHandler.astub @@ -0,0 +1,26 @@ +package org.springframework.security.web.authentication; + +import java.io.IOException; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.core.log.LogMessage; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.DefaultRedirectStrategy; +import org.springframework.security.web.RedirectStrategy; +import org.springframework.security.web.util.UrlUtils; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public abstract class AbstractAuthenticationTargetUrlRequestHandler { + + public void setDefaultTargetUrl(@NonConfidential String defaultTargetUrl); + + public void setTargetUrlParameter(@NonConfidential String targetUrlParameter); +} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index f80147a2d41..3cd5628f7f8 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -22,7 +22,8 @@ "ApacheLog.astub", "Toast.astub", "TextView.astub", - "AlertDialog.astub" + "AlertDialog.astub", + "AbstractAuthenticationTargetUrlRequestHandler.astub" }) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker {} From 1f9a6ee945e1bda12438d0ca995f28a278b22ff9 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 26 Aug 2024 15:37:47 -0700 Subject: [PATCH 112/184] Added Java PrintStream stub file --- .../confidential/ConfidentialChecker.java | 3 +- .../checker/confidential/PrintStream.astub | 49 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/PrintStream.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 3cd5628f7f8..416d1b4b426 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -23,7 +23,8 @@ "Toast.astub", "TextView.astub", "AlertDialog.astub", - "AbstractAuthenticationTargetUrlRequestHandler.astub" + "AbstractAuthenticationTargetUrlRequestHandler.astub", + "PrintStream.astub" }) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/PrintStream.astub b/checker/src/main/java/org/checkerframework/checker/confidential/PrintStream.astub new file mode 100644 index 00000000000..9eb1fee6a55 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/PrintStream.astub @@ -0,0 +1,49 @@ +package java.io; + +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; +import java.util.Formatter; +import java.util.Locale; +import java.util.Locale.Category; + +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public class PrintStream extends FilterOutputStream implements Appendable, Closeable { + + public void print(@NonConfidential char c); + + public void print(@NonConfidential int i); + + public void print(@NonConfidential long l); + + public void print(@NonConfidential float f); + + public void print(@NonConfidential double d); + + public void print(@NonConfidential char[] s); + + public void print(@NonConfidential String s); + + public void print(@NonConfidential Object obj); + + public void println(@NonConfidential char x); + + public void println(@NonConfidential int x); + + public void println(@NonConfidential long x); + + public void println(@NonConfidential float x); + + public void println(@NonConfidential double x); + + public void println(@NonConfidential char[] x); + + public void println(@NonConfidential String x); + + public void println(@NonConfidential Object x); + + public PrintStream printf(@NonConfidential String format, Object... args); + + public PrintStream printf(Locale l, @NonConfidential String format, Object... args); +} From cf99e89246bbbdac7a035b2dc6e4e6e6be486bf0 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 26 Aug 2024 16:04:03 -0700 Subject: [PATCH 113/184] Added Javax HttpServletResponse stub file --- .../confidential/ConfidentialChecker.java | 3 ++- .../confidential/HttpServletResponse.astub | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/HttpServletResponse.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 416d1b4b426..f048e38ec79 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -24,7 +24,8 @@ "TextView.astub", "AlertDialog.astub", "AbstractAuthenticationTargetUrlRequestHandler.astub", - "PrintStream.astub" + "PrintStream.astub", + "HttpServletResponse.astub" }) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/HttpServletResponse.astub b/checker/src/main/java/org/checkerframework/checker/confidential/HttpServletResponse.astub new file mode 100644 index 00000000000..80b50ece07f --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/HttpServletResponse.astub @@ -0,0 +1,16 @@ +package javax.servlet.http; + +import java.io.IOException; +import java.util.Collection; +import java.util.Map; +import java.util.function.Supplier; +import javax.servlet.ServletResponse; + +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public interface HttpServletResponse extends ServletResponse { + + void sendRedirect(@NonConfidential String var1); + + void sendError(int var1, @NonConfidential String var2); +} From f3904f62af801313391037e07cf3c36e89635d2c Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 26 Aug 2024 16:11:00 -0700 Subject: [PATCH 114/184] Added Javax Cookie stub file --- .../confidential/ConfidentialChecker.java | 3 ++- .../checker/confidential/Cookie.astub | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/Cookie.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index f048e38ec79..6977f7169b2 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -25,7 +25,8 @@ "AlertDialog.astub", "AbstractAuthenticationTargetUrlRequestHandler.astub", "PrintStream.astub", - "HttpServletResponse.astub" + "HttpServletResponse.astub", + "Cookie.astub" }) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/Cookie.astub b/checker/src/main/java/org/checkerframework/checker/confidential/Cookie.astub new file mode 100644 index 00000000000..78b7dae7341 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/Cookie.astub @@ -0,0 +1,17 @@ +package javax.servlet.http; + +import java.io.Serializable; +import java.text.MessageFormat; +import java.util.Locale; +import java.util.ResourceBundle; + +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public class Cookie implements Cloneable, Serializable { + + public void setComment(@NonConfidential String purpose); + + public void setDomain(@NonConfidential String domain); + + public void setValue(@NonConfidential String newValue); +} From 35f485fd4308ae9cd4447a030669af256cf3d259 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 3 Sep 2024 15:40:30 -0700 Subject: [PATCH 115/184] Remove `@Private` etc. --- .../checker/private/PolyPrivate.java | 20 --------------- .../checker/private/Private.java | 23 ----------------- .../checker/private/Public.java | 25 ------------------- 3 files changed, 68 deletions(-) delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/private/PolyPrivate.java delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/private/Private.java delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/private/Public.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/private/PolyPrivate.java b/checker-qual/src/main/java/org/checkerframework/checker/private/PolyPrivate.java deleted file mode 100644 index 0f481e6ab56..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/private/PolyPrivate.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.checkerframework.checker.tainting.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.PolymorphicQualifier; - -/** - * A polymorphic qualifier for the Tainting type system. - * - * @checker_framework.manual #tainting-checker Tainting Checker - * @checker_framework.manual #qualifier-polymorphism Qualifier polymorphism - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@PolymorphicQualifier(Tainted.class) -public @interface PolyTainted {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/private/Private.java b/checker-qual/src/main/java/org/checkerframework/checker/private/Private.java deleted file mode 100644 index b0ad26dc49e..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/private/Private.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.checkerframework.checker.tainting.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; -import org.checkerframework.framework.qual.SubtypeOf; - -/** - * Denotes a possibly-tainted value: at run time, the value might be tainted or might be untainted. - * - * @see Untainted - * @see org.checkerframework.checker.tainting.TaintingChecker - * @checker_framework.manual #tainting-checker Tainting Checker - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf({}) -@DefaultQualifierInHierarchy -public @interface Tainted {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/private/Public.java b/checker-qual/src/main/java/org/checkerframework/checker/private/Public.java deleted file mode 100644 index 83d48f5186b..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/private/Public.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.checkerframework.checker.tainting.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultFor; -import org.checkerframework.framework.qual.LiteralKind; -import org.checkerframework.framework.qual.QualifierForLiterals; -import org.checkerframework.framework.qual.SubtypeOf; -import org.checkerframework.framework.qual.TypeUseLocation; - -/** - * Denotes a reference that is untainted, i.e. can be trusted. - * - * @checker_framework.manual #tainting-checker Tainting Checker - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(Tainted.class) -@QualifierForLiterals(LiteralKind.STRING) -@DefaultFor(TypeUseLocation.LOWER_BOUND) -public @interface Untainted {} From d34029842c994e53030f385d6170bb39ffa80720 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 3 Sep 2024 15:41:51 -0700 Subject: [PATCH 116/184] Removed outdated confidential qualifiers --- .../checker/private/PolyPrivate.java | 20 --------------- .../checker/private/Private.java | 23 ----------------- .../checker/private/Public.java | 25 ------------------- 3 files changed, 68 deletions(-) delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/private/PolyPrivate.java delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/private/Private.java delete mode 100644 checker-qual/src/main/java/org/checkerframework/checker/private/Public.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/private/PolyPrivate.java b/checker-qual/src/main/java/org/checkerframework/checker/private/PolyPrivate.java deleted file mode 100644 index 0f481e6ab56..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/private/PolyPrivate.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.checkerframework.checker.tainting.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.PolymorphicQualifier; - -/** - * A polymorphic qualifier for the Tainting type system. - * - * @checker_framework.manual #tainting-checker Tainting Checker - * @checker_framework.manual #qualifier-polymorphism Qualifier polymorphism - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@PolymorphicQualifier(Tainted.class) -public @interface PolyTainted {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/private/Private.java b/checker-qual/src/main/java/org/checkerframework/checker/private/Private.java deleted file mode 100644 index b0ad26dc49e..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/private/Private.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.checkerframework.checker.tainting.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; -import org.checkerframework.framework.qual.SubtypeOf; - -/** - * Denotes a possibly-tainted value: at run time, the value might be tainted or might be untainted. - * - * @see Untainted - * @see org.checkerframework.checker.tainting.TaintingChecker - * @checker_framework.manual #tainting-checker Tainting Checker - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf({}) -@DefaultQualifierInHierarchy -public @interface Tainted {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/private/Public.java b/checker-qual/src/main/java/org/checkerframework/checker/private/Public.java deleted file mode 100644 index 83d48f5186b..00000000000 --- a/checker-qual/src/main/java/org/checkerframework/checker/private/Public.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.checkerframework.checker.tainting.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultFor; -import org.checkerframework.framework.qual.LiteralKind; -import org.checkerframework.framework.qual.QualifierForLiterals; -import org.checkerframework.framework.qual.SubtypeOf; -import org.checkerframework.framework.qual.TypeUseLocation; - -/** - * Denotes a reference that is untainted, i.e. can be trusted. - * - * @checker_framework.manual #tainting-checker Tainting Checker - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(Tainted.class) -@QualifierForLiterals(LiteralKind.STRING) -@DefaultFor(TypeUseLocation.LOWER_BOUND) -public @interface Untainted {} From e89c4591a4910966cc425a6dbabab55057982ef2 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 3 Sep 2024 15:53:31 -0700 Subject: [PATCH 117/184] Expand tests --- .../ConfidentialConcatenation.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/checker/tests/confidential/ConfidentialConcatenation.java b/checker/tests/confidential/ConfidentialConcatenation.java index 141a628d299..c853f9d213e 100644 --- a/checker/tests/confidential/ConfidentialConcatenation.java +++ b/checker/tests/confidential/ConfidentialConcatenation.java @@ -1,3 +1,6 @@ +// NonConfidential <: Confidential + +import org.checkerframework.checker.confidential.qual.Confidential; import org.checkerframework.checker.confidential.qual.NonConfidential; public class ConfidentialConcatenation { @@ -6,7 +9,22 @@ void executeNonConfidential(@NonConfidential String s) {} void executeConfidential(String s) {} + void executeConfidential2(@Confidential String s) {} + void concatenation(@NonConfidential String s1, String s2) { + @Confidential String s_1 = s1 + s1; + @Confidential String s_2 = s1 + s2; + @Confidential String s_3 = s2 + s1; + @Confidential String s_4 = s2 + s2; + + @NonConfidential String s_5 = s1 + s1; + // :: error: (assignment) + @NonConfidential String s_6 = s1 + s2; + // :: error: (assignment) + @NonConfidential String s_7 = s2 + s1; + // :: error: (assignment) + @NonConfidential String s_8 = s2 + s2; + executeNonConfidential(s1 + s1); // :: error: (argument) executeNonConfidential(s1 + s2); @@ -19,6 +37,10 @@ void concatenation(@NonConfidential String s1, String s2) { executeConfidential(s1 + s2); executeConfidential(s2 + s1); executeConfidential(s2 + s2); + executeConfidential2(s1 + s1); + executeConfidential2(s1 + s2); + executeConfidential2(s2 + s1); + executeConfidential2(s2 + s2); } void compoundConcatenation(@NonConfidential String s1, String s2) { From f11d2cc8ac6205307fad4abe9ac8e35185028a2a Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 3 Sep 2024 16:08:53 -0700 Subject: [PATCH 118/184] Split test --- checker/tests/confidential/ConfidentialConcatenation.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/checker/tests/confidential/ConfidentialConcatenation.java b/checker/tests/confidential/ConfidentialConcatenation.java index c853f9d213e..9aa7369ba5e 100644 --- a/checker/tests/confidential/ConfidentialConcatenation.java +++ b/checker/tests/confidential/ConfidentialConcatenation.java @@ -24,6 +24,9 @@ void concatenation(@NonConfidential String s1, String s2) { @NonConfidential String s_7 = s2 + s1; // :: error: (assignment) @NonConfidential String s_8 = s2 + s2; + } + + void concatenationInvocation(@NonConfidential String s1, String s2) { executeNonConfidential(s1 + s1); // :: error: (argument) From 5ed3649cfb35844dd9ce20163576119f59beebde Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 3 Sep 2024 16:11:22 -0700 Subject: [PATCH 119/184] Add smaller test --- .../confidential/ConfidentialConcatenationShort.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 checker/tests/confidential/ConfidentialConcatenationShort.java diff --git a/checker/tests/confidential/ConfidentialConcatenationShort.java b/checker/tests/confidential/ConfidentialConcatenationShort.java new file mode 100644 index 00000000000..b69fbb27b35 --- /dev/null +++ b/checker/tests/confidential/ConfidentialConcatenationShort.java @@ -0,0 +1,11 @@ +// NonConfidential <: Confidential + +import org.checkerframework.checker.confidential.qual.Confidential; +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public class ConfidentialConcatenationShort { + + void concatenation(@NonConfidential String s1, String s2) { + @Confidential String s_1 = s1 + s1; + } +} From b530805efa6a2845245d200392842f569f4424bf Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 3 Sep 2024 16:47:12 -0700 Subject: [PATCH 120/184] Add diagnostic output --- .../org/checkerframework/common/basetype/BaseTypeVisitor.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java b/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java index 50f745ae726..248afa1b3c0 100644 --- a/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java +++ b/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java @@ -3218,6 +3218,8 @@ protected final void commonAssignmentCheckEndDiagnostic( varType, valueType, valueExpTree); + // TEMPORARY + new Error("backtrace").printStackTrace(); } } From a41e7da9d22ef21a678d3a121bb1a98b1f3b8429 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 3 Sep 2024 16:52:03 -0700 Subject: [PATCH 121/184] Sleep --- .../checkerframework/common/basetype/BaseTypeVisitor.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java b/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java index 950570f7667..c397d2a0ebf 100644 --- a/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java +++ b/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java @@ -3227,6 +3227,12 @@ protected final void commonAssignmentCheckEndDiagnostic( valueType, valueExpTree); // TEMPORARY + try { + Thread.sleep(1); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + System.out.flush(); new Error("backtrace").printStackTrace(); } } From 3518e33b460dd5151a07fdc7757b830ce760be34 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 3 Sep 2024 16:57:02 -0700 Subject: [PATCH 122/184] Expand test --- .../tests/confidential/ConfidentialConcatenationShort.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/checker/tests/confidential/ConfidentialConcatenationShort.java b/checker/tests/confidential/ConfidentialConcatenationShort.java index b69fbb27b35..5dd6ef6e7cc 100644 --- a/checker/tests/confidential/ConfidentialConcatenationShort.java +++ b/checker/tests/confidential/ConfidentialConcatenationShort.java @@ -5,7 +5,12 @@ public class ConfidentialConcatenationShort { - void concatenation(@NonConfidential String s1, String s2) { + void concatenationInitialization(@NonConfidential String s1, String s2) { @Confidential String s_1 = s1 + s1; } + + void concatenation(@NonConfidential String s1, String s2) { + @Confidential String s_1; + s_1 = s1 + s1; + } } From 38f520d8271de3a4351b1d6fcef0d3d3c41a7745 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 3 Sep 2024 17:02:20 -0700 Subject: [PATCH 123/184] Simplify test --- .../tests/confidential/ConfidentialConcatenationShort.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/checker/tests/confidential/ConfidentialConcatenationShort.java b/checker/tests/confidential/ConfidentialConcatenationShort.java index 5dd6ef6e7cc..88dd7e56b16 100644 --- a/checker/tests/confidential/ConfidentialConcatenationShort.java +++ b/checker/tests/confidential/ConfidentialConcatenationShort.java @@ -5,12 +5,9 @@ public class ConfidentialConcatenationShort { - void concatenationInitialization(@NonConfidential String s1, String s2) { - @Confidential String s_1 = s1 + s1; - } + @Confidential String confidentialField; void concatenation(@NonConfidential String s1, String s2) { - @Confidential String s_1; - s_1 = s1 + s1; + confidentialField = s1 + s1; } } From 9eecb74e502a8a92ccfaae35690a742d4bb181b2 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 3 Sep 2024 17:23:29 -0700 Subject: [PATCH 124/184] Remove diagnostic output --- .../confidential/ConfidentialConcatenationShort.java | 2 ++ .../checkerframework/common/basetype/BaseTypeVisitor.java | 8 -------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/checker/tests/confidential/ConfidentialConcatenationShort.java b/checker/tests/confidential/ConfidentialConcatenationShort.java index 88dd7e56b16..d7a4ff81974 100644 --- a/checker/tests/confidential/ConfidentialConcatenationShort.java +++ b/checker/tests/confidential/ConfidentialConcatenationShort.java @@ -1,3 +1,5 @@ +// TEMPORARY TEST FILE; remove before merging. + // NonConfidential <: Confidential import org.checkerframework.checker.confidential.qual.Confidential; diff --git a/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java b/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java index c397d2a0ebf..0805eab9379 100644 --- a/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java +++ b/framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java @@ -3226,14 +3226,6 @@ protected final void commonAssignmentCheckEndDiagnostic( varType, valueType, valueExpTree); - // TEMPORARY - try { - Thread.sleep(1); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - System.out.flush(); - new Error("backtrace").printStackTrace(); } } From fbcb577e11597297e2271c79683e7f8b2ebcedf1 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 16 Sep 2024 13:29:23 -0700 Subject: [PATCH 125/184] Revised Confidential checker hierarchy --- .../checker/confidential/qual/Confidential.java | 4 +--- .../checker/confidential/qual/NonConfidential.java | 5 +---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java index 639d600fc80..91bfd265d70 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java @@ -5,7 +5,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; import org.checkerframework.framework.qual.SubtypeOf; /** @@ -20,6 +19,5 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf({}) -@DefaultQualifierInHierarchy +@SubtypeOf(UnknownConfidential.class) public @interface Confidential {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java index 91719ef1bb7..e579e62d381 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java @@ -5,11 +5,9 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultFor; import org.checkerframework.framework.qual.LiteralKind; import org.checkerframework.framework.qual.QualifierForLiterals; import org.checkerframework.framework.qual.SubtypeOf; -import org.checkerframework.framework.qual.TypeUseLocation; /** * Denotes a value that can be exposed to end users, or a location that can be accessed by end @@ -21,7 +19,6 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@SubtypeOf(Confidential.class) +@SubtypeOf(UnknownConfidential.class) @QualifierForLiterals(LiteralKind.ALL) -@DefaultFor(TypeUseLocation.LOWER_BOUND) public @interface NonConfidential {} From 80f52035e7c7aa31b1a1c703efb8c4be962487be Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 16 Sep 2024 13:30:25 -0700 Subject: [PATCH 126/184] Revised Confidential checker hierarchy --- .../confidential/qual/BottomConfidential.java | 27 +++++++++++++++++++ .../qual/UnknownConfidential.java | 26 ++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/BottomConfidential.java create mode 100644 checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/UnknownConfidential.java diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/BottomConfidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/BottomConfidential.java new file mode 100644 index 00000000000..957bf764877 --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/BottomConfidential.java @@ -0,0 +1,27 @@ +package org.checkerframework.checker.confidential.qual; + +/** + * The bottom type in the Confidential type system. Programmers should rarely write this type. + * + * @checker_framework.manual #confidential-checker Confidential Checker + * @checker_framework.manual #bottom-type the bottom type + */ +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.DefaultFor; +import org.checkerframework.framework.qual.InvisibleQualifier; +import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TargetLocations; +import org.checkerframework.framework.qual.TypeUseLocation; + +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@InvisibleQualifier +@SubtypeOf({Confidential.class, NonConfidential.class}) +@DefaultFor(value = {TypeUseLocation.LOWER_BOUND}) +public @interface BottomConfidential {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/UnknownConfidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/UnknownConfidential.java new file mode 100644 index 00000000000..3f4cc7334ab --- /dev/null +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/UnknownConfidential.java @@ -0,0 +1,26 @@ +package org.checkerframework.checker.confidential.qual; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; +import org.checkerframework.framework.qual.InvisibleQualifier; +import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TargetLocations; +import org.checkerframework.framework.qual.TypeUseLocation; + +/** + * Represents the top of the Confidential qualifier hierarchy. + * + * @checker_framework.manual #confidential-checker Confidential Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) +@InvisibleQualifier +@SubtypeOf({}) +@DefaultQualifierInHierarchy +public @interface UnknownConfidential {} From c02a19527319ffd31231c590d0afdaa4fb2799ed Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Wed, 18 Sep 2024 14:05:14 -0700 Subject: [PATCH 127/184] Revised NonConfidential and Confidential qualifier documentation --- .../checker/confidential/qual/Confidential.java | 8 +++++--- .../checker/confidential/qual/NonConfidential.java | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java index 91bfd265d70..d9b0f6a6600 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java @@ -8,9 +8,11 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * Denotes a value that should not be exposed to end users (i.e., PII, passwords, and private keys) - * or a location (i.e., a file or database) that should not be able to be accessed by end users. - * Confidential locations can contain Confidential or NonConfidential information. + * Denotes a value that will not be exposed to end users or a sink that will not be able to be + * accessed by end users. + * + *

Typically, a Confidential value will contain sensitive, private, or otherwise + * privileged-access information, such as passwords, PII, and private keys. * * @see NonConfidential * @see org.checkerframework.checker.confidential.ConfidentialChecker diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java index e579e62d381..32a3dbad29c 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java @@ -10,9 +10,9 @@ import org.checkerframework.framework.qual.SubtypeOf; /** - * Denotes a value that can be exposed to end users, or a location that can be accessed by end - * users. NonConfidential locations can only contain NonConfidential information, not Confidential - * information. + * Denotes a value that may be exposed to end users, or a location that may be accessed by end + * users. NonConfidential locations will never contain sensitive, private, or otherwise + * privileged-access information. * * @checker_framework.manual #confidential-checker Confidential Checker */ From 75e65dd49998d012e6a331feff34c6915a21d652 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 19 Sep 2024 17:13:03 -0700 Subject: [PATCH 128/184] Revised Confidential checker concatenation implementation --- .../ConfidentialAnnotatedTypeFactory.java | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java index 4e3393b407b..b83f878eeb5 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java @@ -1,12 +1,23 @@ package org.checkerframework.checker.confidential; +import com.sun.source.tree.BinaryTree; +import com.sun.source.tree.CompoundAssignmentTree; import java.util.Set; import javax.lang.model.element.AnnotationMirror; +import org.checkerframework.checker.confidential.qual.BottomConfidential; +import org.checkerframework.checker.confidential.qual.Confidential; import org.checkerframework.checker.confidential.qual.NonConfidential; +import org.checkerframework.checker.confidential.qual.UnknownConfidential; +import org.checkerframework.checker.sqlquotes.SqlQuotesAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.framework.type.AnnotatedTypeFactory; +import org.checkerframework.framework.type.AnnotatedTypeMirror; +import org.checkerframework.framework.type.treeannotator.ListTreeAnnotator; +import org.checkerframework.framework.type.treeannotator.TreeAnnotator; import org.checkerframework.javacutil.AnnotationBuilder; import org.checkerframework.javacutil.AnnotationMirrorSet; +import org.checkerframework.javacutil.TreeUtils; /** Annotated type factory for the Confidential Checker. */ public class ConfidentialAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { @@ -14,6 +25,15 @@ public class ConfidentialAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { /** The {@code @}{@link NonConfidential} annotation mirror. */ private final AnnotationMirror NONCONFIDENTIAL; + /** The {@code @}{@link Confidential} annotation mirror. */ + private final AnnotationMirror CONFIDENTIAL; + + /** The {@code @}{@link UnknownConfidential} annotation mirror. */ + private final AnnotationMirror UNKNOWN_CONFIDENTIAL; + + /** The {@code @}{@link BottomConfidential} annotation mirror. */ + private final AnnotationMirror BOTTOM_CONFIDENTIAL; + /** A singleton set containing the {@code @}{@link NonConfidential} annotation mirror. */ private final AnnotationMirrorSet setOfNonConfidential; @@ -25,6 +45,11 @@ public class ConfidentialAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { public ConfidentialAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); this.NONCONFIDENTIAL = AnnotationBuilder.fromClass(getElementUtils(), NonConfidential.class); + this.CONFIDENTIAL = AnnotationBuilder.fromClass(getElementUtils(), NonConfidential.class); + this.UNKNOWN_CONFIDENTIAL = + AnnotationBuilder.fromClass(getElementUtils(), UnknownConfidential.class); + this.BOTTOM_CONFIDENTIAL = + AnnotationBuilder.fromClass(getElementUtils(), BottomConfidential.class); this.setOfNonConfidential = AnnotationMirrorSet.singleton(NONCONFIDENTIAL); postInit(); } @@ -33,4 +58,81 @@ public ConfidentialAnnotatedTypeFactory(BaseTypeChecker checker) { protected Set getEnumConstructorQualifiers() { return setOfNonConfidential; } + + @Override + public TreeAnnotator createTreeAnnotator() { + return new ListTreeAnnotator( + super.createTreeAnnotator(), + new SqlQuotesAnnotatedTypeFactory.SqlQuotesTreeAnnotator(this)); + } + + /** + * A TreeAnnotator to enforce Confidential String concatenation rules: + * + *

    + *
  • (Confidential + NonConfidential) returns Confidential (commutatively); + *
  • (Confidential + Confidential) returns Confidential; + *
  • (NonConfidential + NonConfidential) returns NonConfidential; + *
  • UnknownConfidential dominates other types in concatenation; + *
  • Non-bottom types dominate BottomConfidential in concatenation. + *
+ */ + private class ConfidentialTreeAnnotator extends TreeAnnotator { + /** + * Creates a {@link ConfidentialAnnotatedTypeFactory.ConfidentialTreeAnnotator} + * + * @param atypeFactory the annotated type factory + */ + public ConfidentialTreeAnnotator(AnnotatedTypeFactory atypeFactory) { + super(atypeFactory); + } + + @Override + public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { + if (TreeUtils.isStringConcatenation(tree)) { + AnnotatedTypeMirror leftType = getAnnotatedType(tree.getLeftOperand()); + AnnotatedTypeMirror rightType = getAnnotatedType(tree.getRightOperand()); + type.replaceAnnotation(getResultingType(leftType, rightType)); + } + return null; + } + + @Override + public Void visitCompoundAssignment(CompoundAssignmentTree tree, AnnotatedTypeMirror type) { + if (TreeUtils.isStringCompoundConcatenation(tree)) { + AnnotatedTypeMirror leftType = getAnnotatedType(tree.getVariable()); + AnnotatedTypeMirror rightType = getAnnotatedType(tree.getExpression()); + type.replaceAnnotation(getResultingType(leftType, rightType)); + } + return null; + } + + /** + * Returns the type of concatenating leftType and rightType. + * + * @param leftType the type on the left of the expression + * @param rightType the type on the right of the expression + * @return the resulting type after concatenation + */ + private AnnotationMirror getResultingType( + AnnotatedTypeMirror leftType, AnnotatedTypeMirror rightType) { + if (leftType.hasPrimaryAnnotation(UNKNOWN_CONFIDENTIAL) + || rightType.hasPrimaryAnnotation(UNKNOWN_CONFIDENTIAL)) { + return UNKNOWN_CONFIDENTIAL; + } + + if (leftType.hasPrimaryAnnotation(BOTTOM_CONFIDENTIAL)) { + return rightType.getPrimaryAnnotation(); + } else if (rightType.hasPrimaryAnnotation(BOTTOM_CONFIDENTIAL)) { + return leftType.getPrimaryAnnotation(); + } + + if (leftType.hasPrimaryAnnotation(CONFIDENTIAL) + || rightType.hasPrimaryAnnotation(CONFIDENTIAL)) { + return CONFIDENTIAL; + } + + return NONCONFIDENTIAL; + } + } } From 1989a8f778b42dd84c575aaeb1f9519ba62c7ca8 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 19 Sep 2024 17:14:13 -0700 Subject: [PATCH 129/184] Bug fix --- .../checker/confidential/ConfidentialAnnotatedTypeFactory.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java index b83f878eeb5..9b4bf57f888 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java @@ -8,7 +8,6 @@ import org.checkerframework.checker.confidential.qual.Confidential; import org.checkerframework.checker.confidential.qual.NonConfidential; import org.checkerframework.checker.confidential.qual.UnknownConfidential; -import org.checkerframework.checker.sqlquotes.SqlQuotesAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.framework.type.AnnotatedTypeFactory; @@ -63,7 +62,7 @@ protected Set getEnumConstructorQualifiers() { public TreeAnnotator createTreeAnnotator() { return new ListTreeAnnotator( super.createTreeAnnotator(), - new SqlQuotesAnnotatedTypeFactory.SqlQuotesTreeAnnotator(this)); + new ConfidentialAnnotatedTypeFactory.ConfidentialTreeAnnotator(this)); } /** From 6a0435d11647cef9f337a3acb52c62c587a965d1 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 19 Sep 2024 18:29:57 -0700 Subject: [PATCH 130/184] Typo fixes --- .../checker/confidential/qual/PolyConfidential.java | 2 +- .../checker/confidential/ConfidentialAnnotatedTypeFactory.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/PolyConfidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/PolyConfidential.java index 7c48586a0a5..a218de1b687 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/PolyConfidential.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/PolyConfidential.java @@ -16,5 +16,5 @@ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) -@PolymorphicQualifier(Confidential.class) +@PolymorphicQualifier(UnknownConfidential.class) public @interface PolyConfidential {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java index 9b4bf57f888..098ba088c09 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java @@ -44,7 +44,7 @@ public class ConfidentialAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { public ConfidentialAnnotatedTypeFactory(BaseTypeChecker checker) { super(checker); this.NONCONFIDENTIAL = AnnotationBuilder.fromClass(getElementUtils(), NonConfidential.class); - this.CONFIDENTIAL = AnnotationBuilder.fromClass(getElementUtils(), NonConfidential.class); + this.CONFIDENTIAL = AnnotationBuilder.fromClass(getElementUtils(), Confidential.class); this.UNKNOWN_CONFIDENTIAL = AnnotationBuilder.fromClass(getElementUtils(), UnknownConfidential.class); this.BOTTOM_CONFIDENTIAL = From fb859ecce6ea715cec3d7e947ef92323b10bd979 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Thu, 19 Sep 2024 18:30:37 -0700 Subject: [PATCH 131/184] Revised tests for confidential checker --- .../ConfidentialConcatenation.java | 14 ++--- .../ConfidentialConcatenationShort.java | 15 ----- .../confidential/NonConfidentialLiterals.java | 57 ++++++++++++++++--- .../confidential/SimpleConfidential.java | 6 +- 4 files changed, 59 insertions(+), 33 deletions(-) delete mode 100644 checker/tests/confidential/ConfidentialConcatenationShort.java diff --git a/checker/tests/confidential/ConfidentialConcatenation.java b/checker/tests/confidential/ConfidentialConcatenation.java index 9aa7369ba5e..2cba808a72b 100644 --- a/checker/tests/confidential/ConfidentialConcatenation.java +++ b/checker/tests/confidential/ConfidentialConcatenation.java @@ -7,11 +7,10 @@ public class ConfidentialConcatenation { void executeNonConfidential(@NonConfidential String s) {} - void executeConfidential(String s) {} + void executeConfidential(@Confidential String s) {} - void executeConfidential2(@Confidential String s) {} - - void concatenation(@NonConfidential String s1, String s2) { + void concatenation(@NonConfidential String s1, @Confidential String s2) { + // :: error: (assignment) @Confidential String s_1 = s1 + s1; @Confidential String s_2 = s1 + s2; @Confidential String s_3 = s2 + s1; @@ -26,7 +25,7 @@ void concatenation(@NonConfidential String s1, String s2) { @NonConfidential String s_8 = s2 + s2; } - void concatenationInvocation(@NonConfidential String s1, String s2) { + void concatenationInvocation(@NonConfidential String s1, @Confidential String s2) { executeNonConfidential(s1 + s1); // :: error: (argument) @@ -36,14 +35,11 @@ void concatenationInvocation(@NonConfidential String s1, String s2) { // :: error: (argument) executeNonConfidential(s2 + s2); + // :: error: (argument) executeConfidential(s1 + s1); executeConfidential(s1 + s2); executeConfidential(s2 + s1); executeConfidential(s2 + s2); - executeConfidential2(s1 + s1); - executeConfidential2(s1 + s2); - executeConfidential2(s2 + s1); - executeConfidential2(s2 + s2); } void compoundConcatenation(@NonConfidential String s1, String s2) { diff --git a/checker/tests/confidential/ConfidentialConcatenationShort.java b/checker/tests/confidential/ConfidentialConcatenationShort.java deleted file mode 100644 index d7a4ff81974..00000000000 --- a/checker/tests/confidential/ConfidentialConcatenationShort.java +++ /dev/null @@ -1,15 +0,0 @@ -// TEMPORARY TEST FILE; remove before merging. - -// NonConfidential <: Confidential - -import org.checkerframework.checker.confidential.qual.Confidential; -import org.checkerframework.checker.confidential.qual.NonConfidential; - -public class ConfidentialConcatenationShort { - - @Confidential String confidentialField; - - void concatenation(@NonConfidential String s1, String s2) { - confidentialField = s1 + s1; - } -} diff --git a/checker/tests/confidential/NonConfidentialLiterals.java b/checker/tests/confidential/NonConfidentialLiterals.java index ee920512fef..417cda0b1eb 100644 --- a/checker/tests/confidential/NonConfidentialLiterals.java +++ b/checker/tests/confidential/NonConfidentialLiterals.java @@ -1,81 +1,124 @@ +import org.checkerframework.checker.confidential.qual.Confidential; import org.checkerframework.checker.confidential.qual.NonConfidential; public class NonConfidentialLiterals { void executeString(@NonConfidential String s) {} - void confidentialString(String s) {} + void confidentialString(@Confidential String s) {} + + void unknownString(String s) {} void stringLiteral() { executeString("asdf"); + // :: error: (argument) confidentialString("asdf"); + unknownString("asdf"); executeString("132ijkdsf0wenj va2i3"); + // :: error: (argument) confidentialString("132ijkdsf0wenj va2i3"); + unknownString("132ijkdsf0wenj va2i3"); } void executeBool(@NonConfidential boolean b) {} - void confidentialBool(boolean b) {} + void confidentialBool(@Confidential boolean b) {} + + void unknownBool(boolean b) {} void boolLiteral() { executeBool(true); + // :: error: (argument) confidentialBool(true); + unknownBool(true); executeBool(false); + // :: error: (argument) confidentialBool(false); + unknownBool(false); } void executeChar(@NonConfidential char c) {} - void confidentialChar(char c) {} + void confidentialChar(@Confidential char c) {} + + void unknownChar(char c) {} void charLiteral() { executeChar('f'); + // :: error: (argument) confidentialChar('f'); + unknownChar('f'); executeChar('a'); + // :: error: (argument) confidentialChar('a'); + unknownChar('a'); } void executeDouble(@NonConfidential double d) {} - void confidentialDouble(double d) {} + void confidentialDouble(@Confidential double d) {} + + void unknownDouble(double d) {} void doubleLiteral() { executeDouble(1.204398); + // :: error: (argument) confidentialDouble(1.204398); + unknownDouble(1.204398); executeDouble(-0.5209384); + // :: error: (argument) confidentialDouble(-0.5209384); + unknownDouble(-0.5209384); } void executeFloat(@NonConfidential float f) {} - void confidentialFloat(float f) {} + void confidentialFloat(@Confidential float f) {} + + void unknownFloat(float f) {} void floatLiteral() { executeFloat(198232.412730f); + // :: error: (argument) confidentialFloat(198232.412730f); + unknownFloat(198232.412730f); executeFloat(-0.10938728f); + // :: error: (argument) confidentialFloat(-0.10938728f); + unknownFloat(-0.10938728f); } void executeInt(@NonConfidential int i) {} - void confidentialInt(int i) {} + void confidentialInt(@Confidential int i) {} + + void unknownInt(int i) {} void intLiteral() { executeInt(20987654); + // :: error: (argument) confidentialInt(20987654); + unknownInt(20987654); executeInt(-9598653); + // :: error: (argument) confidentialInt(-9598653); + unknownInt(-9598653); } void executeLong(@NonConfidential long l) {} - void confidentialLong(long l) {} + void confidentialLong(@Confidential long l) {} + + void unknownLong(long l) {} void longLiteral() { executeLong(20987654l); + // :: error: (argument) confidentialLong(20987654l); + unknownLong(20987654l); executeLong(-9598653l); + // :: error: (argument) confidentialLong(-9598653l); + unknownLong(-9598653l); } } diff --git a/checker/tests/confidential/SimpleConfidential.java b/checker/tests/confidential/SimpleConfidential.java index 7694e7c1a6f..a3b35e90c9b 100644 --- a/checker/tests/confidential/SimpleConfidential.java +++ b/checker/tests/confidential/SimpleConfidential.java @@ -1,17 +1,19 @@ +import org.checkerframework.checker.confidential.qual.Confidential; import org.checkerframework.checker.confidential.qual.NonConfidential; public class SimpleConfidential { void executeNonConfidential(@NonConfidential String s) {} - void executeConfidential(String s) {} + void executeConfidential(@Confidential String s) {} void nonConfidentialRef(@NonConfidential String s) { executeNonConfidential(s); + // :: error: (argument) executeConfidential(s); } - void confidentialRef(String s) { + void confidentialRef(@Confidential String s) { // :: error: (argument) executeNonConfidential(s); executeConfidential(s); From d0b1f8ea482d99506015284190d1b26d3e49f88c Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 22 Oct 2024 02:01:22 -0700 Subject: [PATCH 132/184] Revised documentation of PolyConfidential --- .../checker/confidential/qual/PolyConfidential.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/PolyConfidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/PolyConfidential.java index a218de1b687..e0bc07155f3 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/PolyConfidential.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/PolyConfidential.java @@ -10,7 +10,7 @@ /** * A polymorphic qualifier for the Confidential type system. * - * @checker_framework.manual TODO + * @checker_framework.manual #confidential-checker Confidential Checker * @checker_framework.manual #qualifier-polymorphism Qualifier polymorphism */ @Documented From 620948558bb853f1dd23526122672029493c45c7 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 22 Oct 2024 02:07:36 -0700 Subject: [PATCH 133/184] Added manual section for confidential checker --- docs/manual/advanced-features.tex | 3 + docs/manual/confidential-checker.tex | 110 +++++++++ docs/manual/figures/confidential.svg | 325 +++++++++++++++++++++++++++ docs/manual/introduction.tex | 4 + docs/manual/manual.tex | 1 + 5 files changed, 443 insertions(+) create mode 100644 docs/manual/confidential-checker.tex create mode 100644 docs/manual/figures/confidential.svg diff --git a/docs/manual/advanced-features.tex b/docs/manual/advanced-features.tex index 6a4db2d9e7c..2fa7739aa26 100644 --- a/docs/manual/advanced-features.tex +++ b/docs/manual/advanced-features.tex @@ -991,6 +991,9 @@ \item \ahrefloc{tainting-checker}{Tainting Checker} for trust and security errors (see \chapterpageref{tainting-checker}) +\item + \ahrefloc{confidential-checker}{Confidential Checker} to identify sensitive + information exposure (see \chapterpageref{confidential-checker}) \item \ahrefloc{guieffect-checker}{GUI Effect Checker} to ensure that non-GUI threads do not access the UI, which would crash the application diff --git a/docs/manual/confidential-checker.tex b/docs/manual/confidential-checker.tex new file mode 100644 index 00000000000..41ed3eafb4d --- /dev/null +++ b/docs/manual/confidential-checker.tex @@ -0,0 +1,110 @@ +\htmlhr +\chapterAndLabel{Confidential Checker}{confidential-checker} + +The Confidential Checker helps identify insecure software implementations that may +lead to \href{https://cwe.mitre.org/data/definitions/1417.html}{sensitive information +exposure}. These vulnerabilities arise when developers allow information such as PII, +passwords, or local file paths to be passed to potentially public-facing sinks, which +include website and app user interfaces, log files, error messages, and URL targets. + +Exposure may occur mistakenly or with a benign objective in mind. For instance, a developer +may unwittingly write code that exposes sensitive information, or they may output +sensitive information to error messages with the intention of supplying helpful +troubleshooting direction; the Confidential Checker covers both of these cases by +guaranteeing that no values marked as sensitive information will be passed to a +location marked as public-facing. + +However, the Confidential Checker cannot guarantee the correctness or completeness +of the annotations themselves. In other words, the onus of comprehensively annotating +sensitive information falls solely upon the developer. The Confidential Checker does +provide preliminary annotations for certain public-facing sinks, but developers should +always verify that any sinks used in their code are annotated appropriately. + +To run the Confidential Checker, supply the +\code{-processor ConfidentialChecker} +or +\code{-processor org.checkerframework.checker.confidential.ConfidentialChecker} +command-line option to javac. + + +\sectionAndLabel{Confidential annotations}{confidential-annotations} + +The Confidential Checker type system uses the following annotations: + +\begin{description} +\item[\refqualclass{checker/confidential/qual}{Confidential}] + indicates a value that will not be exposed to end users or a sink that + will not be able to be accessed by end users. +\item[\refqualclass{checker/confidential/qual}{NonConfidential}] + indicates a value that may be exposed to end users, or a location that + may be accessed by end users. It is the default qualifier for literals. +\item[\refqualclass{checker/confidential/qual}{UnknownConfidential}] + indicates a value whose confidentiality is unknown. + \code{@UnknownConfidential} is a supertype of \code{@Confidential} + and \code{@NonConfidential}. It is the default qualifier for non-literals. +\item[\refqualclass{checker/confidential/qual}{PolyConfidential}] + indicates qualifier polymorphism. For a description of qualifier polymorphism, + see Section~\ref{method-qualifier-polymorphism}. +\item[\refqualclass{checker/confidential/qual}{BottomConfidential}] + is the bottom qualifier. Programmers rarely need to write it. +\end{description} + +The subtyping hierarchy of the Confidential Checker's qualifiers is shown in +Figure~\ref{fig-confidential-hierarchy}. + +\begin{figure} +\includeimage{confidential}{5.5cm} +\caption{The subtyping relationship of the Confidential Checker's qualifiers. + Qualifiers in gray are used internally by the type system but should never + be written by a programmer.} +\label{fig-confidential-hierarchy} +\end{figure} + +Although parallels could be drawn between the Confidential Checker's +\code{@Confidential} annotation and the Taint Checker's \code{@Tainted} +annotation (see Section~\ref{tainting-annotations}), it should be noted that +\code{@Confidential} is not ambiguous in the values to which it can be applied. +As a result, while the Confidential Checker (correctly) does not allow +\code{@Confidential} values to be passed to \code{@NonConfidential} sinks, it also +disallows \code{@NonConfidential} values in \code{@Confidential} sinks. The +motivation for this structure was to avoid issues caused by +\href{https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)} +{invariant subtyping}. + +The latter constraint may not constitute desired behavior if, for example, we want +to set a \code{@Confidential} password field to a simple literal (which defaults +to \code{@NonConfidential}). However, in practice, the \code{@NonConfidential} +value would often be concatenated with a \code{@Confidential} value prior to +being passed to the \code{@Confidential} sink, thus converting it to a +\code{@Confidential} value via the type concatenation rules laid out below in +Section~\ref{confidential-checks}. For other cases, \code{@SuppressWarnings} +annotations should be specified to conduct casts between \code{@NonConfidential} +and \code{@Confidential} values. + + +\sectionAndLabel{What the Confidential Checker checks}{confidential-checks} + +Concatenation of \code{@Confidential} and \code{@NonConfidential} values is +always dominated by \code{@Confidential}. In other words, concatenation of +\code{@Confidential} and \code{@NonConfidential} values are most narrowly typed +as follows: + +\begin{Verbatim} + @Confidential + @Confidential = @Confidential + @Confidential + @NonConfidential = @Confidential + @NonConfidential + @Confidential = @Confidential + @NonConfidential + @NonConfidential = @NonConfidential +\end{Verbatim} + +\sectionAndLabel{Library annotations}{confidential-library-annotations} + +As mentioned prior, the Confidential Checker provides preliminary annotations +for certain public-facing sinks. For instance, the \code{TextView} class for Android +apps requires that a \code{@NonConfidential CharSequence} should be passed to +its \code{setText} method to avoid displaying sensitive information on the user's +viewport. + +If necessary, developers can write methods to vet \code{@Confidential} or +\code{@UnknownConfidential} values and determine which, if any, parts of the +value can be safely cast to \code{@NonConfidential} under a \code{@SuppressWarnings} +annotation and passed to user-facing sinks. diff --git a/docs/manual/figures/confidential.svg b/docs/manual/figures/confidential.svg new file mode 100644 index 00000000000..665a69d7179 --- /dev/null +++ b/docs/manual/figures/confidential.svg @@ -0,0 +1,325 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + @NonConfidential + + + @NonConfidential + + + + + @UnknownConfidential + + + + + @BottomConfidential + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/manual/introduction.tex b/docs/manual/introduction.tex index a0c1c72082d..2ad38cbe29b 100644 --- a/docs/manual/introduction.tex +++ b/docs/manual/introduction.tex @@ -47,6 +47,10 @@ \ahrefloc{sql-quotes-checker}{SQL Quotes Checker} to mitigate SQL injection attacks (see \chapterpageref{sql-quotes-checker}) +\item + \ahrefloc{confidential-checker}{Confidential Checker} to identify sensitive + information exposure + (see \chapterpageref{confidential-checker}) \item \ahrefloc{lock-checker}{Lock Checker} for concurrency and lock errors (see \chapterpageref{lock-checker}) diff --git a/docs/manual/manual.tex b/docs/manual/manual.tex index 3e7ce3b2c6b..ba4e1bc85e4 100644 --- a/docs/manual/manual.tex +++ b/docs/manual/manual.tex @@ -63,6 +63,7 @@ % These are related to tainting: \input{tainting-checker.tex} \input{sql-quotes-checker.tex} +\input{confidential-checker.tex} % These are focused on strings: \input{regex-checker.tex} From d8d88af7d521cd4de15da97c19a6cbe2bbb23273 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 29 Oct 2024 21:29:40 -0700 Subject: [PATCH 134/184] Removed stub files present in annotated JDK --- .../checker/confidential/ConfidentialChecker.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 6977f7169b2..5187c69eb6b 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -16,15 +16,15 @@ "Log4jLogger.astub", "AndroidLog.astub", "Slf4jLogger.astub", - "Handler.astub", - "JavaLogger.astub", - "Formatter.astub", + // "Handler.astub", + // "JavaLogger.astub", + // "Formatter.astub", "ApacheLog.astub", "Toast.astub", "TextView.astub", "AlertDialog.astub", "AbstractAuthenticationTargetUrlRequestHandler.astub", - "PrintStream.astub", + // "PrintStream.astub", "HttpServletResponse.astub", "Cookie.astub" }) From bf472f4cff142c37759350cdf6b0506a8958af84 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 25 Nov 2024 14:12:42 -0800 Subject: [PATCH 135/184] Changed NonConfidential to default --- .../checker/confidential/qual/NonConfidential.java | 2 ++ .../checker/confidential/qual/UnknownConfidential.java | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java index 32a3dbad29c..3ab786ffd59 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java @@ -5,6 +5,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; import org.checkerframework.framework.qual.LiteralKind; import org.checkerframework.framework.qual.QualifierForLiterals; import org.checkerframework.framework.qual.SubtypeOf; @@ -21,4 +22,5 @@ @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(UnknownConfidential.class) @QualifierForLiterals(LiteralKind.ALL) +@DefaultQualifierInHierarchy public @interface NonConfidential {} diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/UnknownConfidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/UnknownConfidential.java index 3f4cc7334ab..6bf37fd46fd 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/UnknownConfidential.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/UnknownConfidential.java @@ -5,7 +5,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; import org.checkerframework.framework.qual.InvisibleQualifier; import org.checkerframework.framework.qual.SubtypeOf; import org.checkerframework.framework.qual.TargetLocations; @@ -22,5 +21,4 @@ @TargetLocations({TypeUseLocation.EXPLICIT_LOWER_BOUND, TypeUseLocation.EXPLICIT_UPPER_BOUND}) @InvisibleQualifier @SubtypeOf({}) -@DefaultQualifierInHierarchy public @interface UnknownConfidential {} From 42ae722da2e0d0d2efdc8abe66db48a8a7020e03 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 25 Nov 2024 14:17:47 -0800 Subject: [PATCH 136/184] Modified assignment rules to allowed casting to Confidential --- .../confidential/ConfidentialVisitor.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialVisitor.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialVisitor.java index e9a0ec3cda9..59c39fbcdad 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialVisitor.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialVisitor.java @@ -1,9 +1,14 @@ package org.checkerframework.checker.confidential; +import com.sun.source.tree.Tree; import javax.lang.model.element.ExecutableElement; +import org.checkerframework.checker.compilermsgs.qual.CompilerMessageKey; +import org.checkerframework.checker.confidential.qual.Confidential; +import org.checkerframework.checker.formatter.qual.FormatMethod; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.common.basetype.BaseTypeVisitor; +import org.checkerframework.framework.type.AnnotatedTypeMirror; import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType; /** Visitor for the {@link ConfidentialChecker}. */ @@ -25,4 +30,18 @@ public ConfidentialVisitor(BaseTypeChecker checker) { @Override protected void checkConstructorResult( AnnotatedExecutableType constructorType, ExecutableElement constructorElement) {} + + @Override + @FormatMethod + protected boolean commonAssignmentCheck( + AnnotatedTypeMirror varType, + AnnotatedTypeMirror valueType, + Tree valueTree, + @CompilerMessageKey String errorKey, + Object... extraArgs) { + if (varType.hasEffectiveAnnotation(Confidential.class)) { + return true; + } + return super.commonAssignmentCheck(varType, valueType, valueTree, errorKey, extraArgs); + } } From ad423d4d1bd89a87cc1a05cbd306098458da69e3 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 25 Nov 2024 14:18:20 -0800 Subject: [PATCH 137/184] Modified tests for new assignment rule --- .../ConfidentialConcatenation.java | 5 +- .../confidential/NonConfidentialLiterals.java | 124 ------------------ .../confidential/SimpleConfidential.java | 1 - 3 files changed, 1 insertion(+), 129 deletions(-) delete mode 100644 checker/tests/confidential/NonConfidentialLiterals.java diff --git a/checker/tests/confidential/ConfidentialConcatenation.java b/checker/tests/confidential/ConfidentialConcatenation.java index 2cba808a72b..d76ee172095 100644 --- a/checker/tests/confidential/ConfidentialConcatenation.java +++ b/checker/tests/confidential/ConfidentialConcatenation.java @@ -10,7 +10,6 @@ void executeNonConfidential(@NonConfidential String s) {} void executeConfidential(@Confidential String s) {} void concatenation(@NonConfidential String s1, @Confidential String s2) { - // :: error: (assignment) @Confidential String s_1 = s1 + s1; @Confidential String s_2 = s1 + s2; @Confidential String s_3 = s2 + s1; @@ -26,7 +25,6 @@ void concatenation(@NonConfidential String s1, @Confidential String s2) { } void concatenationInvocation(@NonConfidential String s1, @Confidential String s2) { - executeNonConfidential(s1 + s1); // :: error: (argument) executeNonConfidential(s1 + s2); @@ -35,14 +33,13 @@ void concatenationInvocation(@NonConfidential String s1, @Confidential String s2 // :: error: (argument) executeNonConfidential(s2 + s2); - // :: error: (argument) executeConfidential(s1 + s1); executeConfidential(s1 + s2); executeConfidential(s2 + s1); executeConfidential(s2 + s2); } - void compoundConcatenation(@NonConfidential String s1, String s2) { + void compoundConcatenation(@NonConfidential String s1, @Confidential String s2) { s1 += s1; // :: error: (compound.assignment) s1 += s2; diff --git a/checker/tests/confidential/NonConfidentialLiterals.java b/checker/tests/confidential/NonConfidentialLiterals.java deleted file mode 100644 index 417cda0b1eb..00000000000 --- a/checker/tests/confidential/NonConfidentialLiterals.java +++ /dev/null @@ -1,124 +0,0 @@ -import org.checkerframework.checker.confidential.qual.Confidential; -import org.checkerframework.checker.confidential.qual.NonConfidential; - -public class NonConfidentialLiterals { - - void executeString(@NonConfidential String s) {} - - void confidentialString(@Confidential String s) {} - - void unknownString(String s) {} - - void stringLiteral() { - executeString("asdf"); - // :: error: (argument) - confidentialString("asdf"); - unknownString("asdf"); - executeString("132ijkdsf0wenj va2i3"); - // :: error: (argument) - confidentialString("132ijkdsf0wenj va2i3"); - unknownString("132ijkdsf0wenj va2i3"); - } - - void executeBool(@NonConfidential boolean b) {} - - void confidentialBool(@Confidential boolean b) {} - - void unknownBool(boolean b) {} - - void boolLiteral() { - executeBool(true); - // :: error: (argument) - confidentialBool(true); - unknownBool(true); - executeBool(false); - // :: error: (argument) - confidentialBool(false); - unknownBool(false); - } - - void executeChar(@NonConfidential char c) {} - - void confidentialChar(@Confidential char c) {} - - void unknownChar(char c) {} - - void charLiteral() { - executeChar('f'); - // :: error: (argument) - confidentialChar('f'); - unknownChar('f'); - executeChar('a'); - // :: error: (argument) - confidentialChar('a'); - unknownChar('a'); - } - - void executeDouble(@NonConfidential double d) {} - - void confidentialDouble(@Confidential double d) {} - - void unknownDouble(double d) {} - - void doubleLiteral() { - executeDouble(1.204398); - // :: error: (argument) - confidentialDouble(1.204398); - unknownDouble(1.204398); - executeDouble(-0.5209384); - // :: error: (argument) - confidentialDouble(-0.5209384); - unknownDouble(-0.5209384); - } - - void executeFloat(@NonConfidential float f) {} - - void confidentialFloat(@Confidential float f) {} - - void unknownFloat(float f) {} - - void floatLiteral() { - executeFloat(198232.412730f); - // :: error: (argument) - confidentialFloat(198232.412730f); - unknownFloat(198232.412730f); - executeFloat(-0.10938728f); - // :: error: (argument) - confidentialFloat(-0.10938728f); - unknownFloat(-0.10938728f); - } - - void executeInt(@NonConfidential int i) {} - - void confidentialInt(@Confidential int i) {} - - void unknownInt(int i) {} - - void intLiteral() { - executeInt(20987654); - // :: error: (argument) - confidentialInt(20987654); - unknownInt(20987654); - executeInt(-9598653); - // :: error: (argument) - confidentialInt(-9598653); - unknownInt(-9598653); - } - - void executeLong(@NonConfidential long l) {} - - void confidentialLong(@Confidential long l) {} - - void unknownLong(long l) {} - - void longLiteral() { - executeLong(20987654l); - // :: error: (argument) - confidentialLong(20987654l); - unknownLong(20987654l); - executeLong(-9598653l); - // :: error: (argument) - confidentialLong(-9598653l); - unknownLong(-9598653l); - } -} diff --git a/checker/tests/confidential/SimpleConfidential.java b/checker/tests/confidential/SimpleConfidential.java index a3b35e90c9b..0834d3ca9e2 100644 --- a/checker/tests/confidential/SimpleConfidential.java +++ b/checker/tests/confidential/SimpleConfidential.java @@ -9,7 +9,6 @@ void executeConfidential(@Confidential String s) {} void nonConfidentialRef(@NonConfidential String s) { executeNonConfidential(s); - // :: error: (argument) executeConfidential(s); } From a405e328b004f8b8cb01f5947eec0b79c0450730 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 1 Dec 2024 23:47:01 -0800 Subject: [PATCH 138/184] Added PasswordEncoder and UsernamePasswordAuthenticationToken stub file --- .../confidential/ConfidentialChecker.java | 2 ++ .../confidential/PasswordEncoder.astub | 14 ++++++++++++++ .../UsernamePasswordAuthenticationToken.astub | 19 +++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/PasswordEncoder.astub create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/UsernamePasswordAuthenticationToken.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 5187c69eb6b..977c20cacd6 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -24,6 +24,8 @@ "TextView.astub", "AlertDialog.astub", "AbstractAuthenticationTargetUrlRequestHandler.astub", + "UsernamePasswordAuthenticationToken.astub", + "PasswordEncoder.astub", // "PrintStream.astub", "HttpServletResponse.astub", "Cookie.astub" diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/PasswordEncoder.astub b/checker/src/main/java/org/checkerframework/checker/confidential/PasswordEncoder.astub new file mode 100644 index 00000000000..77bac47a435 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/PasswordEncoder.astub @@ -0,0 +1,14 @@ +package org.springframework.security.crypto.password; + +import org.checkerframework.checker.confidential.qual.Confidential; +import org.checkerframework.checker.confidential.qual.UnknownConfidential; + +public interface PasswordEncoder { + @Confidential String encode(@UnknownConfidential CharSequence var1); + + boolean matches(@Confidential CharSequence var1, @Confidential String var2); + + default boolean upgradeEncoding(@Confidential String encodedPassword) { + return false; + } +} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/UsernamePasswordAuthenticationToken.astub b/checker/src/main/java/org/checkerframework/checker/confidential/UsernamePasswordAuthenticationToken.astub new file mode 100644 index 00000000000..99165c25b05 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/UsernamePasswordAuthenticationToken.astub @@ -0,0 +1,19 @@ +package org.springframework.security.authentication; + +import java.util.Collection; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.util.Assert; + +import org.checkerframework.checker.confidential.qual.Confidential; + +public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken { + private static final long serialVersionUID = 550L; + private final Object principal; + private @Confidential Object credentials; + + public UsernamePasswordAuthenticationToken(Object principal, @Confidential Object credentials); + + public UsernamePasswordAuthenticationToken(Object principal, @Confidential Object credentials, Collection authorities); + + public @Confidential Object getCredentials(); +} From 83180d9fe6bd184708fca51fd056afd2f4728acd Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 2 Dec 2024 00:33:04 -0800 Subject: [PATCH 139/184] Revised confidential checker manual --- docs/manual/confidential-checker.tex | 49 ++++++++++++++++------------ 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/docs/manual/confidential-checker.tex b/docs/manual/confidential-checker.tex index 41ed3eafb4d..5fc335ebdd8 100644 --- a/docs/manual/confidential-checker.tex +++ b/docs/manual/confidential-checker.tex @@ -37,11 +37,11 @@ will not be able to be accessed by end users. \item[\refqualclass{checker/confidential/qual}{NonConfidential}] indicates a value that may be exposed to end users, or a location that - may be accessed by end users. It is the default qualifier for literals. + may be accessed by end users. It is the default qualifier. \item[\refqualclass{checker/confidential/qual}{UnknownConfidential}] indicates a value whose confidentiality is unknown. \code{@UnknownConfidential} is a supertype of \code{@Confidential} - and \code{@NonConfidential}. It is the default qualifier for non-literals. + and \code{@NonConfidential}. \item[\refqualclass{checker/confidential/qual}{PolyConfidential}] indicates qualifier polymorphism. For a description of qualifier polymorphism, see Section~\ref{method-qualifier-polymorphism}. @@ -63,24 +63,13 @@ Although parallels could be drawn between the Confidential Checker's \code{@Confidential} annotation and the Taint Checker's \code{@Tainted} annotation (see Section~\ref{tainting-annotations}), it should be noted that -\code{@Confidential} is not ambiguous in the values to which it can be applied. -As a result, while the Confidential Checker (correctly) does not allow -\code{@Confidential} values to be passed to \code{@NonConfidential} sinks, it also -disallows \code{@NonConfidential} values in \code{@Confidential} sinks. The -motivation for this structure was to avoid issues caused by -\href{https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)} -{invariant subtyping}. - -The latter constraint may not constitute desired behavior if, for example, we want -to set a \code{@Confidential} password field to a simple literal (which defaults -to \code{@NonConfidential}). However, in practice, the \code{@NonConfidential} -value would often be concatenated with a \code{@Confidential} value prior to -being passed to the \code{@Confidential} sink, thus converting it to a -\code{@Confidential} value via the type concatenation rules laid out below in -Section~\ref{confidential-checks}. For other cases, \code{@SuppressWarnings} -annotations should be specified to conduct casts between \code{@NonConfidential} -and \code{@Confidential} values. - +there is no subtyping relationship between \code{@Confidential} and +\code{@NonConfidential}. However, the external behavior of these annotations +can strongly resemble that of a supertype and subtype, as casts from the latter +to the former are always permitted (see Section~\ref{confidential-checks}). As +a result, while the Confidential Checker (correctly) does not allow +\code{@Confidential} values to be passed to \code{@NonConfidential} sinks, it does +allow \code{@NonConfidential} values in \code{@Confidential} sinks. \sectionAndLabel{What the Confidential Checker checks}{confidential-checks} @@ -96,10 +85,19 @@ @NonConfidential + @NonConfidential = @NonConfidential \end{Verbatim} +However, casts of any type in the Confidential hierarchy to \code{@Confidential} +are always allowed as they do not pose a risk of sensitive information exposure: +\code{@NonConfidential} to \code{@Confidential} casts only increase stringency, +while \code{@UnknownConfidential} is subtyped by \code{@Confidential}, +\code{@NonConfidential} and can thus be safely cast. This allowance was motivated +by a high percentage of \code{@SuppressWarnings} annotations being written to allow +casts from \code{@NonConfidential} to \code{@Confidential}. + \sectionAndLabel{Library annotations}{confidential-library-annotations} As mentioned prior, the Confidential Checker provides preliminary annotations -for certain public-facing sinks. For instance, the \code{TextView} class for Android +for certain public-facing sinks either in the form of stub files or within the +Checker Framework's annotated JDK. For instance, the \code{TextView} class for Android apps requires that a \code{@NonConfidential CharSequence} should be passed to its \code{setText} method to avoid displaying sensitive information on the user's viewport. @@ -108,3 +106,12 @@ \code{@UnknownConfidential} values and determine which, if any, parts of the value can be safely cast to \code{@NonConfidential} under a \code{@SuppressWarnings} annotation and passed to user-facing sinks. + +It should be noted that, since \code{@NonConfidential} is the default annotation, +developers must be particularly attentive to explicitly annotating their variables +to avoid accidentally passing a secret value to a public-facing sink. For this reason, +it may seem insecure to set \code{@NonConfidential} as the default rather than +\code{@UnknownConfidential} or \code{@Confidential}. However, this implementation +significantly decreases the number of \code{@SuppressWarnings} annotations (and +overall annotations)that the developer must write, as in practice, values are more +often \code{@NonConfidential} than \code{@Confidential}. From 49c49dd921c63ff68aabe7f42bb8ff471579c62a Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 7 Jan 2025 00:43:32 -0800 Subject: [PATCH 140/184] Updated log files to reflect changes to default annotation --- checker/build.gradle | 2 +- ...uthenticationTargetUrlRequestHandler.astub | 7 +- .../checker/confidential/AlertDialog.astub | 100 +- .../checker/confidential/AndroidLog.astub | 30 +- .../checker/confidential/ApacheLog.astub | 26 +- .../confidential/ConfidentialChecker.java | 7 +- .../checker/confidential/Cookie.astub | 11 +- .../checker/confidential/Formatter.astub | 12 - .../checker/confidential/Handler.astub | 16 - .../confidential/HttpServletResponse.astub | 10 +- .../checker/confidential/JavaLogger.astub | 85 - .../checker/confidential/Log4jLogger.astub | 1452 +++++++++-------- .../checker/confidential/PrintStream.astub | 49 - 13 files changed, 876 insertions(+), 931 deletions(-) delete mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/Formatter.astub delete mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/Handler.astub delete mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/JavaLogger.astub delete mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/PrintStream.astub diff --git a/checker/build.gradle b/checker/build.gradle index 7f30cf2c6b8..a2d57aa7f6b 100644 --- a/checker/build.gradle +++ b/checker/build.gradle @@ -1067,7 +1067,7 @@ publishing { checkerPom it artifact checkerJar artifact allSourcesJar - artifact allJavadocJar + // artifact allJavadocJar } } } diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/AbstractAuthenticationTargetUrlRequestHandler.astub b/checker/src/main/java/org/checkerframework/checker/confidential/AbstractAuthenticationTargetUrlRequestHandler.astub index d653501c249..031a3e20db3 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/AbstractAuthenticationTargetUrlRequestHandler.astub +++ b/checker/src/main/java/org/checkerframework/checker/confidential/AbstractAuthenticationTargetUrlRequestHandler.astub @@ -16,11 +16,12 @@ import org.springframework.security.web.util.UrlUtils; import org.springframework.util.Assert; import org.springframework.util.StringUtils; -import org.checkerframework.checker.confidential.qual.NonConfidential; +import org.checkerframework.checker.confidential.qual.UnknownConfidential; public abstract class AbstractAuthenticationTargetUrlRequestHandler { - public void setDefaultTargetUrl(@NonConfidential String defaultTargetUrl); + protected void handle(HttpServletRequest request, HttpServletResponse response, @UnknownConfidential Authentication authentication); - public void setTargetUrlParameter(@NonConfidential String targetUrlParameter); + protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response, + @UnknownConfidential Authentication authentication); } diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/AlertDialog.astub b/checker/src/main/java/org/checkerframework/checker/confidential/AlertDialog.astub index 475b9b868d5..78e48b6f71a 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/AlertDialog.astub +++ b/checker/src/main/java/org/checkerframework/checker/confidential/AlertDialog.astub @@ -27,11 +27,105 @@ import android.widget.ListView; import com.android.internal.R; import com.android.internal.app.AlertController; -import org.checkerframework.checker.confidential.qual.NonConfidential; +import org.checkerframework.checker.confidential.qual.*; public class AlertDialog extends Dialog implements DialogInterface { - public void setMessage(@NonConfidential CharSequence message); + protected AlertDialog(@UnknownConfidential Context context); - public Builder setMessage(@NonConfidential CharSequence message); + protected AlertDialog(@UnknownConfidential Context context, boolean cancelable, + @UnknownConfidential OnCancelListener cancelListener); + + protected AlertDialog(@UnknownConfidential Context context, @StyleRes int themeResId); + + AlertDialog(@UnknownConfidential Context context, @StyleRes int themeResId, + boolean createContextThemeWrapper); + + static @StyleRes int resolveDialogTheme(@UnknownConfidential Context context, + @StyleRes int themeResId); + + public static class Builder { + public @UnknownConfidential Builder(@UnknownConfidential Context context); + + public @UnknownConfidential Builder(@UnknownConfidential Context context, int themeResId); + + public @UnknownConfidential Context getContext(); + + public @UnknownConfidential Builder setTitle(@StringRes int titleId); + + public @UnknownConfidential Builder setTitle(CharSequence title); + + public @UnknownConfidential Builder setCustomTitle(View customTitleView); + + public @UnknownConfidential Builder setMessage(@StringRes int messageId); + + public @UnknownConfidential Builder setMessage(CharSequence message); + + public @UnknownConfidential Builder setIcon(@DrawableRes int iconId); + + public @UnknownConfidential Builder setIcon(Drawable icon); + + public @UnknownConfidential Builder setIconAttribute(@AttrRes int attrId); + + public @UnknownConfidential Builder setPositiveButton(@StringRes int textId, final @UnknownConfidential OnClickListener listener); + + public @UnknownConfidential Builder setPositiveButton(CharSequence text, final @UnknownConfidential OnClickListener listener); + + public @UnknownConfidential Builder setNegativeButton(@StringRes int textId, final @UnknownConfidential OnClickListener listener); + + public @UnknownConfidential Builder setNegativeButton(CharSequence text, final @UnknownConfidential OnClickListener listener); + + public @UnknownConfidential Builder setNeutralButton(@StringRes int textId, final @UnknownConfidential OnClickListener listener); + + public @UnknownConfidential Builder setNeutralButton(CharSequence text, final @UnknownConfidential OnClickListener listener); + + public @UnknownConfidential Builder setCancelable(boolean cancelable); + + public @UnknownConfidential Builder setOnCancelListener(@UnknownConfidential OnCancelListener onCancelListener); + + public @UnknownConfidential Builder setOnDismissListener(@UnknownConfidential OnDismissListener onDismissListener); + + public @UnknownConfidential Builder setOnKeyListener(@UnknownConfidential OnKeyListener onKeyListener); + + public @UnknownConfidential Builder setItems(@ArrayRes int itemsId, final @UnknownConfidential OnClickListener listener); + + public @UnknownConfidential Builder setItems(CharSequence[] items, final @UnknownConfidential OnClickListener listener); + + public @UnknownConfidential Builder setAdapter(final @UnknownConfidential ListAdapter adapter, final @UnknownConfidential OnClickListener listener); + + public @UnknownConfidential Builder setCursor(final @UnknownConfidential Cursor cursor, final @UnknownConfidential OnClickListener listener, + String labelColumn); + + public @UnknownConfidential Builder setMultiChoiceItems(@ArrayRes int itemsId, boolean[] checkedItems, + final @UnknownConfidential OnMultiChoiceClickListener listener); + + public @UnknownConfidential Builder setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, + final @UnknownConfidential OnMultiChoiceClickListener listener); + + public @UnknownConfidential Builder setMultiChoiceItems(@UnknownConfidential Cursor cursor, String isCheckedColumn, String labelColumn, + final @UnknownConfidential OnMultiChoiceClickListener listener); + + public @UnknownConfidential Builder setSingleChoiceItems(@ArrayRes int itemsId, int checkedItem, + final @UnknownConfidential OnClickListener listener); + + public @UnknownConfidential Builder setSingleChoiceItems(@UnknownConfidential Cursor cursor, int checkedItem, String labelColumn, + final @UnknownConfidential OnClickListener listener); + + public @UnknownConfidential Builder setSingleChoiceItems(CharSequence[] items, int checkedItem, final @UnknownConfidential OnClickListener listener); + + public @UnknownConfidential Builder setSingleChoiceItems(@UnknownConfidential ListAdapter adapter, int checkedItem, final @UnknownConfidential OnClickListener listener); + + public @UnknownConfidential Builder setOnItemSelectedListener(final @UnknownConfidential AdapterView.OnItemSelectedListener listener); + + public @UnknownConfidential Builder setView(int layoutResId); + + public @UnknownConfidential Builder setView(View view); + + @UnsupportedAppUsage + public @UnknownConfidential Builder setRecycleOnMeasureEnabled(boolean enabled); + + public @UnknownConfidential AlertDialog create(); + + public @UnknownConfidential AlertDialog show(); + } } diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/AndroidLog.astub b/checker/src/main/java/org/checkerframework/checker/confidential/AndroidLog.astub index afbe2c27478..e95219dd955 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/AndroidLog.astub +++ b/checker/src/main/java/org/checkerframework/checker/confidential/AndroidLog.astub @@ -16,29 +16,35 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.net.UnknownHostException; -import org.checkerframework.checker.confidential.qual.NonConfidential; +import org.checkerframework.checker.confidential.qual.*; public final class Log { - public static int d(@Nullable @NonConfidential String tag, @NonNull @NonConfidential String msg); + public static int d(@Nullable String tag, @Nullable String msg, @Nullable @UnknownConfidential Throwable tr); - public static int d(@Nullable @NonConfidential String tag, @Nullable @NonConfidential String msg, @Nullable @NonConfidential Throwable tr); + public static int w(@Nullable String tag, @Nullable String msg, @Nullable @UnknownConfidential Throwable tr); - public static int w(@Nullable @NonConfidential String tag, @NonNull @NonConfidential String msg); + public static int w(@Nullable String tag, @Nullable @UnknownConfidential Throwable tr); - public static int w(@Nullable @NonConfidential String tag, @Nullable @NonConfidential String msg, @Nullable @NonConfidential Throwable tr); + public static int v(@Nullable String tag, @Nullable String msg, @Nullable @UnknownConfidential Throwable tr); - public static int w(@Nullable @NonConfidential String tag, @Nullable @NonConfidential Throwable tr); + public static int i(@Nullable String tag, @Nullable String msg, @Nullable @UnknownConfidential Throwable tr); - public static int v(@Nullable @NonConfidential String tag, @NonNull @NonConfidential String msg); + public static int e(@Nullable String tag, @Nullable String msg, @Nullable @UnknownConfidential Throwable tr); - public static int v(@Nullable @NonConfidential String tag, @Nullable @NonConfidential String msg, @Nullable @NonConfidential Throwable tr); + public static int wtf(@Nullable String tag, @NonNull @UnknownConfidential Throwable tr); - public static int i(@Nullable @NonConfidential String tag, @NonNull @NonConfidential String msg); + public static int wtf(@Nullable String tag, @Nullable String msg, @Nullable @UnknownConfidential Throwable tr); - public static int i(@Nullable @NonConfidential String tag, @Nullable @NonConfidential String msg, @Nullable @NonConfidential Throwable tr); + static int wtf(int logId, @Nullable String tag, @Nullable String msg, @Nullable @UnknownConfidential Throwable tr, + boolean localStack, boolean system); - public static int e(@Nullable @NonConfidential String tag, @NonNull @NonConfidential String msg); + @NonNull + public static @UnknownConfidential TerribleFailureHandler setWtfHandler(@NonNull @UnknownConfidential TerribleFailureHandler handler); - public static int e(@Nullable @NonConfidential String tag, @Nullable @NonConfidential String msg, @Nullable @NonConfidential Throwable tr); + @NonNull + public static String getStackTraceString(@Nullable @UnknownConfidential Throwable tr); + + public static int printlns(int bufID, int priority, @Nullable String tag, @NonNull String msg, + @Nullable @UnknownConfidential Throwable tr); } diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ApacheLog.astub b/checker/src/main/java/org/checkerframework/checker/confidential/ApacheLog.astub index cdfb443e45b..5666785ebc4 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ApacheLog.astub +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ApacheLog.astub @@ -1,30 +1,18 @@ package org.apache.commons.logging; -import org.checkerframework.checker.confidential.qual.NonConfidential; +import org.checkerframework.checker.confidential.qual.*; public interface Log { - void debug(@NonConfidential Object var1); + void debug(Object var1, Throwable var2); - void debug(@NonConfidential Object var1, @NonConfidential Throwable var2); + void error(Object var1, Throwable var2); - void error(@NonConfidential Object var1); + void fatal(Object var1, Throwable var2); - void error(@NonConfidential Object var1, @NonConfidential Throwable var2); + void info(Object var1, Throwable var2); - void fatal(@NonConfidential Object var1); + void trace(Object var1, Throwable var2); - void fatal(@NonConfidential Object var1, @NonConfidential Throwable var2); - - void info(@NonConfidential Object var1); - - void info(@NonConfidential Object var1, @NonConfidential Throwable var2); - - void trace(@NonConfidential Object var1); - - void trace(@NonConfidential Object var1, @NonConfidential Throwable var2); - - void warn(@NonConfidential Object var1); - - void warn(@NonConfidential Object var1, @NonConfidential Throwable var2); + void warn(Object var1, Throwable var2); } diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 977c20cacd6..0c7d4dae04f 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -16,9 +16,6 @@ "Log4jLogger.astub", "AndroidLog.astub", "Slf4jLogger.astub", - // "Handler.astub", - // "JavaLogger.astub", - // "Formatter.astub", "ApacheLog.astub", "Toast.astub", "TextView.astub", @@ -26,9 +23,9 @@ "AbstractAuthenticationTargetUrlRequestHandler.astub", "UsernamePasswordAuthenticationToken.astub", "PasswordEncoder.astub", - // "PrintStream.astub", "HttpServletResponse.astub", - "Cookie.astub" + "Cookie.astub", + "UserDetails.astub" }) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/Cookie.astub b/checker/src/main/java/org/checkerframework/checker/confidential/Cookie.astub index 78b7dae7341..d585d02e7e2 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/Cookie.astub +++ b/checker/src/main/java/org/checkerframework/checker/confidential/Cookie.astub @@ -1,17 +1,14 @@ -package javax.servlet.http; +package jakarta.servlet.http; import java.io.Serializable; import java.text.MessageFormat; import java.util.Locale; import java.util.ResourceBundle; -import org.checkerframework.checker.confidential.qual.NonConfidential; +import org.checkerframework.checker.confidential.qual.*; public class Cookie implements Cloneable, Serializable { - public void setComment(@NonConfidential String purpose); - - public void setDomain(@NonConfidential String domain); - - public void setValue(@NonConfidential String newValue); + @Override + public boolean equals(@UnknownConfidential Object obj); } diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/Formatter.astub b/checker/src/main/java/org/checkerframework/checker/confidential/Formatter.astub deleted file mode 100644 index cfb0ceaff96..00000000000 --- a/checker/src/main/java/org/checkerframework/checker/confidential/Formatter.astub +++ /dev/null @@ -1,12 +0,0 @@ -package java.util.logging; - -import java.text.MessageFormat; -import java.util.MissingResourceException; -import java.util.ResourceBundle; - -import org.checkerframework.checker.confidential.qual.NonConfidential; - -public abstract class Formatter { - - public abstract String format(@NonConfidential LogRecord var1); -} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/Handler.astub b/checker/src/main/java/org/checkerframework/checker/confidential/Handler.astub deleted file mode 100644 index a81d2af6d0a..00000000000 --- a/checker/src/main/java/org/checkerframework/checker/confidential/Handler.astub +++ /dev/null @@ -1,16 +0,0 @@ -package java.util.logging; - -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; -import java.nio.charset.IllegalCharsetNameException; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Objects; - -import org.checkerframework.checker.confidential.qual.NonConfidential; - -public abstract class Handler { - - public abstract void publish(@NonConfidential LogRecord var1); -} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/HttpServletResponse.astub b/checker/src/main/java/org/checkerframework/checker/confidential/HttpServletResponse.astub index 80b50ece07f..a0f737f4fbd 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/HttpServletResponse.astub +++ b/checker/src/main/java/org/checkerframework/checker/confidential/HttpServletResponse.astub @@ -1,4 +1,4 @@ -package javax.servlet.http; +package jakarta.servlet.http; import java.io.IOException; import java.util.Collection; @@ -6,11 +6,13 @@ import java.util.Map; import java.util.function.Supplier; import javax.servlet.ServletResponse; -import org.checkerframework.checker.confidential.qual.NonConfidential; +import org.checkerframework.checker.confidential.qual.*; public interface HttpServletResponse extends ServletResponse { - void sendRedirect(@NonConfidential String var1); + void addCookie(@UnknownConfidential Cookie cookie); - void sendError(int var1, @NonConfidential String var2); + default void setTrailerFields(@UnknownConfidential Supplier> supplier); + + default @UnknownConfidential Supplier> getTrailerFields(); } diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/JavaLogger.astub b/checker/src/main/java/org/checkerframework/checker/confidential/JavaLogger.astub deleted file mode 100644 index 1027520f048..00000000000 --- a/checker/src/main/java/org/checkerframework/checker/confidential/JavaLogger.astub +++ /dev/null @@ -1,85 +0,0 @@ -package java.util.logging; - -import java.lang.ref.WeakReference; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.Locale; -import java.util.MissingResourceException; -import java.util.Objects; -import java.util.ResourceBundle; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.function.Supplier; -import jdk.internal.logger.DefaultLoggerFinder; -import jdk.internal.misc.JavaUtilResourceBundleAccess; -import jdk.internal.misc.SharedSecrets; -import jdk.internal.reflect.CallerSensitive; -import jdk.internal.reflect.Reflection; - -import org.checkerframework.checker.confidential.qual.NonConfidential; - -public class Logger { - - public void config(@NonConfidential String msg); - - public void config(@NonConfidential Supplier msgSupplier); - - public void fine(@NonConfidential String msg); - - public void fine(@NonConfidential Supplier msgSupplier); - - public void finer(@NonConfidential String msg); - - public void finer(@NonConfidential Supplier msgSupplier); - - public void finest(@NonConfidential String msg); - - public void finest(@NonConfidential Supplier msgSupplier); - - public void info(@NonConfidential String msg); - - public void info(@NonConfidential Supplier msgSupplier); - - public void log(@NonConfidential LogRecord record); - - public void log(Level level, @NonConfidential String msg); - - public void log(Level level, @NonConfidential Supplier msgSupplier); - - public void log(Level level, @NonConfidential String msg, Object param1); - - public void log(Level level, @NonConfidential String msg, Object[] params); - - public void log(Level level, @NonConfidential String msg, @NonConfidential Throwable thrown); - - public void log(Level level, @NonConfidential Throwable thrown, @NonConfidential Supplier msgSupplier); - - public void logp(Level level, @NonConfidential String sourceClass, @NonConfidential String sourceMethod, @NonConfidential String msg); - - public void logp(Level level, @NonConfidential String sourceClass, @NonConfidential String sourceMethod, @NonConfidential Supplier msgSupplier); - - public void logp(Level level, @NonConfidential String sourceClass, @NonConfidential String sourceMethod, @NonConfidential String msg, Object param1); - - public void logp(Level level, @NonConfidential String sourceClass, @NonConfidential String sourceMethod, @NonConfidential String msg, Object[] params); - - public void logp(Level level, @NonConfidential String sourceClass, @NonConfidential String sourceMethod, @NonConfidential String msg, @NonConfidential Throwable thrown); - - public void logp(Level level, @NonConfidential String sourceClass, @NonConfidential String sourceMethod, @NonConfidential Throwable thrown, @NonConfidential Supplier msgSupplier); - - public void logrb(Level level, @NonConfidential String sourceClass, @NonConfidential String sourceMethod, ResourceBundle bundle, @NonConfidential String msg, Object... params); - - public void logrb(Level level, ResourceBundle bundle, @NonConfidential String msg, Object... params); - - public void logrb(Level level, @NonConfidential String sourceClass, @NonConfidential String sourceMethod, ResourceBundle bundle, @NonConfidential String msg, @NonConfidential Throwable thrown); - - public void logrb(Level level, ResourceBundle bundle, @NonConfidential String msg, @NonConfidential Throwable thrown); - - public void severe(@NonConfidential String msg); - - public void severe(@NonConfidential Supplier msgSupplier); - - public void warning(@NonConfidential String msg); - - public void warning(@NonConfidential Supplier msgSupplier); -} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/Log4jLogger.astub b/checker/src/main/java/org/checkerframework/checker/confidential/Log4jLogger.astub index 1b85cdeeedb..a4d5d85fcb1 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/Log4jLogger.astub +++ b/checker/src/main/java/org/checkerframework/checker/confidential/Log4jLogger.astub @@ -8,1117 +8,1139 @@ import org.apache.logging.log4j.message.MessageFactory2; import org.apache.logging.log4j.util.MessageSupplier; import org.apache.logging.log4j.util.Supplier; -import org.checkerframework.checker.confidential.qual.NonConfidential; +import org.checkerframework.checker.confidential.qual.*; public interface Logger { - void error(@NonConfidential Marker marker, @NonConfidential Message message); + void error(@UnknownConfidential Marker marker, Message message); - void error(@NonConfidential Marker marker, @NonConfidential Message message, @NonConfidential Throwable throwable); + void error(@UnknownConfidential Marker marker, Message message, @UnknownConfidential Throwable throwable); - void error(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier); + void error(@UnknownConfidential Marker marker, @UnknownConfidential MessageSupplier messageSupplier); - void error(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + void error(@UnknownConfidential Marker marker, @UnknownConfidential MessageSupplier messageSupplier, @UnknownConfidential Throwable throwable); - void error(@NonConfidential Marker marker, @NonConfidential CharSequence message); + void error(@UnknownConfidential Marker marker, CharSequence message); - void error(@NonConfidential Marker marker, @NonConfidential CharSequence message, @NonConfidential Throwable throwable); + void error(@UnknownConfidential Marker marker, CharSequence message, @UnknownConfidential Throwable throwable); - void error(@NonConfidential Marker marker, @NonConfidential Object message); + void error(@UnknownConfidential Marker marker, Object message); - void error(@NonConfidential Marker marker, @NonConfidential Object message, @NonConfidential Throwable throwable); + void error(@UnknownConfidential Marker marker, Object message, @UnknownConfidential Throwable throwable); - void error(@NonConfidential Marker marker, @NonConfidential String message); + void error(@UnknownConfidential Marker marker, String message); - void error(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Object... params); + void error(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object... params); - void error(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + void error(@UnknownConfidential Marker marker, String message, @UnknownConfidential Supplier... paramSuppliers); - void error(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Throwable throwable); + void error(@UnknownConfidential Marker marker, String message, @UnknownConfidential Throwable throwable); - void error(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier); + void error(@UnknownConfidential Marker marker, @UnknownConfidential Supplier messageSupplier); - void error(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + void error(@UnknownConfidential Marker marker, @UnknownConfidential Supplier messageSupplier, @UnknownConfidential Throwable throwable); - void error(@NonConfidential Message message); + void error(Message message); - void error(@NonConfidential Message message, @NonConfidential Throwable throwable); + void error(Message message, @UnknownConfidential Throwable throwable); - void error(@NonConfidential MessageSupplier messageSupplier); + void error(@UnknownConfidential MessageSupplier messageSupplier); - void error(@NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + void error(@UnknownConfidential MessageSupplier messageSupplier, @UnknownConfidential Throwable throwable); - void error(@NonConfidential CharSequence message); + void error(CharSequence message); - void error(@NonConfidential CharSequence message, @NonConfidential Throwable throwable); + void error(CharSequence message, @UnknownConfidential Throwable throwable); - void error(@NonConfidential Object message); + void error(Object message); - void error(@NonConfidential Object message, @NonConfidential Throwable throwable); + void error(Object message, @UnknownConfidential Throwable throwable); - void error(@NonConfidential String message); + void error(String message); - void error(@NonConfidential String message, @NonConfidential Object... params); + void error(String message, @UnknownConfidential Object... params); - void error(@NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + void error(String message, @UnknownConfidential Supplier... paramSuppliers); - void error(@NonConfidential String message, @NonConfidential Throwable throwable); + void error(String message, @UnknownConfidential Throwable throwable); - void error(@NonConfidential Supplier messageSupplier); + void error(@UnknownConfidential Supplier messageSupplier); - void error(@NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + void error(@UnknownConfidential Supplier messageSupplier, @UnknownConfidential Throwable throwable); - void error(@NonConfidential Marker marker, @NonConfidential String message, Object p0); + void error(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0); - void error(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1); + void error(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1); - void error(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2); + void error(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2); - void error(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + void error(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3); - void error(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + void error(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4); - void error(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + void error(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5); void error( - @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + @UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6); void error( - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7); void error( - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8); void error( - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8, - Object p9); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8, + @UnknownConfidential Object p9); - void error(@NonConfidential String message, Object p0); + void error(String message, @UnknownConfidential Object p0); - void error(@NonConfidential String message, Object p0, Object p1); + void error(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1); - void error(@NonConfidential String message, Object p0, Object p1, Object p2); + void error(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2); - void error(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + void error(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3); - void error(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + void error(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4); - void error(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + void error(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5); - void error(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + void error(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6); - void error(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7); + void error(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6, @UnknownConfidential Object p7); void error( - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8); + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8); void error( - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8, - Object p9); + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8, + @UnknownConfidential Object p9); - void info(@NonConfidential Marker marker, @NonConfidential Message message); + void info(@UnknownConfidential Marker marker, Message message); - void info(@NonConfidential Marker marker, @NonConfidential Message message, @NonConfidential Throwable throwable); + void info(@UnknownConfidential Marker marker, Message message, @UnknownConfidential Throwable throwable); - void info(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier); + void info(@UnknownConfidential Marker marker, @UnknownConfidential MessageSupplier messageSupplier); - void info(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + void info(@UnknownConfidential Marker marker, @UnknownConfidential MessageSupplier messageSupplier, @UnknownConfidential Throwable throwable); - void info(@NonConfidential Marker marker, @NonConfidential CharSequence message); + void info(@UnknownConfidential Marker marker, CharSequence message); - void info(@NonConfidential Marker marker, @NonConfidential CharSequence message, @NonConfidential Throwable throwable); + void info(@UnknownConfidential Marker marker, CharSequence message, @UnknownConfidential Throwable throwable); - void info(@NonConfidential Marker marker, @NonConfidential Object message); + void info(@UnknownConfidential Marker marker, Object message); - void info(@NonConfidential Marker marker, @NonConfidential Object message, @NonConfidential Throwable throwable); + void info(@UnknownConfidential Marker marker, Object message, @UnknownConfidential Throwable throwable); - void info(@NonConfidential Marker marker, @NonConfidential String message); + void info(@UnknownConfidential Marker marker, String message); - void info(@NonConfidential Marker marker, @NonConfidential String message, Object... params); + void info(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object... params); - void info(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + void info(@UnknownConfidential Marker marker, String message, @UnknownConfidential Supplier... paramSuppliers); - void info(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Throwable throwable); + void info(@UnknownConfidential Marker marker, String message, @UnknownConfidential Throwable throwable); - void info(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier); + void info(@UnknownConfidential Marker marker, @UnknownConfidential Supplier messageSupplier); - void info(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + void info(@UnknownConfidential Marker marker, @UnknownConfidential Supplier messageSupplier, @UnknownConfidential Throwable throwable); - void info(@NonConfidential Message message); + void info(Message message); - void info(@NonConfidential Message message, @NonConfidential Throwable throwable); + void info(Message message, @UnknownConfidential Throwable throwable); - void info(@NonConfidential MessageSupplier messageSupplier); + void info(@UnknownConfidential MessageSupplier messageSupplier); - void info(@NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + void info(@UnknownConfidential MessageSupplier messageSupplier, @UnknownConfidential Throwable throwable); - void info(@NonConfidential CharSequence message); + void info(CharSequence message); - void info(@NonConfidential CharSequence message, @NonConfidential Throwable throwable); + void info(CharSequence message, @UnknownConfidential Throwable throwable); - void info(@NonConfidential Object message); + void info(Object message); - void info(@NonConfidential Object message, @NonConfidential Throwable throwable); + void info(Object message, @UnknownConfidential Throwable throwable); - void info(@NonConfidential String message); + void info(String message); - void info(@NonConfidential String message, Object... params); + void info(String message, @UnknownConfidential Object... params); - void info(@NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + void info(String message, @UnknownConfidential Supplier... paramSuppliers); - void info(@NonConfidential String message, @NonConfidential Throwable throwable); + void info(String message, @UnknownConfidential Throwable throwable); - void info(@NonConfidential Supplier messageSupplier); + void info(@UnknownConfidential Supplier messageSupplier); - void info(@NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + void info(@UnknownConfidential Supplier messageSupplier, @UnknownConfidential Throwable throwable); - void info(@NonConfidential Marker marker, @NonConfidential String message, Object p0); + void info(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0); - void info(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1); + void info(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1); - void info(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2); + void info(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2); - void info(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + void info(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3); - void info(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + void info(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4); - void info(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + void info(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5); void info( - @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + @UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6); void info( - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7); void info( - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8); void info( - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8, - Object p9); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8, + @UnknownConfidential Object p9); - void info(@NonConfidential String message, Object p0); + void info(String message, @UnknownConfidential Object p0); - void info(@NonConfidential String message, Object p0, Object p1); + void info(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1); - void info(@NonConfidential String message, Object p0, Object p1, Object p2); + void info(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2); - void info(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + void info(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3); - void info(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + void info(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4); - void info(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + void info(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5); - void info(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + void info(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6); - void info(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7); + void info(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6, @UnknownConfidential Object p7); void info( - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8); + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8); void info( - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8, - Object p9); + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8, + @UnknownConfidential Object p9); - void catching(Level level, @NonConfidential Throwable throwable); + void catching(Level level, @UnknownConfidential Throwable throwable); - void catching(@NonConfidential Throwable throwable); + void catching(@UnknownConfidential Throwable throwable); - void debug(@NonConfidential Marker marker, @NonConfidential Message message); + void debug(@UnknownConfidential Marker marker, Message message); - void debug(@NonConfidential Marker marker, @NonConfidential Message message, @NonConfidential Throwable throwable); + void debug(@UnknownConfidential Marker marker, Message message, @UnknownConfidential Throwable throwable); - void debug(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier); + void debug(@UnknownConfidential Marker marker, @UnknownConfidential MessageSupplier messageSupplier); - void debug(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + void debug(@UnknownConfidential Marker marker, @UnknownConfidential MessageSupplier messageSupplier, @UnknownConfidential Throwable throwable); - void debug(@NonConfidential Marker marker, @NonConfidential CharSequence message); + void debug(@UnknownConfidential Marker marker, CharSequence message); - void debug(@NonConfidential Marker marker, @NonConfidential CharSequence message, @NonConfidential Throwable throwable); + void debug(@UnknownConfidential Marker marker, CharSequence message, @UnknownConfidential Throwable throwable); - void debug(@NonConfidential Marker marker, @NonConfidential Object message); + void debug(@UnknownConfidential Marker marker, Object message); - void debug(@NonConfidential Marker marker, @NonConfidential Object message, @NonConfidential Throwable throwable); + void debug(@UnknownConfidential Marker marker, Object message, @UnknownConfidential Throwable throwable); - void debug(@NonConfidential Marker marker, @NonConfidential String message); + void debug(@UnknownConfidential Marker marker, String message); - void debug(@NonConfidential Marker marker, @NonConfidential String message, Object... params); + void debug(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object... params); - void debug(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + void debug(@UnknownConfidential Marker marker, String message, @UnknownConfidential Supplier... paramSuppliers); - void debug(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Throwable throwable); + void debug(@UnknownConfidential Marker marker, String message, @UnknownConfidential Throwable throwable); - void debug(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier); + void debug(@UnknownConfidential Marker marker, @UnknownConfidential Supplier messageSupplier); - void debug(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + void debug(@UnknownConfidential Marker marker, @UnknownConfidential Supplier messageSupplier, @UnknownConfidential Throwable throwable); - void debug(@NonConfidential Message message); + void debug(Message message); - void debug(@NonConfidential Message message, @NonConfidential Throwable throwable); + void debug(Message message, @UnknownConfidential Throwable throwable); - void debug(@NonConfidential MessageSupplier messageSupplier); + void debug(@UnknownConfidential MessageSupplier messageSupplier); - void debug(@NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + void debug(@UnknownConfidential MessageSupplier messageSupplier, @UnknownConfidential Throwable throwable); - void debug(@NonConfidential CharSequence message); + void debug(CharSequence message); - void debug(@NonConfidential CharSequence message, @NonConfidential Throwable throwable); + void debug(CharSequence message, @UnknownConfidential Throwable throwable); - void debug(@NonConfidential Object message); + void debug(Object message); - void debug(@NonConfidential Object message, @NonConfidential Throwable throwable); + void debug(Object message, @UnknownConfidential Throwable throwable); - void debug(@NonConfidential String message); + void debug(String message); - void debug(@NonConfidential String message, Object... params); + void debug(String message, @UnknownConfidential Object... params); - void debug(@NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + void debug(String message, @UnknownConfidential Supplier... paramSuppliers); - void debug(@NonConfidential String message, @NonConfidential Throwable throwable); + void debug(String message, @UnknownConfidential Throwable throwable); - void debug(@NonConfidential Supplier messageSupplier); + void debug(@UnknownConfidential Supplier messageSupplier); - void debug(@NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + void debug(@UnknownConfidential Supplier messageSupplier, @UnknownConfidential Throwable throwable); - void debug(@NonConfidential Marker marker, @NonConfidential String message, Object p0); + void debug(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0); - void debug(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1); + void debug(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1); - void debug(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2); + void debug(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2); - void debug(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + void debug(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3); - void debug(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + void debug(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4); - void debug(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + void debug(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5); void debug( - @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + @UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6); void debug( - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7); void debug( - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8); void debug( - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8, - Object p9); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8, + @UnknownConfidential Object p9); - void debug(@NonConfidential String message, Object p0); + void debug(String message, @UnknownConfidential Object p0); - void debug(@NonConfidential String message, Object p0, Object p1); + void debug(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1); - void debug(@NonConfidential String message, Object p0, Object p1, Object p2); + void debug(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2); - void debug(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + void debug(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3); - void debug(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + void debug(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4); - void debug(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + void debug(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5); - void debug(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + void debug(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6); - void debug(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7); + void debug(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6, @UnknownConfidential Object p7); void debug( - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8); + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8); void debug( - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8, - Object p9); + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8, + @UnknownConfidential Object p9); - void fatal(@NonConfidential Marker marker, @NonConfidential Message message); + void fatal(@UnknownConfidential Marker marker, Message message); - void fatal(@NonConfidential Marker marker, @NonConfidential Message message, @NonConfidential Throwable throwable); + void fatal(@UnknownConfidential Marker marker, Message message, @UnknownConfidential Throwable throwable); - void fatal(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier); + void fatal(@UnknownConfidential Marker marker, @UnknownConfidential MessageSupplier messageSupplier); - void fatal(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + void fatal(@UnknownConfidential Marker marker, @UnknownConfidential MessageSupplier messageSupplier, @UnknownConfidential Throwable throwable); - void fatal(@NonConfidential Marker marker, @NonConfidential CharSequence message); + void fatal(@UnknownConfidential Marker marker, CharSequence message); - void fatal(@NonConfidential Marker marker, @NonConfidential CharSequence message, @NonConfidential Throwable throwable); + void fatal(@UnknownConfidential Marker marker, CharSequence message, @UnknownConfidential Throwable throwable); - void fatal(@NonConfidential Marker marker, @NonConfidential Object message); + void fatal(@UnknownConfidential Marker marker, Object message); - void fatal(@NonConfidential Marker marker, @NonConfidential Object message, @NonConfidential Throwable throwable); + void fatal(@UnknownConfidential Marker marker, Object message, @UnknownConfidential Throwable throwable); - void fatal(@NonConfidential Marker marker, @NonConfidential String message); + void fatal(@UnknownConfidential Marker marker, String message); - void fatal(@NonConfidential Marker marker, @NonConfidential String message, Object... params); + void fatal(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object... params); - void fatal(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + void fatal(@UnknownConfidential Marker marker, String message, @UnknownConfidential Supplier... paramSuppliers); - void fatal(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Throwable throwable); + void fatal(@UnknownConfidential Marker marker, String message, @UnknownConfidential Throwable throwable); - void fatal(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier); + void fatal(@UnknownConfidential Marker marker, @UnknownConfidential Supplier messageSupplier); - void fatal(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + void fatal(@UnknownConfidential Marker marker, @UnknownConfidential Supplier messageSupplier, @UnknownConfidential Throwable throwable); - void fatal(@NonConfidential Message message); + void fatal(Message message); - void fatal(@NonConfidential Message message, @NonConfidential Throwable throwable); + void fatal(Message message, @UnknownConfidential Throwable throwable); - void fatal(@NonConfidential MessageSupplier messageSupplier); + void fatal(@UnknownConfidential MessageSupplier messageSupplier); - void fatal(@NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + void fatal(@UnknownConfidential MessageSupplier messageSupplier, @UnknownConfidential Throwable throwable); - void fatal(@NonConfidential CharSequence message); + void fatal(CharSequence message); - void fatal(@NonConfidential CharSequence message, @NonConfidential Throwable throwable); + void fatal(CharSequence message, @UnknownConfidential Throwable throwable); - void fatal(@NonConfidential Object message); + void fatal(Object message); - void fatal(@NonConfidential Object message, @NonConfidential Throwable throwable); + void fatal(Object message, @UnknownConfidential Throwable throwable); - void fatal(@NonConfidential String message); + void fatal(String message); - void fatal(@NonConfidential String message, Object... params); + void fatal(String message, @UnknownConfidential Object... params); - void fatal(@NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + void fatal(String message, @UnknownConfidential Supplier... paramSuppliers); - void fatal(@NonConfidential String message, @NonConfidential Throwable throwable); + void fatal(String message, @UnknownConfidential Throwable throwable); - void fatal(@NonConfidential Supplier messageSupplier); + void fatal(@UnknownConfidential Supplier messageSupplier); - void fatal(@NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + void fatal(@UnknownConfidential Supplier messageSupplier, @UnknownConfidential Throwable throwable); - void fatal(@NonConfidential Marker marker, @NonConfidential String message, Object p0); + void fatal(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0); - void fatal(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1); + void fatal(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1); - void fatal(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2); + void fatal(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2); - void fatal(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + void fatal(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3); - void fatal(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + void fatal(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4); - void fatal(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + void fatal(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5); void fatal( - @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + @UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6); void fatal( - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7); void fatal( - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8); void fatal( - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8, - Object p9); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8, + @UnknownConfidential Object p9); - void fatal(@NonConfidential String message, Object p0); + void fatal(String message, @UnknownConfidential Object p0); - void fatal(@NonConfidential String message, Object p0, Object p1); + void fatal(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1); - void fatal(@NonConfidential String message, Object p0, Object p1, Object p2); + void fatal(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2); - void fatal(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + void fatal(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3); - void fatal(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + void fatal(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4); - void fatal(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + void fatal(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5); - void fatal(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + void fatal(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6); - void fatal(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7); + void fatal(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6, @UnknownConfidential Object p7); void fatal( - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8); + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8); void fatal( - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8, - Object p9); + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8, + @UnknownConfidential Object p9); - void log(Level level, @NonConfidential Marker marker, @NonConfidential Message message); + void log(Level level, @UnknownConfidential Marker marker, Message message); - void log(Level level, @NonConfidential Marker marker, @NonConfidential Message message, @NonConfidential Throwable throwable); + void log(Level level, @UnknownConfidential Marker marker, Message message, @UnknownConfidential Throwable throwable); - void log(Level level, @NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier); + void log(Level level, @UnknownConfidential Marker marker, @UnknownConfidential MessageSupplier messageSupplier); - void log(Level level, @NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + void log(Level level, @UnknownConfidential Marker marker, @UnknownConfidential MessageSupplier messageSupplier, @UnknownConfidential Throwable throwable); - void log(Level level, @NonConfidential Marker marker, @NonConfidential CharSequence message); + void log(Level level, @UnknownConfidential Marker marker, CharSequence message); - void log(Level level, @NonConfidential Marker marker, @NonConfidential CharSequence message, @NonConfidential Throwable throwable); + void log(Level level, @UnknownConfidential Marker marker, CharSequence message, @UnknownConfidential Throwable throwable); - void log(Level level, @NonConfidential Marker marker, @NonConfidential Object message); + void log(Level level, @UnknownConfidential Marker marker, Object message); - void log(Level level, @NonConfidential Marker marker, @NonConfidential Object message, @NonConfidential Throwable throwable); + void log(Level level, @UnknownConfidential Marker marker, Object message, @UnknownConfidential Throwable throwable); - void log(Level level, @NonConfidential Marker marker, @NonConfidential String message); + void log(Level level, @UnknownConfidential Marker marker, String message); - void log(Level level, @NonConfidential Marker marker, @NonConfidential String message, Object... params); + void log(Level level, @UnknownConfidential Marker marker, String message, @UnknownConfidential Object... params); - void log(Level level, @NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + void log(Level level, @UnknownConfidential Marker marker, String message, @UnknownConfidential Supplier... paramSuppliers); - void log(Level level, @NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Throwable throwable); + void log(Level level, @UnknownConfidential Marker marker, String message, @UnknownConfidential Throwable throwable); - void log(Level level, @NonConfidential Marker marker, @NonConfidential Supplier messageSupplier); + void log(Level level, @UnknownConfidential Marker marker, @UnknownConfidential Supplier messageSupplier); - void log(Level level, @NonConfidential Marker marker, @NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + void log(Level level, @UnknownConfidential Marker marker, @UnknownConfidential Supplier messageSupplier, @UnknownConfidential Throwable throwable); - void log(Level level, @NonConfidential Message message); + void log(Level level, Message message); - void log(Level level, @NonConfidential Message message, @NonConfidential Throwable throwable); + void log(Level level, Message message, @UnknownConfidential Throwable throwable); - void log(Level level, @NonConfidential MessageSupplier messageSupplier); + void log(Level level, @UnknownConfidential MessageSupplier messageSupplier); - void log(Level level, @NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + void log(Level level, @UnknownConfidential MessageSupplier messageSupplier, @UnknownConfidential Throwable throwable); - void log(Level level, @NonConfidential CharSequence message); + void log(Level level, CharSequence message); - void log(Level level, @NonConfidential CharSequence message, @NonConfidential Throwable throwable); + void log(Level level, CharSequence message, @UnknownConfidential Throwable throwable); - void log(Level level, @NonConfidential Object message); + void log(Level level, Object message); - void log(Level level, @NonConfidential Object message, @NonConfidential Throwable throwable); + void log(Level level, Object message, @UnknownConfidential Throwable throwable); - void log(Level level, @NonConfidential String message); + void log(Level level, String message); - void log(Level level, @NonConfidential String message, Object... params); + void log(Level level, String message, @UnknownConfidential Object... params); - void log(Level level, @NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + void log(Level level, String message, @UnknownConfidential Supplier... paramSuppliers); - void log(Level level, @NonConfidential String message, @NonConfidential Throwable throwable); + void log(Level level, String message, @UnknownConfidential Throwable throwable); - void log(Level level, @NonConfidential Supplier messageSupplier); + void log(Level level, @UnknownConfidential Supplier messageSupplier); - void log(Level level, @NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + void log(Level level, @UnknownConfidential Supplier messageSupplier, @UnknownConfidential Throwable throwable); - void log(Level level, @NonConfidential Marker marker, @NonConfidential String message, Object p0); + void log(Level level, @UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0); - void log(Level level, @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1); + void log(Level level, @UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1); - void log(Level level, @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2); + void log(Level level, @UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2); - void log(Level level, @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + void log(Level level, @UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3); - void log(Level level, @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + void log(Level level, @UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4); void log( Level level, - Marker marker, + @UnknownConfidential Marker marker, String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5); + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5); void log( Level level, - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6); void log( Level level, - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7); void log( Level level, - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8); void log( Level level, - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8, - Object p9); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8, + @UnknownConfidential Object p9); - void log(Level level, @NonConfidential String message, Object p0); + void log(Level level, String message, @UnknownConfidential Object p0); - void log(Level level, @NonConfidential String message, Object p0, Object p1); + void log(Level level, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1); - void log(Level level, @NonConfidential String message, Object p0, Object p1, Object p2); + void log(Level level, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2); - void log(Level level, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + void log(Level level, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3); - void log(Level level, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + void log(Level level, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4); - void log(Level level, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + void log(Level level, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5); - void log(Level level, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + void log(Level level, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6); void log( Level level, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7); + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7); void log( Level level, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8); + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8); void log( Level level, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8, - Object p9); + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8, + @UnknownConfidential Object p9); default void logMessage( final Level level, - final @NonConfidential Marker marker, - final @NonConfidential String fqcn, - final @NonConfidential StackTraceElement location, - final @NonConfidential Message message, - final @NonConfidential Throwable throwable); + final @UnknownConfidential Marker marker, + final String fqcn, + final StackTraceElement location, + final Message message, + final @UnknownConfidential Throwable throwable); - void printf(Level level, @NonConfidential Marker marker, @NonConfidential String format, Object... params); + void printf(Level level, @UnknownConfidential Marker marker, String format, @UnknownConfidential Object... params); - void printf(Level level, @NonConfidential String format, Object... params); + void printf(Level level, String format, @UnknownConfidential Object... params); - void trace(@NonConfidential Marker marker, @NonConfidential Message message); + void trace(@UnknownConfidential Marker marker, Message message); - void trace(@NonConfidential Marker marker, @NonConfidential Message message, @NonConfidential Throwable throwable); + void trace(@UnknownConfidential Marker marker, Message message, @UnknownConfidential Throwable throwable); - void trace(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier); + void trace(@UnknownConfidential Marker marker, @UnknownConfidential MessageSupplier messageSupplier); - void trace(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + void trace(@UnknownConfidential Marker marker, @UnknownConfidential MessageSupplier messageSupplier, @UnknownConfidential Throwable throwable); - void trace(@NonConfidential Marker marker, @NonConfidential CharSequence message); + void trace(@UnknownConfidential Marker marker, CharSequence message); - void trace(@NonConfidential Marker marker, @NonConfidential CharSequence message, @NonConfidential Throwable throwable); + void trace(@UnknownConfidential Marker marker, CharSequence message, @UnknownConfidential Throwable throwable); - void trace(@NonConfidential Marker marker, @NonConfidential Object message); + void trace(@UnknownConfidential Marker marker, Object message); - void trace(@NonConfidential Marker marker, @NonConfidential Object message, @NonConfidential Throwable throwable); + void trace(@UnknownConfidential Marker marker, Object message, @UnknownConfidential Throwable throwable); - void trace(@NonConfidential Marker marker, @NonConfidential String message); + void trace(@UnknownConfidential Marker marker, String message); - void trace(@NonConfidential Marker marker, @NonConfidential String message, Object... params); + void trace(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object... params); - void trace(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + void trace(@UnknownConfidential Marker marker, String message, @UnknownConfidential Supplier... paramSuppliers); - void trace(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Throwable throwable); + void trace(@UnknownConfidential Marker marker, String message, @UnknownConfidential Throwable throwable); - void trace(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier); + void trace(@UnknownConfidential Marker marker, @UnknownConfidential Supplier messageSupplier); - void trace(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + void trace(@UnknownConfidential Marker marker, @UnknownConfidential Supplier messageSupplier, @UnknownConfidential Throwable throwable); - void trace(@NonConfidential Message message); + void trace(Message message); - void trace(@NonConfidential Message message, @NonConfidential Throwable throwable); + void trace(Message message, @UnknownConfidential Throwable throwable); - void trace(@NonConfidential MessageSupplier messageSupplier); + void trace(@UnknownConfidential MessageSupplier messageSupplier); - void trace(@NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + void trace(@UnknownConfidential MessageSupplier messageSupplier, @UnknownConfidential Throwable throwable); - void trace(@NonConfidential CharSequence message); + void trace(CharSequence message); - void trace(@NonConfidential CharSequence message, @NonConfidential Throwable throwable); + void trace(CharSequence message, @UnknownConfidential Throwable throwable); - void trace(@NonConfidential Object message); + void trace(Object message); - void trace(@NonConfidential Object message, @NonConfidential Throwable throwable); + void trace(Object message, @UnknownConfidential Throwable throwable); - void trace(@NonConfidential String message); + void trace(String message); - void trace(@NonConfidential String message, Object... params); + void trace(String message, @UnknownConfidential Object... params); - void trace(@NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + void trace(String message, @UnknownConfidential Supplier... paramSuppliers); - void trace(@NonConfidential String message, @NonConfidential Throwable throwable); + void trace(String message, @UnknownConfidential Throwable throwable); - void trace(@NonConfidential Supplier messageSupplier); + void trace(@UnknownConfidential Supplier messageSupplier); - void trace(@NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + void trace(@UnknownConfidential Supplier messageSupplier, @UnknownConfidential Throwable throwable); - void trace(@NonConfidential Marker marker, @NonConfidential String message, Object p0); + void trace(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0); - void trace(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1); + void trace(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1); - void trace(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2); + void trace(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2); - void trace(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + void trace(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3); - void trace(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + void trace(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4); - void trace(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + void trace(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5); void trace( - @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + @UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6); void trace( - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7); void trace( - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8); void trace( - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8, - Object p9); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8, + @UnknownConfidential Object p9); - void trace(@NonConfidential String message, Object p0); + void trace(String message, @UnknownConfidential Object p0); - void trace(@NonConfidential String message, Object p0, Object p1); + void trace(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1); - void trace(@NonConfidential String message, Object p0, Object p1, Object p2); + void trace(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2); - void trace(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + void trace(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3); - void trace(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + void trace(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4); - void trace(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + void trace(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5); - void trace(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + void trace(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6); - void trace(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7); + void trace(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6, @UnknownConfidential Object p7); void trace( - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8); + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8); void trace( - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8, - Object p9); + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8, + @UnknownConfidential Object p9); - void warn(@NonConfidential Marker marker, @NonConfidential Message message); + void warn(@UnknownConfidential Marker marker, Message message); - void warn(@NonConfidential Marker marker, @NonConfidential Message message, @NonConfidential Throwable throwable); + void warn(@UnknownConfidential Marker marker, Message message, @UnknownConfidential Throwable throwable); - void warn(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier); + void warn(@UnknownConfidential Marker marker, @UnknownConfidential MessageSupplier messageSupplier); - void warn(@NonConfidential Marker marker, @NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + void warn(@UnknownConfidential Marker marker, @UnknownConfidential MessageSupplier messageSupplier, @UnknownConfidential Throwable throwable); - void warn(@NonConfidential Marker marker, @NonConfidential CharSequence message); + void warn(@UnknownConfidential Marker marker, CharSequence message); - void warn(@NonConfidential Marker marker, @NonConfidential CharSequence message, @NonConfidential Throwable throwable); + void warn(@UnknownConfidential Marker marker, CharSequence message, @UnknownConfidential Throwable throwable); - void warn(@NonConfidential Marker marker, @NonConfidential Object message); + void warn(@UnknownConfidential Marker marker, Object message); - void warn(@NonConfidential Marker marker, @NonConfidential Object message, @NonConfidential Throwable throwable); + void warn(@UnknownConfidential Marker marker, Object message, @UnknownConfidential Throwable throwable); - void warn(@NonConfidential Marker marker, @NonConfidential String message); + void warn(@UnknownConfidential Marker marker, String message); - void warn(@NonConfidential Marker marker, @NonConfidential String message, Object... params); + void warn(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object... params); - void warn(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + void warn(@UnknownConfidential Marker marker, String message, @UnknownConfidential Supplier... paramSuppliers); - void warn(@NonConfidential Marker marker, @NonConfidential String message, @NonConfidential Throwable throwable); + void warn(@UnknownConfidential Marker marker, String message, @UnknownConfidential Throwable throwable); - void warn(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier); + void warn(@UnknownConfidential Marker marker, @UnknownConfidential Supplier messageSupplier); - void warn(@NonConfidential Marker marker, @NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + void warn(@UnknownConfidential Marker marker, @UnknownConfidential Supplier messageSupplier, @UnknownConfidential Throwable throwable); - void warn(@NonConfidential Message message); + void warn(Message message); - void warn(@NonConfidential Message message, @NonConfidential Throwable throwable); + void warn(Message message, @UnknownConfidential Throwable throwable); - void warn(@NonConfidential MessageSupplier messageSupplier); + void warn(@UnknownConfidential MessageSupplier messageSupplier); - void warn(@NonConfidential MessageSupplier messageSupplier, @NonConfidential Throwable throwable); + void warn(@UnknownConfidential MessageSupplier messageSupplier, @UnknownConfidential Throwable throwable); - void warn(@NonConfidential CharSequence message); + void warn(CharSequence message); - void warn(@NonConfidential CharSequence message, @NonConfidential Throwable throwable); + void warn(CharSequence message, @UnknownConfidential Throwable throwable); - void warn(@NonConfidential Object message); + void warn(Object message); - void warn(@NonConfidential Object message, @NonConfidential Throwable throwable); + void warn(Object message, @UnknownConfidential Throwable throwable); - void warn(@NonConfidential String message); + void warn(String message); - void warn(@NonConfidential String message, Object... params); + void warn(String message, @UnknownConfidential Object... params); - void warn(@NonConfidential String message, @NonConfidential Supplier... paramSuppliers); + void warn(String message, @UnknownConfidential Supplier... paramSuppliers); - void warn(@NonConfidential String message, @NonConfidential Throwable throwable); + void warn(String message, @UnknownConfidential Throwable throwable); - void warn(@NonConfidential Supplier messageSupplier); + void warn(@UnknownConfidential Supplier messageSupplier); - void warn(@NonConfidential Supplier messageSupplier, @NonConfidential Throwable throwable); + void warn(@UnknownConfidential Supplier messageSupplier, @UnknownConfidential Throwable throwable); - void warn(@NonConfidential Marker marker, @NonConfidential String message, Object p0); + void warn(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0); - void warn(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1); + void warn(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1); - void warn(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2); + void warn(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2); - void warn(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + void warn(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3); - void warn(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + void warn(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4); - void warn(@NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + void warn(@UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5); void warn( - @NonConfidential Marker marker, @NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + @UnknownConfidential Marker marker, String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6); void warn( - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7); void warn( - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8); void warn( - @NonConfidential Marker marker, - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8, - Object p9); + @UnknownConfidential Marker marker, + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8, + @UnknownConfidential Object p9); - void warn(@NonConfidential String message, Object p0); + void warn(String message, @UnknownConfidential Object p0); - void warn(@NonConfidential String message, Object p0, Object p1); + void warn(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1); - void warn(@NonConfidential String message, Object p0, Object p1, Object p2); + void warn(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2); - void warn(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3); + void warn(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3); - void warn(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4); + void warn(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4); - void warn(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5); + void warn(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5); - void warn(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6); + void warn(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6); - void warn(@NonConfidential String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7); + void warn(String message, @UnknownConfidential Object p0, @UnknownConfidential Object p1, @UnknownConfidential Object p2, @UnknownConfidential Object p3, @UnknownConfidential Object p4, @UnknownConfidential Object p5, @UnknownConfidential Object p6, @UnknownConfidential Object p7); void warn( - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8); + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8); void warn( - @NonConfidential String message, - Object p0, - Object p1, - Object p2, - Object p3, - Object p4, - Object p5, - Object p6, - Object p7, - Object p8, - Object p9); - - T throwing(Level level, @NonConfidential T throwable); - - T throwing(@NonConfidential T throwable); + String message, + @UnknownConfidential Object p0, + @UnknownConfidential Object p1, + @UnknownConfidential Object p2, + @UnknownConfidential Object p3, + @UnknownConfidential Object p4, + @UnknownConfidential Object p5, + @UnknownConfidential Object p6, + @UnknownConfidential Object p7, + @UnknownConfidential Object p8, + @UnknownConfidential Object p9); + + T throwing(Level level, T throwable); + + T throwing(T throwable); + + boolean isDebugEnabled(@UnknownConfidential Marker marker); + + boolean isEnabled(Level level); + + boolean isEnabled(Level level, @UnknownConfidential Marker marker); + + boolean isErrorEnabled(@UnknownConfidential Marker marker); + + boolean isFatalEnabled(@UnknownConfidential Marker marker); + + boolean isInfoEnabled(@UnknownConfidential Marker marker); + + boolean isTraceEnabled(@UnknownConfidential Marker marker); + + boolean isWarnEnabled(@UnknownConfidential Marker marker); + + EntryMessage traceEntry(String format, @UnknownConfidential Object... params); + + EntryMessage traceEntry(@UnknownConfidential Supplier... paramSuppliers); + + EntryMessage traceEntry(String format, @UnknownConfidential Supplier... paramSuppliers); } diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/PrintStream.astub b/checker/src/main/java/org/checkerframework/checker/confidential/PrintStream.astub deleted file mode 100644 index 9eb1fee6a55..00000000000 --- a/checker/src/main/java/org/checkerframework/checker/confidential/PrintStream.astub +++ /dev/null @@ -1,49 +0,0 @@ -package java.io; - -import java.nio.charset.Charset; -import java.nio.charset.IllegalCharsetNameException; -import java.nio.charset.UnsupportedCharsetException; -import java.util.Formatter; -import java.util.Locale; -import java.util.Locale.Category; - -import org.checkerframework.checker.confidential.qual.NonConfidential; - -public class PrintStream extends FilterOutputStream implements Appendable, Closeable { - - public void print(@NonConfidential char c); - - public void print(@NonConfidential int i); - - public void print(@NonConfidential long l); - - public void print(@NonConfidential float f); - - public void print(@NonConfidential double d); - - public void print(@NonConfidential char[] s); - - public void print(@NonConfidential String s); - - public void print(@NonConfidential Object obj); - - public void println(@NonConfidential char x); - - public void println(@NonConfidential int x); - - public void println(@NonConfidential long x); - - public void println(@NonConfidential float x); - - public void println(@NonConfidential double x); - - public void println(@NonConfidential char[] x); - - public void println(@NonConfidential String x); - - public void println(@NonConfidential Object x); - - public PrintStream printf(@NonConfidential String format, Object... args); - - public PrintStream printf(Locale l, @NonConfidential String format, Object... args); -} From e25024d22ead89d2c0bdd7b99b735fa05042cebf Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 12 Jan 2025 22:47:19 -0800 Subject: [PATCH 141/184] Added UserDetails.astub --- .../checker/confidential/UserDetails.astub | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/UserDetails.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/UserDetails.astub b/checker/src/main/java/org/checkerframework/checker/confidential/UserDetails.astub new file mode 100644 index 00000000000..b0ec1a04e2b --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/UserDetails.astub @@ -0,0 +1,22 @@ +package org.springframework.security.core.userdetails; + +import java.io.Serializable; +import java.util.Collection; +import org.springframework.security.core.GrantedAuthority; +import org.checkerframework.checker.confidential.qual.*; + +public interface UserDetails extends Serializable { + Collection getAuthorities(); + + @Confidential String getPassword(); + + String getUsername(); + + boolean isAccountNonExpired(); + + boolean isAccountNonLocked(); + + boolean isCredentialsNonExpired(); + + boolean isEnabled(); +} From bdbd307d85815d7cc9dc6c4812d261646bb41c2c Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 28 Jan 2025 11:19:31 -0800 Subject: [PATCH 142/184] Improve diagnostics & comments --- .../framework/stub/AnnotationFileElementTypes.java | 8 ++++++-- .../framework/stub/AnnotationFileParser.java | 5 +++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/framework/src/main/java/org/checkerframework/framework/stub/AnnotationFileElementTypes.java b/framework/src/main/java/org/checkerframework/framework/stub/AnnotationFileElementTypes.java index 04f6e99391e..4e990b6e66f 100644 --- a/framework/src/main/java/org/checkerframework/framework/stub/AnnotationFileElementTypes.java +++ b/framework/src/main/java/org/checkerframework/framework/stub/AnnotationFileElementTypes.java @@ -452,9 +452,13 @@ private void parseAnnotationFiles(List annotationFiles, AnnotationFileTy public @Nullable AnnotationMirrorSet getDeclAnnotations(Element elt) { if (stubDebug) { if (isParsing()) { - System.out.printf("AFET.getDeclAnnotations(%s [%s])%n", elt, elt.getClass()); + System.out.printf( + "AFET.getDeclAnnotations(%s [%s]): isParsing() => true, returning emptySet.%n", + elt, elt.getClass()); } else { - System.out.printf("AFET.getDeclAnnotations(%s [%s]) IS NOT PARSING%n", elt, elt.getClass()); + System.out.printf( + "AFET.getDeclAnnotations(%s [%s]): isParsing() => false, proceeding%n", + elt, elt.getClass()); } } diff --git a/framework/src/main/java/org/checkerframework/framework/stub/AnnotationFileParser.java b/framework/src/main/java/org/checkerframework/framework/stub/AnnotationFileParser.java index 31cbc225a0e..52ecc0ba749 100644 --- a/framework/src/main/java/org/checkerframework/framework/stub/AnnotationFileParser.java +++ b/framework/src/main/java/org/checkerframework/framework/stub/AnnotationFileParser.java @@ -770,7 +770,8 @@ private void parseStubUnit(InputStream inputStream) { /** * Process {@link #stubUnit}, which is the AST produced by {@link #parseStubUnit}. Processing - * means copying annotations from Stub Parser data structures to {@code #annotationFileAnnos}. + * means copying annotations from Stub Parser data structures to argument {@code + * annotationFileAnnos}. * * @param annotationFileAnnos annotations from the file; side-effected by this method */ @@ -781,7 +782,7 @@ private void process(AnnotationFileAnnotations annotationFileAnnos) { } /** - * Process the given StubUnit: copy its annotations to {@code #annotationFileAnnos}. + * Process the given StubUnit: copy its annotations to {@code this.annotationFileAnnos}. * * @param su the StubUnit to process */ From 0696529ca5f04ffe16533cad76b291e9547e2d2a Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 28 Jan 2025 11:21:32 -0800 Subject: [PATCH 143/184] Punctuation --- .../framework/stub/AnnotationFileElementTypes.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/checkerframework/framework/stub/AnnotationFileElementTypes.java b/framework/src/main/java/org/checkerframework/framework/stub/AnnotationFileElementTypes.java index 4e990b6e66f..0c6659be573 100644 --- a/framework/src/main/java/org/checkerframework/framework/stub/AnnotationFileElementTypes.java +++ b/framework/src/main/java/org/checkerframework/framework/stub/AnnotationFileElementTypes.java @@ -457,7 +457,7 @@ private void parseAnnotationFiles(List annotationFiles, AnnotationFileTy elt, elt.getClass()); } else { System.out.printf( - "AFET.getDeclAnnotations(%s [%s]): isParsing() => false, proceeding%n", + "AFET.getDeclAnnotations(%s [%s]): isParsing() => false, proceeding.%n", elt, elt.getClass()); } } From af123e54ea2947b92d219dbc60e19ca5cb806a35 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 4 Feb 2025 01:01:48 -0800 Subject: [PATCH 144/184] Removed unnecessary confidential checker annotations in stub files --- .../checker/confidential/ApacheLog.astub | 14 +- .../confidential/ConfidentialChecker.java | 2 - .../checker/confidential/Slf4jLogger.astub | 102 ++---------- .../checker/confidential/TextView.astub | 154 ------------------ .../checker/confidential/Toast.astub | 32 ---- 5 files changed, 18 insertions(+), 286 deletions(-) delete mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/TextView.astub delete mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/Toast.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ApacheLog.astub b/checker/src/main/java/org/checkerframework/checker/confidential/ApacheLog.astub index 5666785ebc4..ab6f380348e 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ApacheLog.astub +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ApacheLog.astub @@ -1,18 +1,18 @@ package org.apache.commons.logging; -import org.checkerframework.checker.confidential.qual.*; +import org.checkerframework.checker.confidential.qual.UnknownConfidential; public interface Log { - void debug(Object var1, Throwable var2); + void debug(Object var1, @UnknownConfidential Throwable var2); - void error(Object var1, Throwable var2); + void error(Object var1, @UnknownConfidential Throwable var2); - void fatal(Object var1, Throwable var2); + void fatal(Object var1, @UnknownConfidential Throwable var2); - void info(Object var1, Throwable var2); + void info(Object var1, @UnknownConfidential Throwable var2); - void trace(Object var1, Throwable var2); + void trace(Object var1, @UnknownConfidential Throwable var2); - void warn(Object var1, Throwable var2); + void warn(Object var1, @UnknownConfidential Throwable var2); } diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 0c7d4dae04f..e9f69ad3db9 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -17,8 +17,6 @@ "AndroidLog.astub", "Slf4jLogger.astub", "ApacheLog.astub", - "Toast.astub", - "TextView.astub", "AlertDialog.astub", "AbstractAuthenticationTargetUrlRequestHandler.astub", "UsernamePasswordAuthenticationToken.astub", diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/Slf4jLogger.astub b/checker/src/main/java/org/checkerframework/checker/confidential/Slf4jLogger.astub index d7b49ae5a56..e859b5d786e 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/Slf4jLogger.astub +++ b/checker/src/main/java/org/checkerframework/checker/confidential/Slf4jLogger.astub @@ -17,107 +17,27 @@ import org.slf4j.spi.DefaultLoggingEventBuilder; import org.slf4j.spi.LoggingEventBuilder; import org.slf4j.spi.NOPLoggingEventBuilder; -import org.checkerframework.checker.confidential.qual.NonConfidential; +import org.checkerframework.checker.confidential.qual.UnknownConfidential; public interface Logger { - public void error(@NonConfidential String msg); + public void error(String msg, @UnknownConfidential Throwable t); - public void error(@NonConfidential String format, Object arg); + public void error(Marker marker, String msg, @UnknownConfidential Throwable t); - public void error(@NonConfidential String format, Object arg1, Object arg2); + public void info(String msg, @UnknownConfidential Throwable t); - public void error(@NonConfidential String format, Object... arguments); + public void info(Marker marker, String msg, @UnknownConfidential Throwable t); - public void error(@NonConfidential String msg, @NonConfidential Throwable t); + public void debug(String msg, @UnknownConfidential Throwable t); - public void error(@NonConfidential Marker marker, @NonConfidential String msg); + public void debug(Marker marker, String msg, @UnknownConfidential Throwable t); - public void error(@NonConfidential Marker marker, @NonConfidential String format, Object arg); + public void trace(String msg, @UnknownConfidential Throwable t); - public void error(@NonConfidential Marker marker, @NonConfidential String format, Object arg1, Object arg2); + public void trace(Marker marker, String msg, @UnknownConfidential Throwable t); - public void error(@NonConfidential Marker marker, @NonConfidential String format, Object... arguments); + public void warn(String msg, @UnknownConfidential Throwable t); - public void error(@NonConfidential Marker marker, @NonConfidential String msg, @NonConfidential Throwable t); - - public void info(@NonConfidential String msg); - - public void info(@NonConfidential String format, Object arg); - - public void info(@NonConfidential String format, Object arg1, Object arg2); - - public void info(@NonConfidential String format, Object... arguments); - - public void info(@NonConfidential String msg, @NonConfidential Throwable t); - - public void info(@NonConfidential Marker marker, @NonConfidential String msg); - - public void info(@NonConfidential Marker marker, @NonConfidential String format, Object arg); - - public void info(@NonConfidential Marker marker, @NonConfidential String format, Object arg1, Object arg2); - - public void info(@NonConfidential Marker marker, @NonConfidential String format, Object... arguments); - - public void info(@NonConfidential Marker marker, @NonConfidential String msg, @NonConfidential Throwable t); - - public void debug(@NonConfidential String msg); - - public void debug(@NonConfidential String format, Object arg); - - public void debug(@NonConfidential String format, Object arg1, Object arg2); - - public void debug(@NonConfidential String format, Object... arguments); - - public void debug(@NonConfidential String msg, @NonConfidential Throwable t); - - public void debug(@NonConfidential Marker marker, @NonConfidential String msg); - - public void debug(@NonConfidential Marker marker, @NonConfidential String format, Object arg); - - public void debug(@NonConfidential Marker marker, @NonConfidential String format, Object arg1, Object arg2); - - public void debug(@NonConfidential Marker marker, @NonConfidential String format, Object... arguments); - - public void debug(@NonConfidential Marker marker, @NonConfidential String msg, @NonConfidential Throwable t); - - public void trace(@NonConfidential String msg); - - public void trace(@NonConfidential String format, Object arg); - - public void trace(@NonConfidential String format, Object arg1, Object arg2); - - public void trace(@NonConfidential String format, Object... arguments); - - public void trace(@NonConfidential String msg, @NonConfidential Throwable t); - - public void trace(@NonConfidential Marker marker, @NonConfidential String msg); - - public void trace(@NonConfidential Marker marker, @NonConfidential String format, Object arg); - - public void trace(@NonConfidential Marker marker, @NonConfidential String format, Object arg1, Object arg2); - - public void trace(@NonConfidential Marker marker, @NonConfidential String format, Object... argArray); - - public void trace(@NonConfidential Marker marker, @NonConfidential String msg, @NonConfidential Throwable t); - - public void warn(@NonConfidential String msg); - - public void warn(@NonConfidential String format, Object arg); - - public void warn(@NonConfidential String format, Object... arguments); - - public void warn(@NonConfidential String format, Object arg1, Object arg2); - - public void warn(@NonConfidential String msg, @NonConfidential Throwable t); - - public void warn(@NonConfidential Marker marker, @NonConfidential String msg); - - public void warn(@NonConfidential Marker marker, @NonConfidential String format, Object arg); - - public void warn(@NonConfidential Marker marker, @NonConfidential String format, Object arg1, Object arg2); - - public void warn(@NonConfidential Marker marker, @NonConfidential String format, Object... arguments); - - public void warn(@NonConfidential Marker marker, @NonConfidential String msg, @NonConfidential Throwable t); + public void warn(Marker marker, String msg, @UnknownConfidential Throwable t); } diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/TextView.astub b/checker/src/main/java/org/checkerframework/checker/confidential/TextView.astub deleted file mode 100644 index e8f68a4bae0..00000000000 --- a/checker/src/main/java/org/checkerframework/checker/confidential/TextView.astub +++ /dev/null @@ -1,154 +0,0 @@ -package android.widget; -import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; -import android.R; -import android.annotation.ColorInt; -import android.annotation.DrawableRes; -import android.annotation.FloatRange; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.Size; -import android.annotation.StringRes; -import android.annotation.StyleRes; -import android.annotation.XmlRes; -import android.app.Activity; -import android.app.assist.AssistStructure; -import android.content.ClipData; -import android.content.ClipboardManager; -import android.content.Context; -import android.content.Intent; -import android.content.UndoManager; -import android.content.res.ColorStateList; -import android.content.res.CompatibilityInfo; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.content.res.XmlResourceParser; -import android.graphics.Canvas; -import android.graphics.Insets; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.PorterDuff; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; -import android.os.AsyncTask; -import android.os.Bundle; -import android.os.LocaleList; -import android.os.Parcel; -import android.os.Parcelable; -import android.os.ParcelableParcel; -import android.os.SystemClock; -import android.os.UserHandle; -import android.provider.Settings; -import android.text.BoringLayout; -import android.text.DynamicLayout; -import android.text.Editable; -import android.text.GetChars; -import android.text.GraphicsOperations; -import android.text.InputFilter; -import android.text.InputType; -import android.text.Layout; -import android.text.ParcelableSpan; -import android.text.Selection; -import android.text.SpanWatcher; -import android.text.Spannable; -import android.text.SpannableString; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.SpannedString; -import android.text.StaticLayout; -import android.text.TextDirectionHeuristic; -import android.text.TextDirectionHeuristics; -import android.text.TextPaint; -import android.text.TextUtils; -import android.text.TextUtils.TruncateAt; -import android.text.TextWatcher; -import android.text.method.AllCapsTransformationMethod; -import android.text.method.ArrowKeyMovementMethod; -import android.text.method.DateKeyListener; -import android.text.method.DateTimeKeyListener; -import android.text.method.DialerKeyListener; -import android.text.method.DigitsKeyListener; -import android.text.method.KeyListener; -import android.text.method.LinkMovementMethod; -import android.text.method.MetaKeyKeyListener; -import android.text.method.MovementMethod; -import android.text.method.PasswordTransformationMethod; -import android.text.method.SingleLineTransformationMethod; -import android.text.method.TextKeyListener; -import android.text.method.TimeKeyListener; -import android.text.method.TransformationMethod; -import android.text.method.TransformationMethod2; -import android.text.method.WordIterator; -import android.text.style.CharacterStyle; -import android.text.style.ClickableSpan; -import android.text.style.ParagraphStyle; -import android.text.style.SpellCheckSpan; -import android.text.style.SuggestionSpan; -import android.text.style.URLSpan; -import android.text.style.UpdateAppearance; -import android.text.util.Linkify; -import android.util.AttributeSet; -import android.util.Log; -import android.util.TypedValue; -import android.view.AccessibilityIterators.TextSegmentIterator; -import android.view.ActionMode; -import android.view.Choreographer; -import android.view.ContextMenu; -import android.view.DragEvent; -import android.view.Gravity; -import android.view.HapticFeedbackConstants; -import android.view.KeyCharacterMap; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.PointerIcon; -import android.view.View; -import android.view.ViewConfiguration; -import android.view.ViewDebug; -import android.view.ViewGroup.LayoutParams; -import android.view.ViewHierarchyEncoder; -import android.view.ViewParent; -import android.view.ViewRootImpl; -import android.view.ViewStructure; -import android.view.ViewTreeObserver; -import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityManager; -import android.view.accessibility.AccessibilityNodeInfo; -import android.view.animation.AnimationUtils; -import android.view.inputmethod.BaseInputConnection; -import android.view.inputmethod.CompletionInfo; -import android.view.inputmethod.CorrectionInfo; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.ExtractedText; -import android.view.inputmethod.ExtractedTextRequest; -import android.view.inputmethod.InputConnection; -import android.view.inputmethod.InputMethodManager; -import android.view.textservice.SpellCheckerSubtype; -import android.view.textservice.TextServicesManager; -import android.widget.RemoteViews.RemoteView; -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.FastMath; -import com.android.internal.widget.EditableInputConnection; -import org.xmlpull.v1.XmlPullParserException; -import java.io.IOException; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Locale; - -import org.checkerframework.checker.confidential.qual.NonConfidential; - -public class TextView extends View implements ViewTreeObserver.OnPreDrawListener { - - public final void setText(@NonConfidential CharSequence text); - - public void setText(@NonConfidential CharSequence text, BufferType type); - - private void setText(@NonConfidential CharSequence text, BufferType type, boolean notifyBefore, int oldlen); - - public final void setText(@NonConfidential char[] text, int start, int len); - - public void setError(@NonConfidential CharSequence error); - - public void setError(@NonConfidential CharSequence error, Drawable icon); -} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/Toast.astub b/checker/src/main/java/org/checkerframework/checker/confidential/Toast.astub deleted file mode 100644 index 0007069f21f..00000000000 --- a/checker/src/main/java/org/checkerframework/checker/confidential/Toast.astub +++ /dev/null @@ -1,32 +0,0 @@ -package android.widget; -import android.annotation.IntDef; -import android.annotation.StringRes; -import android.app.INotificationManager; -import android.app.ITransientNotification; -import android.content.Context; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.graphics.PixelFormat; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.util.Log; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.WindowManager; -import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityManager; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import org.checkerframework.checker.confidential.qual.NonConfidential; - -public class Toast { - - public static Toast makeText(Context context, @NonConfidential CharSequence text, @Duration int duration); - - public void setText(@NonConfidential CharSequence s); -} From c900935f5787c080d47148da2bb4137dad30f66e Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 4 Feb 2025 09:49:53 -0800 Subject: [PATCH 145/184] Include the Confidential Checker in the manual --- docs/manual/manual.tex | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/manual/manual.tex b/docs/manual/manual.tex index f430f3c6150..7049ad27960 100644 --- a/docs/manual/manual.tex +++ b/docs/manual/manual.tex @@ -63,6 +63,7 @@ % These are related to tainting: \input{tainting-checker.tex} \input{sql-quotes-checker.tex} +\input{confidential-checker.tex} % These are focused on strings: \input{regex-checker.tex} From 87d3633e4d799c119c18c5831f49df5496a87426 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 4 Feb 2025 17:32:16 -0800 Subject: [PATCH 146/184] Improve the manual --- docs/manual/confidential-checker.tex | 143 ++++++++++++++++----------- docs/manual/hevea.sty | 90 +++++++++++++++++ 2 files changed, 176 insertions(+), 57 deletions(-) create mode 100644 docs/manual/hevea.sty diff --git a/docs/manual/confidential-checker.tex b/docs/manual/confidential-checker.tex index 5fc335ebdd8..8805f603131 100644 --- a/docs/manual/confidential-checker.tex +++ b/docs/manual/confidential-checker.tex @@ -1,43 +1,71 @@ \htmlhr \chapterAndLabel{Confidential Checker}{confidential-checker} -The Confidential Checker helps identify insecure software implementations that may -lead to \href{https://cwe.mitre.org/data/definitions/1417.html}{sensitive information -exposure}. These vulnerabilities arise when developers allow information such as PII, -passwords, or local file paths to be passed to potentially public-facing sinks, which -include website and app user interfaces, log files, error messages, and URL targets. - -Exposure may occur mistakenly or with a benign objective in mind. For instance, a developer -may unwittingly write code that exposes sensitive information, or they may output -sensitive information to error messages with the intention of supplying helpful -troubleshooting direction; the Confidential Checker covers both of these cases by -guaranteeing that no values marked as sensitive information will be passed to a -location marked as public-facing. - -However, the Confidential Checker cannot guarantee the correctness or completeness -of the annotations themselves. In other words, the onus of comprehensively annotating -sensitive information falls solely upon the developer. The Confidential Checker does -provide preliminary annotations for certain public-facing sinks, but developers should -always verify that any sinks used in their code are annotated appropriately. - -To run the Confidential Checker, supply the -\code{-processor ConfidentialChecker} -or -\code{-processor org.checkerframework.checker.confidential.ConfidentialChecker} -command-line option to javac. +The Confidential Checker identifies +\href{https://cwe.mitre.org/data/definitions/1417.html}{sensitive information +exposure}, also known as information leakage. An information leak occurs when private information +such as PII (personally identifiable information), passwords, or local file +paths is revealed. Information is revealed by being passed to +a public-facing sink, such as website and app user interfaces, +log files, error messages, and URL targets. + +The Confidential Checker guarantees that no values marked as +\emph{confidential} flow to a location marked as +\emph{non-confidential}. + +It is the responsibility of the user to annotate sources and sinks as +confidential or non-confidential. +Since \code{@NonConfidential} is the default annotation, if a programmer +forgets to annotate a sensitive source as \<@Confidential>, then there will +be an information leak that the Confidential Checker cannot warn about. +Once sources and sinks are annotated, the Confidential +Checker guarantees that any other annotations in the program are consistent +with those annotations, and that no information flows from confidential to +non-confidential locations. + +The confidential checker does not identify \emph{indirect} information flows, such +as in: + +\begin{Verbatim} + // Information is leaked, but the Confidential Checker issues no error. + @Confidential boolean secret = ...; + @NonConfidential boolean revealed; + if (secret) { + revealed = true; + } else { + revealed = false; + } +\end{Verbatim} + +Exposure may occur mistakenly --- in which case +it should be fixed --- or with a benign objective in mind, such as when +logging to aid troubleshooting. After the Confidential Checker reveals a +leak, it is up to the user to decide whether the leakage is acceptable. + +To run the Confidential Checker, supply one of these +command-line options to javac: +\begin{Verbatim} +-processor ConfidentialChecker +-processor org.checkerframework.checker.confidential.ConfidentialChecker +\end{Verbatim} \sectionAndLabel{Confidential annotations}{confidential-annotations} -The Confidential Checker type system uses the following annotations: +The Confidential Checker type system uses the following type qualifiers; +their subtyping hierarchy is shown in +Figure~\ref{fig-confidential-hierarchy}. \begin{description} \item[\refqualclass{checker/confidential/qual}{Confidential}] - indicates a value that will not be exposed to end users or a sink that - will not be able to be accessed by end users. + An expression whose type is qualified with + \refqualclass{checker/confidential/qual}{Confidential} may evaluate to + a value that should not be exposed. \item[\refqualclass{checker/confidential/qual}{NonConfidential}] - indicates a value that may be exposed to end users, or a location that - may be accessed by end users. It is the default qualifier. + The value of an expression of type + \refqualclass{checker/confidential/qual}{NonConfidential} might be + exposed. It is written on the formal parameter type of a method such + as \ that may leak its argument. It is the default qualifier. \item[\refqualclass{checker/confidential/qual}{UnknownConfidential}] indicates a value whose confidentiality is unknown. \code{@UnknownConfidential} is a supertype of \code{@Confidential} @@ -49,29 +77,27 @@ is the bottom qualifier. Programmers rarely need to write it. \end{description} -The subtyping hierarchy of the Confidential Checker's qualifiers is shown in -Figure~\ref{fig-confidential-hierarchy}. \begin{figure} \includeimage{confidential}{5.5cm} \caption{The subtyping relationship of the Confidential Checker's qualifiers. - Qualifiers in gray are used internally by the type system but should never + Qualifiers in gray are used internally by the type system and should rarely be written by a programmer.} \label{fig-confidential-hierarchy} \end{figure} -Although parallels could be drawn between the Confidential Checker's -\code{@Confidential} annotation and the Taint Checker's \code{@Tainted} -annotation (see Section~\ref{tainting-annotations}), it should be noted that +The Confidential Checker's +\code{@Confidential} qualifier has similarities to the Taint Checker's \code{@Tainted} +qualifier. One difference is that there is no subtyping relationship between \code{@Confidential} and \code{@NonConfidential}. However, the external behavior of these annotations can strongly resemble that of a supertype and subtype, as casts from the latter to the former are always permitted (see Section~\ref{confidential-checks}). As a result, while the Confidential Checker (correctly) does not allow -\code{@Confidential} values to be passed to \code{@NonConfidential} sinks, it does +\code{@Confidential} values to flow to \code{@NonConfidential} sinks, it does allow \code{@NonConfidential} values in \code{@Confidential} sinks. -\sectionAndLabel{What the Confidential Checker checks}{confidential-checks} +\sectionAndLabel{Concatenation}{confidential-concatenation} Concatenation of \code{@Confidential} and \code{@NonConfidential} values is always dominated by \code{@Confidential}. In other words, concatenation of @@ -95,23 +121,26 @@ \sectionAndLabel{Library annotations}{confidential-library-annotations} -As mentioned prior, the Confidential Checker provides preliminary annotations -for certain public-facing sinks either in the form of stub files or within the -Checker Framework's annotated JDK. For instance, the \code{TextView} class for Android -apps requires that a \code{@NonConfidential CharSequence} should be passed to -its \code{setText} method to avoid displaying sensitive information on the user's -viewport. - -If necessary, developers can write methods to vet \code{@Confidential} or -\code{@UnknownConfidential} values and determine which, if any, parts of the -value can be safely cast to \code{@NonConfidential} under a \code{@SuppressWarnings} -annotation and passed to user-facing sinks. - -It should be noted that, since \code{@NonConfidential} is the default annotation, -developers must be particularly attentive to explicitly annotating their variables -to avoid accidentally passing a secret value to a public-facing sink. For this reason, -it may seem insecure to set \code{@NonConfidential} as the default rather than -\code{@UnknownConfidential} or \code{@Confidential}. However, this implementation -significantly decreases the number of \code{@SuppressWarnings} annotations (and -overall annotations)that the developer must write, as in practice, values are more -often \code{@NonConfidential} than \code{@Confidential}. +The Confidential Checker provides annotations for certain public-facing +sinks. For instance, methods in Android's \code{TextView} class have a +formal parameter of type \code{@NonConfidential CharSequence}, indicating +that they display the argument on the user's viewport. The Confidential +Checker will issue a type error if a \<@Confidential> value can be passed +to such functions. + +The built-in annotations appear in the Checker +Framework's annotated JDK and in stub files in directory +\. +A developer can write more annotations in stub files +(\chapterpageref{stub}), especially for libraries that do not already have +annotations. (Please share these with the Checker Framework developers, so +that they can distribute them to all users.) + +If a program contains a method that tests whether a run-time value is +confidential, use annotation +\refqualclass{framework/qual}{EnsuresQualifierIf} (\chapterpageref{type-refinement}). + +If a program contains a method that takes a possibly-confidential argument +and returns a non-confidential result, then suppress the warning +(\chapterpageref{suppressing-warnings}) after manually validating the +method's behavior. diff --git a/docs/manual/hevea.sty b/docs/manual/hevea.sty new file mode 100644 index 00000000000..b194858167f --- /dev/null +++ b/docs/manual/hevea.sty @@ -0,0 +1,90 @@ +% hevea : hevea.sty +% This is a very basic style file for latex document to be processed +% with hevea. It contains definitions of LaTeX environment which are +% processed in a special way by the translator. +% Mostly : +% - latexonly, not processed by hevea, processed by latex. +% - htmlonly , the reverse. +% - rawhtml, to include raw HTML in hevea output. +% - toimage, to send text to the image file. +% The package also provides hevea logos, html related commands (ahref +% etc.), void cutting and image commands. +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{hevea}[2002/01/11] +\RequirePackage{comment} +\newif\ifhevea\heveafalse +\@ifundefined{ifimagen}{\newif\ifimagen\imagenfalse} +\makeatletter% +\newcommand{\heveasmup}[2]{% +\raise #1\hbox{$\m@th$% + \csname S@\f@size\endcsname + \fontsize\sf@size 0% + \math@fontsfalse\selectfont +#2% +}}% +\DeclareRobustCommand{\hevea}{H\kern-.15em\heveasmup{.2ex}{E}\kern-.15emV\kern-.15em\heveasmup{.2ex}{E}\kern-.15emA}% +\DeclareRobustCommand{\hacha}{H\kern-.15em\heveasmup{.2ex}{A}\kern-.15emC\kern-.1em\heveasmup{.2ex}{H}\kern-.15emA}% +\DeclareRobustCommand{\html}{\protect\heveasmup{0.ex}{HTML}} +%%%%%%%%% Hyperlinks hevea style +\newcommand{\ahref}[2]{{#2}} +\newcommand{\ahrefloc}[2]{{#2}} +\newcommand{\aname}[2]{{#2}} +\newcommand{\ahrefurl}[1]{\texttt{#1}} +\newcommand{\footahref}[2]{#2\footnote{\texttt{#1}}} +\newcommand{\mailto}[1]{\texttt{#1}} +\newcommand{\imgsrc}[2][]{} +\newcommand{\home}[1]{\protect\raisebox{-.75ex}{\char126}#1} +\AtBeginDocument +{\@ifundefined{url} +{%url package is not loaded +\let\url\ahref\let\oneurl\ahrefurl\let\footurl\footahref} +{}} +%% Void cutting instructions +\newcounter{cuttingdepth} +\newcommand{\tocnumber}{} +\newcommand{\notocnumber}{} +\newcommand{\cuttingunit}{} +\newcommand{\cutdef}[2][]{} +\newcommand{\cuthere}[2]{} +\newcommand{\cutend}{} +\newcommand{\htmlhead}[1]{} +\newcommand{\htmlfoot}[1]{} +\newcommand{\htmlprefix}[1]{} +\newenvironment{cutflow}[1]{}{} +\newcommand{\cutname}[1]{} +\newcommand{\toplinks}[3]{} +\newcommand{\setlinkstext}[3]{} +\newcommand{\flushdef}[1]{} +\newcommand{\footnoteflush}[1]{} +%%%% Html only +\excludecomment{rawhtml} +\newcommand{\rawhtmlinput}[1]{} +\excludecomment{htmlonly} +%%%% Latex only +\newenvironment{latexonly}{}{} +\newenvironment{verblatex}{}{} +%%%% Image file stuff +\def\toimage{\endgroup} +\def\endtoimage{\begingroup\def\@currenvir{toimage}} +\def\verbimage{\endgroup} +\def\endverbimage{\begingroup\def\@currenvir{verbimage}} +\newcommand{\imageflush}[1][]{} +%%% Bgcolor definition +\newsavebox{\@bgcolorbin} +\newenvironment{bgcolor}[2][] + {\newcommand{\@mycolor}{#2}\begin{lrbox}{\@bgcolorbin}\vbox\bgroup} + {\egroup\end{lrbox}% + \begin{flushleft}% + \colorbox{\@mycolor}{\usebox{\@bgcolorbin}}% + \end{flushleft}} +%%% Style sheets macros, defined as no-ops +\newcommand{\newstyle}[2]{} +\newcommand{\addstyle}[1]{} +\newcommand{\setenvclass}[2]{} +\newcommand{\getenvclass}[1]{} +\newcommand{\loadcssfile}[1]{} +\newenvironment{divstyle}[1]{}{} +\newenvironment{cellstyle}[2]{}{} +\newif\ifexternalcss +%%% Postlude +\makeatother From e01c7dba7def94fcf13a45be20cb5dbad4ae4d1b Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 3 Mar 2025 01:38:10 -0800 Subject: [PATCH 147/184] Added more stub files --- .../checker/confidential/Authentication.astub | 21 +++++++++++++++++++ .../confidential/ConfidentialChecker.java | 5 ++++- .../checker/confidential/ExpiringMap.astub | 10 +++++++++ .../checker/confidential/JwtParser.astub | 12 +++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/Authentication.astub create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/ExpiringMap.astub create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/JwtParser.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/Authentication.astub b/checker/src/main/java/org/checkerframework/checker/confidential/Authentication.astub new file mode 100644 index 00000000000..c09af83eb54 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/Authentication.astub @@ -0,0 +1,21 @@ +package org.springframework.security.core; + +import java.io.Serializable; +import java.security.Principal; +import java.util.Collection; + +import org.checkerframework.checker.confidential.qual.Confidential; + +public interface Authentication extends Principal, Serializable { + Collection getAuthorities(); + + @Confidential Object getCredentials(); + + Object getDetails(); + + Object getPrincipal(); + + boolean isAuthenticated(); + + void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException; +} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index e9f69ad3db9..366a8feaad6 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -23,7 +23,10 @@ "PasswordEncoder.astub", "HttpServletResponse.astub", "Cookie.astub", - "UserDetails.astub" + "UserDetails.astub", + "ExpiringMap.astub", + "JwtParser.astub", + "Authentication.astub" }) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ExpiringMap.astub b/checker/src/main/java/org/checkerframework/checker/confidential/ExpiringMap.astub new file mode 100644 index 00000000000..03a239c37ee --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ExpiringMap.astub @@ -0,0 +1,10 @@ +package net.jodah.expiringmap; + +import java.util.concurrent.ConcurrentMap; + +import org.checkerframework.checker.confidential.qual.PolyConfidential; + +public class ExpiringMap<@PolyConfidential K, @PolyConfidential V> implements ConcurrentMap<<@PolyConfidential K, @PolyConfidential V>> { + + public boolean containsKey(@PolyConfidential Object key); +} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/JwtParser.astub b/checker/src/main/java/org/checkerframework/checker/confidential/JwtParser.astub new file mode 100644 index 00000000000..eb658497dba --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/JwtParser.astub @@ -0,0 +1,12 @@ +package io.jsonwebtoken; + +import java.security.Key; +import java.util.Date; + +import org.checkerframework.checker.confidential.qual.*; + +public interface JwtParser { + char SEPARATOR_CHAR = '.'; + + Jws<@Confidential Claims> parseClaimsJws(@Confidential String var1) throws ExpiredJwtException, UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException; +} From 2b3706c2f3e7edfc7f45ba861fd470d6238955ae Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 10 Mar 2025 04:06:42 -0700 Subject: [PATCH 148/184] Added Claims, ExpiringMap stub files --- .../checker/confidential/Claims.astub | 36 +++++++++++++++++++ .../confidential/ConfidentialChecker.java | 3 +- .../checker/confidential/ExpiringMap.astub | 2 ++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/Claims.astub diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/Claims.astub b/checker/src/main/java/org/checkerframework/checker/confidential/Claims.astub new file mode 100644 index 00000000000..f96572cd03a --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/Claims.astub @@ -0,0 +1,36 @@ +import org.checkerframework.checker.confidential.qual.*; + +import java.util.Date; +import java.util.Map; + +public interface Claims extends Map<@PolyConfidential String, @PolyConfidential Object>, ClaimsMutator { + String getIssuer(); + + Claims setIssuer(String var1); + + String getSubject(@PolyConfidential Claims this); + + Claims setSubject(String var1); + + String getAudience(@PolyConfidential Claims this); + + Claims setAudience(String var1); + + Date getExpiration(@PolyConfidential Claims this); + + Claims setExpiration(Date var1); + + Date getNotBefore(@PolyConfidential Claims this); + + Claims setNotBefore(Date var1); + + Date getIssuedAt(@PolyConfidential Claims this); + + Claims setIssuedAt(Date var1); + + String getId(@PolyConfidential Claims this); + + Claims setId(String var1); + + T get(String var1, Class var2); +} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 366a8feaad6..1a9ac761a88 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -26,7 +26,8 @@ "UserDetails.astub", "ExpiringMap.astub", "JwtParser.astub", - "Authentication.astub" + "Authentication.astub", + "Claims.astub" }) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ExpiringMap.astub b/checker/src/main/java/org/checkerframework/checker/confidential/ExpiringMap.astub index 03a239c37ee..15aa4d40a88 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ExpiringMap.astub +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ExpiringMap.astub @@ -7,4 +7,6 @@ import org.checkerframework.checker.confidential.qual.PolyConfidential; public class ExpiringMap<@PolyConfidential K, @PolyConfidential V> implements ConcurrentMap<<@PolyConfidential K, @PolyConfidential V>> { public boolean containsKey(@PolyConfidential Object key); + + } From 1d90f4e80160bbac829c496c9f818b4457feffbf Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 10 Mar 2025 05:22:33 -0700 Subject: [PATCH 149/184] Updated Claims, ExpiringMap stub files --- .../org/checkerframework/checker/confidential/Claims.astub | 2 +- .../checkerframework/checker/confidential/ExpiringMap.astub | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/Claims.astub b/checker/src/main/java/org/checkerframework/checker/confidential/Claims.astub index f96572cd03a..2526fa1c289 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/Claims.astub +++ b/checker/src/main/java/org/checkerframework/checker/confidential/Claims.astub @@ -1,4 +1,4 @@ -import org.checkerframework.checker.confidential.qual.*; +import org.checkerframework.checker.confidential.qual.PolyConfidential; import java.util.Date; import java.util.Map; diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ExpiringMap.astub b/checker/src/main/java/org/checkerframework/checker/confidential/ExpiringMap.astub index 15aa4d40a88..d3ad6f699e4 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ExpiringMap.astub +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ExpiringMap.astub @@ -1,12 +1,11 @@ package net.jodah.expiringmap; import java.util.concurrent.ConcurrentMap; - import org.checkerframework.checker.confidential.qual.PolyConfidential; public class ExpiringMap<@PolyConfidential K, @PolyConfidential V> implements ConcurrentMap<<@PolyConfidential K, @PolyConfidential V>> { public boolean containsKey(@PolyConfidential Object key); - + public V put(@PolyConfidential K key, V@PolyConfidential value, long duration, TimeUnit timeUnit); } From 03ebab31f1b7956beea3965853f0c5a2eb9b2db3 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 10 Mar 2025 06:56:37 -0700 Subject: [PATCH 150/184] Moved/added comments for pipeline misc check --- .../confidential/qual/BottomConfidential.java | 12 ++++++------ .../checker/confidential/ConfidentialChecker.java | 5 ++++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/BottomConfidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/BottomConfidential.java index 957bf764877..79968aa803a 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/BottomConfidential.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/BottomConfidential.java @@ -1,11 +1,5 @@ package org.checkerframework.checker.confidential.qual; -/** - * The bottom type in the Confidential type system. Programmers should rarely write this type. - * - * @checker_framework.manual #confidential-checker Confidential Checker - * @checker_framework.manual #bottom-type the bottom type - */ import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -17,6 +11,12 @@ import org.checkerframework.framework.qual.TargetLocations; import org.checkerframework.framework.qual.TypeUseLocation; +/** + * The bottom type in the Confidential type system. Programmers should rarely write this type. + * + * @checker_framework.manual #confidential-checker Confidential Checker + * @checker_framework.manual #bottom-type the bottom type + */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 1a9ac761a88..6c4cecbc0ed 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -30,4 +30,7 @@ "Claims.astub" }) @SuppressWarningsPrefix({"confidential"}) -public class ConfidentialChecker extends BaseTypeChecker {} +public class ConfidentialChecker extends BaseTypeChecker { + /** Creates a ConfidentialChecker. */ + public ConfidentialChecker() {} +} From 8e0adab54ff509f72d0fbc24a6bb37f1645d1bed Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 30 Mar 2025 21:08:25 -0700 Subject: [PATCH 151/184] Trivial change for pipeline rerun --- .../checker/confidential/ConfidentialChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 6c4cecbc0ed..e678f536a44 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -31,6 +31,6 @@ }) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker { - /** Creates a ConfidentialChecker. */ + /** Creates a ConfidentialChecker. */ public ConfidentialChecker() {} } From 2f7386dcd27b0dabef4b0f30df2beebd34ce0ecc Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 30 Mar 2025 21:11:35 -0700 Subject: [PATCH 152/184] Trivial change for pipeline rerun --- .../checker/confidential/ConfidentialChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index e678f536a44..6c4cecbc0ed 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -31,6 +31,6 @@ }) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker { - /** Creates a ConfidentialChecker. */ + /** Creates a ConfidentialChecker. */ public ConfidentialChecker() {} } From 6ebb40fcc46e6f1fff33079348c26a6266732248 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 30 Mar 2025 21:50:19 -0700 Subject: [PATCH 153/184] Trivial change for pipeline rerun --- .../checker/confidential/ConfidentialChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 6c4cecbc0ed..e678f536a44 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -31,6 +31,6 @@ }) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker { - /** Creates a ConfidentialChecker. */ + /** Creates a ConfidentialChecker. */ public ConfidentialChecker() {} } From d306408013e1f60b7ba3eb29f2b7320e4e9d22e4 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 30 Mar 2025 23:40:59 -0700 Subject: [PATCH 154/184] Trivial change for pipeline rerun --- .../checker/confidential/ConfidentialChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index e678f536a44..6c4cecbc0ed 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -31,6 +31,6 @@ }) @SuppressWarningsPrefix({"confidential"}) public class ConfidentialChecker extends BaseTypeChecker { - /** Creates a ConfidentialChecker. */ + /** Creates a ConfidentialChecker. */ public ConfidentialChecker() {} } From 61f06fa3282b2b22daa6a5b374615f93e8375fb6 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 31 Mar 2025 10:35:10 -0700 Subject: [PATCH 155/184] Edited for typos --- .../checkerframework/checker/confidential/ExpiringMap.astub | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ExpiringMap.astub b/checker/src/main/java/org/checkerframework/checker/confidential/ExpiringMap.astub index d3ad6f699e4..57561b63a9b 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ExpiringMap.astub +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ExpiringMap.astub @@ -3,9 +3,9 @@ package net.jodah.expiringmap; import java.util.concurrent.ConcurrentMap; import org.checkerframework.checker.confidential.qual.PolyConfidential; -public class ExpiringMap<@PolyConfidential K, @PolyConfidential V> implements ConcurrentMap<<@PolyConfidential K, @PolyConfidential V>> { +public class ExpiringMap<@PolyConfidential K, @PolyConfidential V> implements ConcurrentMap<@PolyConfidential K, @PolyConfidential V> { public boolean containsKey(@PolyConfidential Object key); - public V put(@PolyConfidential K key, V@PolyConfidential value, long duration, TimeUnit timeUnit); + public V put(@PolyConfidential K key, @PolyConfidential V value, long duration, TimeUnit timeUnit); } From 68b2f94504941882157947330e364cee45d42b44 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Sun, 6 Apr 2025 22:55:58 -0700 Subject: [PATCH 156/184] Added new type rules to allow NonConfidential Objects to have NonConfidential toString --- .../ConfidentialAnnotatedTypeFactory.java | 26 +++++++++++++++++++ .../confidential/ConfidentialToString.java | 14 ++++++++++ 2 files changed, 40 insertions(+) create mode 100644 checker/tests/confidential/ConfidentialToString.java diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java index 098ba088c09..4fd034c761f 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java @@ -3,7 +3,11 @@ import com.sun.source.tree.BinaryTree; import com.sun.source.tree.CompoundAssignmentTree; import java.util.Set; +import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import com.sun.source.tree.MethodInvocationTree; +import com.sun.source.tree.Tree; import org.checkerframework.checker.confidential.qual.BottomConfidential; import org.checkerframework.checker.confidential.qual.Confidential; import org.checkerframework.checker.confidential.qual.NonConfidential; @@ -16,6 +20,7 @@ import org.checkerframework.framework.type.treeannotator.TreeAnnotator; import org.checkerframework.javacutil.AnnotationBuilder; import org.checkerframework.javacutil.AnnotationMirrorSet; +import org.checkerframework.javacutil.ElementUtils; import org.checkerframework.javacutil.TreeUtils; /** Annotated type factory for the Confidential Checker. */ @@ -36,6 +41,9 @@ public class ConfidentialAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { /** A singleton set containing the {@code @}{@link NonConfidential} annotation mirror. */ private final AnnotationMirrorSet setOfNonConfidential; + /** The processing environment to use for accessing compiler internals. */ + protected final ProcessingEnvironment processingEnv; + /** * Creates a {@link ConfidentialAnnotatedTypeFactory}. * @@ -50,6 +58,7 @@ public ConfidentialAnnotatedTypeFactory(BaseTypeChecker checker) { this.BOTTOM_CONFIDENTIAL = AnnotationBuilder.fromClass(getElementUtils(), BottomConfidential.class); this.setOfNonConfidential = AnnotationMirrorSet.singleton(NONCONFIDENTIAL); + this.processingEnv = checker.getProcessingEnvironment(); postInit(); } @@ -134,4 +143,21 @@ private AnnotationMirror getResultingType( return NONCONFIDENTIAL; } } + + @Override + public void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror type, boolean useFlow) { + Element element = TreeUtils.elementFromTree(tree); + if (TreeUtils.isMethodAccess(tree)) { + MethodInvocationTree methodInvoc = (MethodInvocationTree) tree; + if (TreeUtils.isMethodInvocation(methodInvoc, + TreeUtils.getMethod(Object.class, "toString", 1, processingEnv), + processingEnv)) { + Element arg = TreeUtils.elementFromTree(methodInvoc.getTypeArguments().get(0)); + if (ElementUtils.hasAnnotation(arg, "NonConfidential")) { + type.replaceAnnotation(NONCONFIDENTIAL); + } + } + } + super.addComputedTypeAnnotations(tree, type, useFlow); + } } diff --git a/checker/tests/confidential/ConfidentialToString.java b/checker/tests/confidential/ConfidentialToString.java new file mode 100644 index 00000000000..6095d35807a --- /dev/null +++ b/checker/tests/confidential/ConfidentialToString.java @@ -0,0 +1,14 @@ +import org.checkerframework.checker.confidential.qual.Confidential; +import org.checkerframework.checker.confidential.qual.NonConfidential; + +public ConfidentialToString { + void confParam(@Confidential Object confObj) { + // :: error: (assignment) + @NonConfidential String nonConfRes = confObj.toString(); + @Confidential String confRes = confObj.toString(); + } + + void nonConfParam(@NonConfidential Object nonConfObj) { + @NonConfidential String nonConfRes = nonConfObj.toString(); + } +} From 0b1601c478d6967d6fea46b0916d1241912861c8 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 7 Apr 2025 23:20:54 -0700 Subject: [PATCH 157/184] Added comment to addComputedTypeAnnotations and revised to use hasPrimaryAnnotation to check annotation --- .../ConfidentialAnnotatedTypeFactory.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java index 4fd034c761f..8a851239a91 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java @@ -41,9 +41,6 @@ public class ConfidentialAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { /** A singleton set containing the {@code @}{@link NonConfidential} annotation mirror. */ private final AnnotationMirrorSet setOfNonConfidential; - /** The processing environment to use for accessing compiler internals. */ - protected final ProcessingEnvironment processingEnv; - /** * Creates a {@link ConfidentialAnnotatedTypeFactory}. * @@ -58,7 +55,6 @@ public ConfidentialAnnotatedTypeFactory(BaseTypeChecker checker) { this.BOTTOM_CONFIDENTIAL = AnnotationBuilder.fromClass(getElementUtils(), BottomConfidential.class); this.setOfNonConfidential = AnnotationMirrorSet.singleton(NONCONFIDENTIAL); - this.processingEnv = checker.getProcessingEnvironment(); postInit(); } @@ -144,16 +140,23 @@ private AnnotationMirror getResultingType( } } + /** + * Defines specific type-checking rules for Object.toString() that allow + * @NonConfidential Objects to return @NonConfidential Strings. + * + * @param tree an AST node + * @param type the type obtained from tree + * @param useFlow whether to use information from dataflow analysis + */ @Override public void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror type, boolean useFlow) { - Element element = TreeUtils.elementFromTree(tree); if (TreeUtils.isMethodAccess(tree)) { MethodInvocationTree methodInvoc = (MethodInvocationTree) tree; if (TreeUtils.isMethodInvocation(methodInvoc, TreeUtils.getMethod(Object.class, "toString", 1, processingEnv), processingEnv)) { Element arg = TreeUtils.elementFromTree(methodInvoc.getTypeArguments().get(0)); - if (ElementUtils.hasAnnotation(arg, "NonConfidential")) { + if (fromElement(arg).hasPrimaryAnnotation(NONCONFIDENTIAL)) { type.replaceAnnotation(NONCONFIDENTIAL); } } From 501b42b7235dec9d0cab9365fcc80ca084253f75 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 8 Apr 2025 09:48:03 -0700 Subject: [PATCH 158/184] Fix Java error --- checker/tests/confidential/ConfidentialToString.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checker/tests/confidential/ConfidentialToString.java b/checker/tests/confidential/ConfidentialToString.java index 6095d35807a..f54afa6e9e8 100644 --- a/checker/tests/confidential/ConfidentialToString.java +++ b/checker/tests/confidential/ConfidentialToString.java @@ -1,7 +1,7 @@ import org.checkerframework.checker.confidential.qual.Confidential; import org.checkerframework.checker.confidential.qual.NonConfidential; -public ConfidentialToString { +public class ConfidentialToString { void confParam(@Confidential Object confObj) { // :: error: (assignment) @NonConfidential String nonConfRes = confObj.toString(); From 105fb7c144e04e8ee2197b7c94b8192492ddbf7d Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 8 Apr 2025 09:48:15 -0700 Subject: [PATCH 159/184] Improve documentation --- .../src/main/java/org/checkerframework/javacutil/TreeUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java b/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java index f7564940ae2..afd4e815a4a 100644 --- a/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java +++ b/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java @@ -1555,7 +1555,7 @@ public static String getFieldName(Tree tree) { } /** - * Determine whether {@code tree} refers to a method element, such as. + * Determine whether {@code tree} refers to a method element, such as "m" or "obj.m" in: * *
    *   m(...)

From e29832cd2c028033b4939a77838486c2355fa077 Mon Sep 17 00:00:00 2001
From: iywang2016 
Date: Tue, 8 Apr 2025 10:53:37 -0700
Subject: [PATCH 160/184] Changed addComputedTypeAnnotations to
 visitMethodInvocation

---
 .../ConfidentialAnnotatedTypeFactory.java     | 40 ++++++++++---------
 1 file changed, 22 insertions(+), 18 deletions(-)

diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java
index 8a851239a91..cf7bb5a1fa3 100644
--- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java
+++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java
@@ -6,6 +6,7 @@
 import javax.annotation.processing.ProcessingEnvironment;
 import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
 import com.sun.source.tree.MethodInvocationTree;
 import com.sun.source.tree.Tree;
 import org.checkerframework.checker.confidential.qual.BottomConfidential;
@@ -41,6 +42,10 @@ public class ConfidentialAnnotatedTypeFactory extends BaseAnnotatedTypeFactory {
   /** A singleton set containing the {@code @}{@link NonConfidential} annotation mirror. */
   private final AnnotationMirrorSet setOfNonConfidential;
 
+  /** The Object.toString method. */
+  private final ExecutableElement objectToString =
+      TreeUtils.getMethod("java.lang.Object", "toString", 0, processingEnv);
+
   /**
    * Creates a {@link ConfidentialAnnotatedTypeFactory}.
    *
@@ -138,29 +143,28 @@ private AnnotationMirror getResultingType(
 
       return NONCONFIDENTIAL;
     }
-  }
 
-  /**
-   * Defines specific type-checking rules for Object.toString() that allow
-   * @NonConfidential Objects to return @NonConfidential Strings.
-   *
-   * @param tree an AST node
-   * @param type the type obtained from tree
-   * @param useFlow whether to use information from dataflow analysis
-   */
-  @Override
-  public void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror type, boolean useFlow) {
-    if (TreeUtils.isMethodAccess(tree)) {
-      MethodInvocationTree methodInvoc = (MethodInvocationTree) tree;
-      if (TreeUtils.isMethodInvocation(methodInvoc,
-          TreeUtils.getMethod(Object.class, "toString", 1, processingEnv),
-          processingEnv)) {
-        Element arg = TreeUtils.elementFromTree(methodInvoc.getTypeArguments().get(0));
+    /**
+     * Visits a method invocation node. Enforces specific type-checking rules
+     * for Object.toString() that allow a @NonConfidential Object to return
+     * a @NonConfidential String.
+     *
+     * Supplements the @Confidential String return in Object.toString() to cover
+     * all secure use cases, i.e. all cases covered by a @PolyConfidential receiver
+     * and return excepting a @NonConfidential String from a @Confidential receiver.
+     *
+     * @param tree an AST node representing a method call
+     * @param type the type obtained from tree
+     */
+    @Override
+    public Void visitMethodInvocation(MethodInvocationTree tree, AnnotatedTypeMirror type) {
+      if (TreeUtils.isMethodInvocation(tree, objectToString, processingEnv)) {
+        Element arg = TreeUtils.elementFromTree(tree.getTypeArguments().get(0));
         if (fromElement(arg).hasPrimaryAnnotation(NONCONFIDENTIAL)) {
           type.replaceAnnotation(NONCONFIDENTIAL);
         }
       }
+      return super.visitMethodInvocation(tree, type);
     }
-    super.addComputedTypeAnnotations(tree, type, useFlow);
   }
 }

From bc796d0f04503d781df04b4228a6753ec098edd6 Mon Sep 17 00:00:00 2001
From: iywang2016 
Date: Thu, 10 Apr 2025 14:16:43 -0700
Subject: [PATCH 161/184] Revised type factory to deal with NonConfidential
 toString

---
 .../confidential/ConfidentialAnnotatedTypeFactory.java      | 6 ++++--
 checker/tests/confidential/ConfidentialToString.java        | 4 ++--
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java
index cf7bb5a1fa3..1684ab45afe 100644
--- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java
+++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java
@@ -159,9 +159,11 @@ private AnnotationMirror getResultingType(
     @Override
     public Void visitMethodInvocation(MethodInvocationTree tree, AnnotatedTypeMirror type) {
       if (TreeUtils.isMethodInvocation(tree, objectToString, processingEnv)) {
-        Element arg = TreeUtils.elementFromTree(tree.getTypeArguments().get(0));
-        if (fromElement(arg).hasPrimaryAnnotation(NONCONFIDENTIAL)) {
+        AnnotatedTypeMirror receiver = getReceiverType(tree);
+        if (receiver.hasPrimaryAnnotation(NONCONFIDENTIAL)) {
           type.replaceAnnotation(NONCONFIDENTIAL);
+        } else {
+          type.replaceAnnotation(CONFIDENTIAL);
         }
       }
       return super.visitMethodInvocation(tree, type);
diff --git a/checker/tests/confidential/ConfidentialToString.java b/checker/tests/confidential/ConfidentialToString.java
index f54afa6e9e8..19990f3c4aa 100644
--- a/checker/tests/confidential/ConfidentialToString.java
+++ b/checker/tests/confidential/ConfidentialToString.java
@@ -2,13 +2,13 @@
 import org.checkerframework.checker.confidential.qual.NonConfidential;
 
 public class ConfidentialToString {
-  void confParam(@Confidential Object confObj) {
+  void confObj(@Confidential Object confObj) {
     // :: error: (assignment)
     @NonConfidential String nonConfRes = confObj.toString();
     @Confidential String confRes = confObj.toString();
   }
 
-  void nonConfParam(@NonConfidential Object nonConfObj) {
+  void nonConfObj(@NonConfidential Object nonConfObj) {
     @NonConfidential String nonConfRes = nonConfObj.toString();
   }
 }

From b516dfcd9930ec948953816ab0a776bff665b488 Mon Sep 17 00:00:00 2001
From: iywang2016 
Date: Mon, 14 Apr 2025 00:52:56 -0700
Subject: [PATCH 162/184] Fixed formatting issues

---
 .../ConfidentialAnnotatedTypeFactory.java       | 17 ++++++-----------
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java
index 1684ab45afe..2d5f1b8abfd 100644
--- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java
+++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java
@@ -2,13 +2,10 @@
 
 import com.sun.source.tree.BinaryTree;
 import com.sun.source.tree.CompoundAssignmentTree;
+import com.sun.source.tree.MethodInvocationTree;
 import java.util.Set;
-import javax.annotation.processing.ProcessingEnvironment;
 import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
-import com.sun.source.tree.MethodInvocationTree;
-import com.sun.source.tree.Tree;
 import org.checkerframework.checker.confidential.qual.BottomConfidential;
 import org.checkerframework.checker.confidential.qual.Confidential;
 import org.checkerframework.checker.confidential.qual.NonConfidential;
@@ -21,7 +18,6 @@
 import org.checkerframework.framework.type.treeannotator.TreeAnnotator;
 import org.checkerframework.javacutil.AnnotationBuilder;
 import org.checkerframework.javacutil.AnnotationMirrorSet;
-import org.checkerframework.javacutil.ElementUtils;
 import org.checkerframework.javacutil.TreeUtils;
 
 /** Annotated type factory for the Confidential Checker. */
@@ -145,13 +141,12 @@ private AnnotationMirror getResultingType(
     }
 
     /**
-     * Visits a method invocation node. Enforces specific type-checking rules
-     * for Object.toString() that allow a @NonConfidential Object to return
-     * a @NonConfidential String.
+     * Visits a method invocation node. Enforces specific type-checking rules for Object.toString()
+     * that allow a @NonConfidential Object to return a @NonConfidential String.
      *
-     * Supplements the @Confidential String return in Object.toString() to cover
-     * all secure use cases, i.e. all cases covered by a @PolyConfidential receiver
-     * and return excepting a @NonConfidential String from a @Confidential receiver.
+     * 

Supplements the @Confidential String return in Object.toString() to cover all secure use + * cases, i.e. all cases covered by a @PolyConfidential receiver and return excepting + * a @NonConfidential String from a @Confidential receiver. * * @param tree an AST node representing a method call * @param type the type obtained from tree From 9caaf900f6ed8b9b2f2565c9c7e9a04bff40e7aa Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 14 Apr 2025 11:47:28 -0700 Subject: [PATCH 163/184] Trivial changes for pipeline rerun --- .../checker/confidential/ConfidentialAnnotatedTypeFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java index 2d5f1b8abfd..392baf1fce7 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java @@ -146,7 +146,7 @@ private AnnotationMirror getResultingType( * *

Supplements the @Confidential String return in Object.toString() to cover all secure use * cases, i.e. all cases covered by a @PolyConfidential receiver and return excepting - * a @NonConfidential String from a @Confidential receiver. + * a @NonConfidential String from @Confidential receivers. * * @param tree an AST node representing a method call * @param type the type obtained from tree From 61c4557854e7dd74ab5101a9d77879d7f091799c Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sun, 20 Apr 2025 11:36:00 -0700 Subject: [PATCH 164/184] Undo a change --- checker/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checker/build.gradle b/checker/build.gradle index 01c35beec3b..6cfee73f537 100644 --- a/checker/build.gradle +++ b/checker/build.gradle @@ -1006,7 +1006,7 @@ publishing { checkerPom it artifact checkerJar artifact allSourcesJar - // artifact allJavadocJar + artifact allJavadocJar } } } From b82a9458f3ddea82d71f36b6024b8232d2f47208 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 21 Apr 2025 00:55:36 -0700 Subject: [PATCH 165/184] Moved string concatenation rules to ConfidentialTransfer --- .../ConfidentialAnnotatedTypeFactory.java | 67 +++++-------------- 1 file changed, 15 insertions(+), 52 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java index 392baf1fce7..e567059a53d 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java @@ -12,6 +12,11 @@ import org.checkerframework.checker.confidential.qual.UnknownConfidential; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; +import org.checkerframework.common.value.ValueTransfer; +import org.checkerframework.framework.flow.CFAbstractAnalysis; +import org.checkerframework.framework.flow.CFStore; +import org.checkerframework.framework.flow.CFTransfer; +import org.checkerframework.framework.flow.CFValue; import org.checkerframework.framework.type.AnnotatedTypeFactory; import org.checkerframework.framework.type.AnnotatedTypeMirror; import org.checkerframework.framework.type.treeannotator.ListTreeAnnotator; @@ -24,16 +29,16 @@ public class ConfidentialAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { /** The {@code @}{@link NonConfidential} annotation mirror. */ - private final AnnotationMirror NONCONFIDENTIAL; + protected final AnnotationMirror NONCONFIDENTIAL; /** The {@code @}{@link Confidential} annotation mirror. */ - private final AnnotationMirror CONFIDENTIAL; + protected final AnnotationMirror CONFIDENTIAL; /** The {@code @}{@link UnknownConfidential} annotation mirror. */ - private final AnnotationMirror UNKNOWN_CONFIDENTIAL; + protected final AnnotationMirror UNKNOWN_CONFIDENTIAL; /** The {@code @}{@link BottomConfidential} annotation mirror. */ - private final AnnotationMirror BOTTOM_CONFIDENTIAL; + protected final AnnotationMirror BOTTOM_CONFIDENTIAL; /** A singleton set containing the {@code @}{@link NonConfidential} annotation mirror. */ private final AnnotationMirrorSet setOfNonConfidential; @@ -71,6 +76,12 @@ public TreeAnnotator createTreeAnnotator() { new ConfidentialAnnotatedTypeFactory.ConfidentialTreeAnnotator(this)); } + @Override + public CFTransfer createFlowTransferFunction( + CFAbstractAnalysis analysis) { + return new ConfidentialTransfer(analysis); + } + /** * A TreeAnnotator to enforce Confidential String concatenation rules: * @@ -92,54 +103,6 @@ public ConfidentialTreeAnnotator(AnnotatedTypeFactory atypeFactory) { super(atypeFactory); } - @Override - public Void visitBinary(BinaryTree tree, AnnotatedTypeMirror type) { - if (TreeUtils.isStringConcatenation(tree)) { - AnnotatedTypeMirror leftType = getAnnotatedType(tree.getLeftOperand()); - AnnotatedTypeMirror rightType = getAnnotatedType(tree.getRightOperand()); - type.replaceAnnotation(getResultingType(leftType, rightType)); - } - return null; - } - - @Override - public Void visitCompoundAssignment(CompoundAssignmentTree tree, AnnotatedTypeMirror type) { - if (TreeUtils.isStringCompoundConcatenation(tree)) { - AnnotatedTypeMirror leftType = getAnnotatedType(tree.getVariable()); - AnnotatedTypeMirror rightType = getAnnotatedType(tree.getExpression()); - type.replaceAnnotation(getResultingType(leftType, rightType)); - } - return null; - } - - /** - * Returns the type of concatenating leftType and rightType. - * - * @param leftType the type on the left of the expression - * @param rightType the type on the right of the expression - * @return the resulting type after concatenation - */ - private AnnotationMirror getResultingType( - AnnotatedTypeMirror leftType, AnnotatedTypeMirror rightType) { - if (leftType.hasPrimaryAnnotation(UNKNOWN_CONFIDENTIAL) - || rightType.hasPrimaryAnnotation(UNKNOWN_CONFIDENTIAL)) { - return UNKNOWN_CONFIDENTIAL; - } - - if (leftType.hasPrimaryAnnotation(BOTTOM_CONFIDENTIAL)) { - return rightType.getPrimaryAnnotation(); - } else if (rightType.hasPrimaryAnnotation(BOTTOM_CONFIDENTIAL)) { - return leftType.getPrimaryAnnotation(); - } - - if (leftType.hasPrimaryAnnotation(CONFIDENTIAL) - || rightType.hasPrimaryAnnotation(CONFIDENTIAL)) { - return CONFIDENTIAL; - } - - return NONCONFIDENTIAL; - } - /** * Visits a method invocation node. Enforces specific type-checking rules for Object.toString() * that allow a @NonConfidential Object to return a @NonConfidential String. From 599a40b417cad84176d6f743eaf225368af688ec Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 21 Apr 2025 01:25:41 -0700 Subject: [PATCH 166/184] Moved string concatenation rules to ConfidentialTransfer --- .../ConfidentialAnnotatedTypeFactory.java | 17 +++ .../confidential/ConfidentialTransfer.java | 103 ++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java index e567059a53d..ad1fa3ff8b4 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java @@ -13,6 +13,7 @@ import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.common.value.ValueTransfer; +import org.checkerframework.common.value.qual.MatchesRegex; import org.checkerframework.framework.flow.CFAbstractAnalysis; import org.checkerframework.framework.flow.CFStore; import org.checkerframework.framework.flow.CFTransfer; @@ -40,6 +41,22 @@ public class ConfidentialAnnotatedTypeFactory extends BaseAnnotatedTypeFactory { /** The {@code @}{@link BottomConfidential} annotation mirror. */ protected final AnnotationMirror BOTTOM_CONFIDENTIAL; + /** Fully-qualified class name of {@link NonConfidential}. */ + public static final String NONCONFIDENTIAL_NAME = + "org.checkerframework.checker.confidential.qual.NonConfidential"; + + /** Fully-qualified class name of {@link Confidential}. */ + public static final String CONFIDENTIAL_NAME = + "org.checkerframework.checker.confidential.qual.Confidential"; + + /** Fully-qualified class name of {@link UnknownConfidential}. */ + public static final String UNKNOWN_CONFIDENTIAL_NAME = + "org.checkerframework.checker.confidential.qual.UnknownConfidential"; + + /** Fully-qualified class name of {@link BottomConfidential}. */ + public static final String BOTTOM_CONFIDENTIAL_NAME = + "org.checkerframework.checker.confidential.qual.BottomConfidential"; + /** A singleton set containing the {@code @}{@link NonConfidential} annotation mirror. */ private final AnnotationMirrorSet setOfNonConfidential; diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java new file mode 100644 index 00000000000..8e06e9ad8d1 --- /dev/null +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java @@ -0,0 +1,103 @@ +package org.checkerframework.checker.confidential; + +import org.checkerframework.common.value.ValueAnnotatedTypeFactory; +import org.checkerframework.dataflow.analysis.TransferInput; +import org.checkerframework.dataflow.analysis.TransferResult; +import org.checkerframework.dataflow.cfg.node.Node; +import org.checkerframework.dataflow.cfg.node.StringConcatenateNode; +import org.checkerframework.framework.flow.CFAbstractAnalysis; +import org.checkerframework.framework.flow.CFStore; +import org.checkerframework.framework.flow.CFTransfer; +import org.checkerframework.framework.flow.CFValue; +import org.checkerframework.framework.type.QualifierHierarchy; +import org.checkerframework.javacutil.AnnotationUtils; +import javax.lang.model.element.AnnotationMirror; + +/** The transfer class for the Confidential Checker. */ +public class ConfidentialTransfer extends CFTransfer { + + /** The Confidential type factory. */ + protected final ConfidentialAnnotatedTypeFactory atypeFactory; + + /** The Confidential qualifier hierarchy. */ + protected final QualifierHierarchy qualHierarchy; + + /** + * Create a new ConfidentialTransfer. + * + * @param analysis the corresponding analysis + */ + public ConfidentialTransfer(CFAbstractAnalysis analysis) { + super(analysis); + atypeFactory = (ConfidentialAnnotatedTypeFactory) analysis.getTypeFactory(); + qualHierarchy = atypeFactory.getQualifierHierarchy(); + } + + /** + * Enforces Confidential String concatenation rules: + * + *

    + *
  • (Confidential + NonConfidential) returns Confidential (commutatively); + *
  • (Confidential + Confidential) returns Confidential; + *
  • (NonConfidential + NonConfidential) returns NonConfidential; + *
  • UnknownConfidential dominates other types in concatenation; + *
  • Non-bottom types dominate BottomConfidential in concatenation. + *
+ */ + @Override + public TransferResult visitStringConcatenate( + StringConcatenateNode n, TransferInput p) { + TransferResult result = super.visitStringConcatenate(n, p); + return stringConcatenation(n.getLeftOperand(), n.getRightOperand(), p, result); + } + + public TransferResult stringConcatenation( + Node leftOperand, + Node rightOperand, + TransferInput p, + TransferResult result) { + AnnotationMirror resultAnno = + createAnnotationForStringConcatenation(leftOperand, rightOperand, p); + return recreateTransferResult(resultAnno, result); + } + + /** Creates an annotation for a result of string concatenation. */ + private AnnotationMirror createAnnotationForStringConcatenation( + Node leftOperand, Node rightOperand, TransferInput p) { + CFValue leftValue = p.getValueOfSubNode(leftOperand); + AnnotationMirror leftAnno = getValueAnnotation(leftValue); + if (leftAnno == null) { + return null; + } + String leftAnnoName = AnnotationUtils.annotationName(leftAnno); + CFValue rightValue = p.getValueOfSubNode(rightOperand); + AnnotationMirror rightAnno = getValueAnnotation(rightValue); + if (rightAnno == null) { + return null; + } + String rightAnnoName = AnnotationUtils.annotationName(rightAnno); + + if (leftAnnoName.equals(ConfidentialAnnotatedTypeFactory.UNKNOWN_CONFIDENTIAL_NAME) + || rightAnnoName.equals(ConfidentialAnnotatedTypeFactory.UNKNOWN_CONFIDENTIAL_NAME)) { + return atypeFactory.UNKNOWN_CONFIDENTIAL; + } + + if (leftAnnoName.equals(ConfidentialAnnotatedTypeFactory.BOTTOM_CONFIDENTIAL_NAME)) { + return rightAnno; + } else if (rightAnnoName.equals(ConfidentialAnnotatedTypeFactory.BOTTOM_CONFIDENTIAL_NAME)) { + return leftAnno; + } + + if (leftAnnoName.equals(ConfidentialAnnotatedTypeFactory.CONFIDENTIAL_NAME) + || rightAnnoName.equals(ConfidentialAnnotatedTypeFactory.CONFIDENTIAL_NAME)) { + return atypeFactory.CONFIDENTIAL; + } + + return atypeFactory.NONCONFIDENTIAL; + } + + private AnnotationMirror getValueAnnotation(CFValue cfValue) { + return qualHierarchy.findAnnotationInHierarchy( + cfValue.getAnnotations(), atypeFactory.UNKNOWN_CONFIDENTIAL); + } +} From ec3f8bcc8160b5dfcd4c8dcc5de629267dbc015e Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 21 Apr 2025 01:36:42 -0700 Subject: [PATCH 167/184] Fixed spotlessApply issues --- .../confidential/ConfidentialAnnotatedTypeFactory.java | 4 ---- .../checker/confidential/ConfidentialTransfer.java | 3 +-- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java index ad1fa3ff8b4..f645dd8aa7e 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java @@ -1,7 +1,5 @@ package org.checkerframework.checker.confidential; -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.CompoundAssignmentTree; import com.sun.source.tree.MethodInvocationTree; import java.util.Set; import javax.lang.model.element.AnnotationMirror; @@ -12,8 +10,6 @@ import org.checkerframework.checker.confidential.qual.UnknownConfidential; import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory; import org.checkerframework.common.basetype.BaseTypeChecker; -import org.checkerframework.common.value.ValueTransfer; -import org.checkerframework.common.value.qual.MatchesRegex; import org.checkerframework.framework.flow.CFAbstractAnalysis; import org.checkerframework.framework.flow.CFStore; import org.checkerframework.framework.flow.CFTransfer; diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java index 8e06e9ad8d1..ecadef96c23 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java @@ -1,6 +1,6 @@ package org.checkerframework.checker.confidential; -import org.checkerframework.common.value.ValueAnnotatedTypeFactory; +import javax.lang.model.element.AnnotationMirror; import org.checkerframework.dataflow.analysis.TransferInput; import org.checkerframework.dataflow.analysis.TransferResult; import org.checkerframework.dataflow.cfg.node.Node; @@ -11,7 +11,6 @@ import org.checkerframework.framework.flow.CFValue; import org.checkerframework.framework.type.QualifierHierarchy; import org.checkerframework.javacutil.AnnotationUtils; -import javax.lang.model.element.AnnotationMirror; /** The transfer class for the Confidential Checker. */ public class ConfidentialTransfer extends CFTransfer { From 4015c6b90ad69a9bc79ed553fd1312ef1d73ec88 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 21 Apr 2025 01:51:43 -0700 Subject: [PATCH 168/184] Added comments --- .../checker/confidential/ConfidentialTransfer.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java index ecadef96c23..ceb1284c4ea 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java @@ -50,6 +50,15 @@ public TransferResult visitStringConcatenate( return stringConcatenation(n.getLeftOperand(), n.getRightOperand(), p, result); } + /** + * Determines the resulting type of the string concatenation. + * + * @param leftOperand the left operand to be concatenated + * @param rightOperand the right operand to be concatenated + * @param p the input types + * @param result the result types + * @return the resulting type of the string concatenation operation. + */ public TransferResult stringConcatenation( Node leftOperand, Node rightOperand, @@ -95,6 +104,7 @@ private AnnotationMirror createAnnotationForStringConcatenation( return atypeFactory.NONCONFIDENTIAL; } + /** Returns the annotation in the Confidential type hierarchy for the given value. */ private AnnotationMirror getValueAnnotation(CFValue cfValue) { return qualHierarchy.findAnnotationInHierarchy( cfValue.getAnnotations(), atypeFactory.UNKNOWN_CONFIDENTIAL); From da3612ec8ad1d2a4eab11f0989fd951b90ceb53b Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 21 Apr 2025 02:05:42 -0700 Subject: [PATCH 169/184] Added documentation for createAnnotationForStringConcatenation --- .../checker/confidential/ConfidentialTransfer.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java index ceb1284c4ea..8d8d5500ad0 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java @@ -69,7 +69,13 @@ public TransferResult stringConcatenation( return recreateTransferResult(resultAnno, result); } - /** Creates an annotation for a result of string concatenation. */ + /** + * Creates an annotation for a result of string concatenation. + * @param leftOperand the left operand to be concatenated + * @param rightOperand the right operand to be concatenated + * @param p the input types + * @return the resulting AnnotationMirror of the string concatenation operation. + */ private AnnotationMirror createAnnotationForStringConcatenation( Node leftOperand, Node rightOperand, TransferInput p) { CFValue leftValue = p.getValueOfSubNode(leftOperand); From 73a9345821d9db14bfa94784fd7ec8e674008e73 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 21 Apr 2025 02:12:25 -0700 Subject: [PATCH 170/184] Ran spotlessApply --- .../checker/confidential/ConfidentialTransfer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java index 8d8d5500ad0..f67a6886916 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java @@ -71,6 +71,7 @@ public TransferResult stringConcatenation( /** * Creates an annotation for a result of string concatenation. + * * @param leftOperand the left operand to be concatenated * @param rightOperand the right operand to be concatenated * @param p the input types From db9fa0f68883c52ac53c980aa7e33206571281eb Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 21 Apr 2025 02:25:10 -0700 Subject: [PATCH 171/184] Documented getValueAnnotation --- .../checker/confidential/ConfidentialTransfer.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java index f67a6886916..f2eae9a625b 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java @@ -111,7 +111,12 @@ private AnnotationMirror createAnnotationForStringConcatenation( return atypeFactory.NONCONFIDENTIAL; } - /** Returns the annotation in the Confidential type hierarchy for the given value. */ + /** + * Returns the annotation in the Confidential type hierarchy for the given value. + * + * @param cfValue the value + * @return the value's AnnotationMirror from the Confidential hierarchy. + */ private AnnotationMirror getValueAnnotation(CFValue cfValue) { return qualHierarchy.findAnnotationInHierarchy( cfValue.getAnnotations(), atypeFactory.UNKNOWN_CONFIDENTIAL); From a49c65676436c62aad5086cac24745d37847961a Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 5 May 2025 06:35:10 -0700 Subject: [PATCH 172/184] Confidential checker qualifier and transfer changes --- .../checker/confidential/qual/NonConfidential.java | 5 ++++- .../checker/confidential/ConfidentialTransfer.java | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java index 3ab786ffd59..76f9997cc96 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/NonConfidential.java @@ -5,10 +5,12 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.checkerframework.framework.qual.DefaultFor; import org.checkerframework.framework.qual.DefaultQualifierInHierarchy; import org.checkerframework.framework.qual.LiteralKind; import org.checkerframework.framework.qual.QualifierForLiterals; import org.checkerframework.framework.qual.SubtypeOf; +import org.checkerframework.framework.qual.TypeUseLocation; /** * Denotes a value that may be exposed to end users, or a location that may be accessed by end @@ -21,6 +23,7 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @SubtypeOf(UnknownConfidential.class) -@QualifierForLiterals(LiteralKind.ALL) +@QualifierForLiterals({LiteralKind.STRING, LiteralKind.PRIMITIVE}) @DefaultQualifierInHierarchy +@DefaultFor(value = {TypeUseLocation.LOCAL_VARIABLE, TypeUseLocation.UPPER_BOUND}) public @interface NonConfidential {} diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java index f2eae9a625b..6a1a6170c53 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java @@ -108,7 +108,11 @@ private AnnotationMirror createAnnotationForStringConcatenation( return atypeFactory.CONFIDENTIAL; } - return atypeFactory.NONCONFIDENTIAL; + if (leftAnnoName.equals(ConfidentialAnnotatedTypeFactory.NONCONFIDENTIAL_NAME) + && rightAnnoName.equals(ConfidentialAnnotatedTypeFactory.NONCONFIDENTIAL_NAME)) { + return atypeFactory.NONCONFIDENTIAL; + } + return null; } /** From 832211858411532c9595e2f776432f549d04a8f3 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Mon, 5 May 2025 06:35:52 -0700 Subject: [PATCH 173/184] Confidential checker all-systems warning suppression --- framework/tests/all-systems/Issue577.java | 2 ++ framework/tests/all-systems/Issue6282.java | 1 + framework/tests/all-systems/MultipleUnions.java | 6 +++++- framework/tests/all-systems/UnionCrash.java | 6 +++++- framework/tests/all-systems/UnionTypes.java | 3 +++ framework/tests/all-systems/Unions.java | 4 ++++ 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/framework/tests/all-systems/Issue577.java b/framework/tests/all-systems/Issue577.java index df27c3a9a6f..1c831c686c5 100644 --- a/framework/tests/all-systems/Issue577.java +++ b/framework/tests/all-systems/Issue577.java @@ -58,6 +58,8 @@ void foo1(MyInterface param) throws Throwable { try { bar(); } catch (MyExceptionA | MyExceptionB ex1) { + @SuppressWarnings( + "confidential") // correctly prevents invoking get methods on UnknownConfidential String s = ex1.getT(); } } diff --git a/framework/tests/all-systems/Issue6282.java b/framework/tests/all-systems/Issue6282.java index 3e99d2129cf..2f2a042a158 100644 --- a/framework/tests/all-systems/Issue6282.java +++ b/framework/tests/all-systems/Issue6282.java @@ -9,6 +9,7 @@ public static final MethodHandle setAccessible0_Method() { throw new RuntimeException(); } + @SuppressWarnings("confidential") // correctly prevents exposing @UnknownConfidential throwable public static void setAccessible(final AccessibleObject accessibleObject) { try { diff --git a/framework/tests/all-systems/MultipleUnions.java b/framework/tests/all-systems/MultipleUnions.java index aafe839d92f..6d4eb450743 100644 --- a/framework/tests/all-systems/MultipleUnions.java +++ b/framework/tests/all-systems/MultipleUnions.java @@ -1,7 +1,11 @@ public class MultipleUnions { public static boolean flag = false; - @SuppressWarnings("ainfertest") // only check WPI for crashes + @SuppressWarnings({ + "ainfertest", + "confidential" + }) // only check WPI for crashes; correctly prevents cast of @UnknownConfidential to + // @NonConfidential void foo1(MyInterface param) throws Throwable { try { bar(); diff --git a/framework/tests/all-systems/UnionCrash.java b/framework/tests/all-systems/UnionCrash.java index 3ea9d253a66..44e45bfc2ba 100644 --- a/framework/tests/all-systems/UnionCrash.java +++ b/framework/tests/all-systems/UnionCrash.java @@ -1,7 +1,11 @@ // Test case for issue #775 // https://github.com/typetools/checker-framework/issues/775 -@SuppressWarnings("ainfertest") // only check WPI for crashes +@SuppressWarnings({ + "ainfertest", + "confidential" +}) // only check WPI for crashes; correctly prevents cast of @UnknownConfidential to +// @NonConfidential public class UnionCrash { void foo(MyInterface param) throws Throwable { try { diff --git a/framework/tests/all-systems/UnionTypes.java b/framework/tests/all-systems/UnionTypes.java index 4fc1717e433..29db6569932 100644 --- a/framework/tests/all-systems/UnionTypes.java +++ b/framework/tests/all-systems/UnionTypes.java @@ -6,6 +6,9 @@ public void TryCatch() { int[] arr = new int[10]; arr[4] = 1; } catch (ArrayIndexOutOfBoundsException | StringIndexOutOfBoundsException exc) { + @SuppressWarnings( + "confidential") // correctly prevents cast of @UnknownConfidential to @NonConfidential + // Exception Exception e = exc; } } diff --git a/framework/tests/all-systems/Unions.java b/framework/tests/all-systems/Unions.java index 3837a84e49c..9bcdf0310d3 100644 --- a/framework/tests/all-systems/Unions.java +++ b/framework/tests/all-systems/Unions.java @@ -1,5 +1,7 @@ @SuppressWarnings("ainfertest") // only check WPI for crashes public class Unions { + @SuppressWarnings( + "confidential") // correctly prevents cast of @UnknownConfidential to @NonConfidential void foo1(MyInterface param) throws Throwable { try { bar(); @@ -12,6 +14,8 @@ void foo1(MyInterface param) throws Throwable { } } + @SuppressWarnings( + "confidential") // correctly prevents cast of @UnknownConfidential to @NonConfidential void foo2(MyInterface param) throws Throwable { try { bar(); From b9a94a76f89b4e0295c8b7c216dc861eb64e562f Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 6 May 2025 09:41:32 -0700 Subject: [PATCH 174/184] Separate the explanations for two different warnings --- framework/tests/all-systems/UnionCrash.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/framework/tests/all-systems/UnionCrash.java b/framework/tests/all-systems/UnionCrash.java index 44e45bfc2ba..ef77932baab 100644 --- a/framework/tests/all-systems/UnionCrash.java +++ b/framework/tests/all-systems/UnionCrash.java @@ -2,10 +2,9 @@ // https://github.com/typetools/checker-framework/issues/775 @SuppressWarnings({ - "ainfertest", - "confidential" -}) // only check WPI for crashes; correctly prevents cast of @UnknownConfidential to -// @NonConfidential + "ainfertest", // only check WPI for crashes + "confidential" // correctly prevents cast of @UnknownConfidential to @NonConfidential +}) public class UnionCrash { void foo(MyInterface param) throws Throwable { try { From 02492b0aaba2560b0b25905a857586b5765766a7 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Mon, 19 May 2025 17:01:22 -0700 Subject: [PATCH 175/184] Warning justifications --- framework/tests/all-systems/Issue577.java | 3 +-- framework/tests/all-systems/Issue6282.java | 2 +- framework/tests/all-systems/MultipleUnions.java | 7 +++---- framework/tests/all-systems/UnionCrash.java | 2 +- framework/tests/all-systems/UnionTypes.java | 4 +--- framework/tests/all-systems/Unions.java | 6 ++---- 6 files changed, 9 insertions(+), 15 deletions(-) diff --git a/framework/tests/all-systems/Issue577.java b/framework/tests/all-systems/Issue577.java index 1c831c686c5..c6cbb3c26f2 100644 --- a/framework/tests/all-systems/Issue577.java +++ b/framework/tests/all-systems/Issue577.java @@ -58,8 +58,7 @@ void foo1(MyInterface param) throws Throwable { try { bar(); } catch (MyExceptionA | MyExceptionB ex1) { - @SuppressWarnings( - "confidential") // correctly prevents invoking get methods on UnknownConfidential + @SuppressWarnings("confidential") // true positive: exception might be UnknownConfidential String s = ex1.getT(); } } diff --git a/framework/tests/all-systems/Issue6282.java b/framework/tests/all-systems/Issue6282.java index 2f2a042a158..b590feebf3e 100644 --- a/framework/tests/all-systems/Issue6282.java +++ b/framework/tests/all-systems/Issue6282.java @@ -9,7 +9,7 @@ public static final MethodHandle setAccessible0_Method() { throw new RuntimeException(); } - @SuppressWarnings("confidential") // correctly prevents exposing @UnknownConfidential throwable + @SuppressWarnings("confidential") // true positive: thrown exception might be @UnknownConfidential public static void setAccessible(final AccessibleObject accessibleObject) { try { diff --git a/framework/tests/all-systems/MultipleUnions.java b/framework/tests/all-systems/MultipleUnions.java index 6d4eb450743..bc1b9afc29d 100644 --- a/framework/tests/all-systems/MultipleUnions.java +++ b/framework/tests/all-systems/MultipleUnions.java @@ -2,10 +2,9 @@ public class MultipleUnions { public static boolean flag = false; @SuppressWarnings({ - "ainfertest", - "confidential" - }) // only check WPI for crashes; correctly prevents cast of @UnknownConfidential to - // @NonConfidential + "ainfertest", // only check WPI for crashes + "confidential" // true positive: thrown exception might be @UnknownConfidential + }) void foo1(MyInterface param) throws Throwable { try { bar(); diff --git a/framework/tests/all-systems/UnionCrash.java b/framework/tests/all-systems/UnionCrash.java index ef77932baab..de0b04ea3a7 100644 --- a/framework/tests/all-systems/UnionCrash.java +++ b/framework/tests/all-systems/UnionCrash.java @@ -3,7 +3,7 @@ @SuppressWarnings({ "ainfertest", // only check WPI for crashes - "confidential" // correctly prevents cast of @UnknownConfidential to @NonConfidential + "confidential" // true positive: thrown exception might be @UnknownConfidential }) public class UnionCrash { void foo(MyInterface param) throws Throwable { diff --git a/framework/tests/all-systems/UnionTypes.java b/framework/tests/all-systems/UnionTypes.java index 29db6569932..dbfc5b7724b 100644 --- a/framework/tests/all-systems/UnionTypes.java +++ b/framework/tests/all-systems/UnionTypes.java @@ -6,9 +6,7 @@ public void TryCatch() { int[] arr = new int[10]; arr[4] = 1; } catch (ArrayIndexOutOfBoundsException | StringIndexOutOfBoundsException exc) { - @SuppressWarnings( - "confidential") // correctly prevents cast of @UnknownConfidential to @NonConfidential - // Exception + @SuppressWarnings("confidential") // true positive: exception might be @UnknownConfidential Exception e = exc; } } diff --git a/framework/tests/all-systems/Unions.java b/framework/tests/all-systems/Unions.java index 9bcdf0310d3..1c048dcd421 100644 --- a/framework/tests/all-systems/Unions.java +++ b/framework/tests/all-systems/Unions.java @@ -1,7 +1,6 @@ @SuppressWarnings("ainfertest") // only check WPI for crashes public class Unions { - @SuppressWarnings( - "confidential") // correctly prevents cast of @UnknownConfidential to @NonConfidential + @SuppressWarnings("confidential") // true positive: thrown exception might be @UnknownConfidential void foo1(MyInterface param) throws Throwable { try { bar(); @@ -14,8 +13,7 @@ void foo1(MyInterface param) throws Throwable { } } - @SuppressWarnings( - "confidential") // correctly prevents cast of @UnknownConfidential to @NonConfidential + @SuppressWarnings("confidential") // true positive: thrown exception might be @UnknownConfidential void foo2(MyInterface param) throws Throwable { try { bar(); From fd7ee4d5cd6155d5517a3104e4eccb3de5571ac5 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 5 Jun 2025 18:47:28 -0700 Subject: [PATCH 176/184] Code review changes --- .../confidential/ConfidentialChecker.java | 4 +- .../confidential/ConfidentialTransfer.java | 10 +- docs/manual/confidential-checker.tex | 115 +++++++++--------- docs/manual/figures/confidential.svg | 18 +-- 4 files changed, 76 insertions(+), 71 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java index 6c4cecbc0ed..53f14ebd8a9 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialChecker.java @@ -8,7 +8,9 @@ * A type-checker plug-in for the Confidential type system qualifier that finds (and verifies the * absence of) information leakage bugs. * - *

It verifies that no confidential values are passed to user-facing methods. + *

It verifies that no confidential values are passed to sensitive sinks. A sensitive sink has a + * formal parameter type of {@code @NonConfidential}. One example of a sensitive sink is a method + * that displays information to the user. * * @checker_framework.manual #confidential-checker Confidential Checker */ diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java index 6a1a6170c53..e9403078e24 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java @@ -51,12 +51,12 @@ public TransferResult visitStringConcatenate( } /** - * Determines the resulting type of the string concatenation. + * Determines the type of a string concatenation. * * @param leftOperand the left operand to be concatenated * @param rightOperand the right operand to be concatenated - * @param p the input types - * @param result the result types + * @param p the input abstract values + * @param result the result abstract values * @return the resulting type of the string concatenation operation. */ public TransferResult stringConcatenation( @@ -74,8 +74,8 @@ public TransferResult stringConcatenation( * * @param leftOperand the left operand to be concatenated * @param rightOperand the right operand to be concatenated - * @param p the input types - * @return the resulting AnnotationMirror of the string concatenation operation. + * @param p the input abstract values + * @return the resulting AnnotationMirror of the string concatenation operation */ private AnnotationMirror createAnnotationForStringConcatenation( Node leftOperand, Node rightOperand, TransferInput p) { diff --git a/docs/manual/confidential-checker.tex b/docs/manual/confidential-checker.tex index 8805f603131..2b62ab6ce88 100644 --- a/docs/manual/confidential-checker.tex +++ b/docs/manual/confidential-checker.tex @@ -1,42 +1,33 @@ \htmlhr -\chapterAndLabel{Confidential Checker}{confidential-checker} +\chapterAndLabel{Confidential Checker for information leakage}{confidential-checker} The Confidential Checker identifies \href{https://cwe.mitre.org/data/definitions/1417.html}{sensitive information -exposure}, also known as information leakage. An information leak occurs when private information -such as PII (personally identifiable information), passwords, or local file -paths is revealed. Information is revealed by being passed to -a public-facing sink, such as website and app user interfaces, -log files, error messages, and URL targets. +exposure}, also known as information leakage. An information leak occurs +when private information is revealed by being passed to a public-facing +sink, such as website and app user interfaces, log files, error messages, +and URL targets. Private information includes PII (personally identifiable +information), passwords, local file paths, or whatever data the user +chooses. The Confidential Checker guarantees that no values marked as -\emph{confidential} flow to a location marked as -\emph{non-confidential}. +\emph{confidential} flow to a location marked as \emph{non-confidential}. It is the responsibility of the user to annotate sources and sinks as -confidential or non-confidential. +confidential or non-confidential. Sources are locations where information +is created, such as being read from a file. Sinks are locations where +information is used, such as being displayed on a screen or printed to a +log. The Confidential Checker ships with many sinks annotated, both in the +JDK and in popular libraries, but the user may want to annotate more sinks. + Since \code{@NonConfidential} is the default annotation, if a programmer forgets to annotate a sensitive source as \<@Confidential>, then there will be an information leak that the Confidential Checker cannot warn about. -Once sources and sinks are annotated, the Confidential -Checker guarantees that any other annotations in the program are consistent -with those annotations, and that no information flows from confidential to +Once sources and sinks are annotated, the Confidential Checker guarantees +that any other annotations in the program are consistent with those +annotations, and that no information flows from confidential to non-confidential locations. -The confidential checker does not identify \emph{indirect} information flows, such -as in: - -\begin{Verbatim} - // Information is leaked, but the Confidential Checker issues no error. - @Confidential boolean secret = ...; - @NonConfidential boolean revealed; - if (secret) { - revealed = true; - } else { - revealed = false; - } -\end{Verbatim} - Exposure may occur mistakenly --- in which case it should be fixed --- or with a benign objective in mind, such as when logging to aid troubleshooting. After the Confidential Checker reveals a @@ -50,11 +41,27 @@ \end{Verbatim} +\sectionAndLabel{Only direct leakage, via a chain of assignments}{confidential-direct-only} + +The Confidential Checker does \emph{not} identify \emph{indirect} +information flows, such as in: + +\begin{Verbatim} + // Information is leaked, but the Confidential Checker issues no error. + @Confidential boolean secret = ...; + @NonConfidential boolean revealed; + if (secret) { + revealed = true; + } else { + revealed = false; + } +\end{Verbatim} + + \sectionAndLabel{Confidential annotations}{confidential-annotations} -The Confidential Checker type system uses the following type qualifiers; -their subtyping hierarchy is shown in -Figure~\ref{fig-confidential-hierarchy}. +The Confidential Checker type system uses the following type qualifiers. +Figure~\ref{fig-confidential-hierarchy} shows their subtyping hierarchy. \begin{description} \item[\refqualclass{checker/confidential/qual}{Confidential}] @@ -81,43 +88,39 @@ \begin{figure} \includeimage{confidential}{5.5cm} \caption{The subtyping relationship of the Confidential Checker's qualifiers. + Any cast to \refqualclass{checker/confidential/qual}{Confidential} is permitted. Qualifiers in gray are used internally by the type system and should rarely - be written by a programmer.} + be written by a programmer. +} \label{fig-confidential-hierarchy} \end{figure} -The Confidential Checker's -\code{@Confidential} qualifier has similarities to the Taint Checker's \code{@Tainted} -qualifier. One difference is that +The Confidential Checker's \code{@Confidential} qualifier has similarities +to the Taint Checker's \code{@Tainted} qualifier. One difference is that there is no subtyping relationship between \code{@Confidential} and \code{@NonConfidential}. However, the external behavior of these annotations -can strongly resemble that of a supertype and subtype, as casts from the latter -to the former are always permitted (see Section~\ref{confidential-checks}). As -a result, while the Confidential Checker (correctly) does not allow -\code{@Confidential} values to flow to \code{@NonConfidential} sinks, it does -allow \code{@NonConfidential} values in \code{@Confidential} sinks. +can strongly resemble that of a supertype and subtype, as casts from the +latter to the former are always permitted. As a result, while the +Confidential Checker (correctly) does not allow \code{@Confidential} values +to flow to \code{@NonConfidential} sinks, it does allow +\code{@NonConfidential} values in \code{@Confidential} sinks. \sectionAndLabel{Concatenation}{confidential-concatenation} -Concatenation of \code{@Confidential} and \code{@NonConfidential} values is -always dominated by \code{@Confidential}. In other words, concatenation of +Concatenation of \code{@Confidential} and \code{@NonConfidential} values +results in a \code{@Confidential} value. In other words, concatenation of \code{@Confidential} and \code{@NonConfidential} values are most narrowly typed as follows: \begin{Verbatim} - @Confidential + @Confidential = @Confidential - @Confidential + @NonConfidential = @Confidential - @NonConfidential + @Confidential = @Confidential - @NonConfidential + @NonConfidential = @NonConfidential + @Confidential String c; + @NonConfidential String nc; + c + c // has type @Confidential + c + nc // has type @Confidential + nc + c // has type @Confidential + nc + nc // has type @NonConfidential \end{Verbatim} -However, casts of any type in the Confidential hierarchy to \code{@Confidential} -are always allowed as they do not pose a risk of sensitive information exposure: -\code{@NonConfidential} to \code{@Confidential} casts only increase stringency, -while \code{@UnknownConfidential} is subtyped by \code{@Confidential}, -\code{@NonConfidential} and can thus be safely cast. This allowance was motivated -by a high percentage of \code{@SuppressWarnings} annotations being written to allow -casts from \code{@NonConfidential} to \code{@Confidential}. \sectionAndLabel{Library annotations}{confidential-library-annotations} @@ -125,20 +128,20 @@ sinks. For instance, methods in Android's \code{TextView} class have a formal parameter of type \code{@NonConfidential CharSequence}, indicating that they display the argument on the user's viewport. The Confidential -Checker will issue a type error if a \<@Confidential> value can be passed -to such functions. +Checker will issue a type error anywhere that a \<@Confidential> value can +be passed to such functions. The built-in annotations appear in the Checker Framework's annotated JDK and in stub files in directory -\. +\. A developer can write more annotations in stub files -(\chapterpageref{stub}), especially for libraries that do not already have +(\sectionpageref{stub}), especially for libraries that do not already have annotations. (Please share these with the Checker Framework developers, so that they can distribute them to all users.) If a program contains a method that tests whether a run-time value is confidential, use annotation -\refqualclass{framework/qual}{EnsuresQualifierIf} (\chapterpageref{type-refinement}). +\refqualclass{framework/qual}{EnsuresQualifierIf} (\sectionpageref{type-refinement}). If a program contains a method that takes a possibly-confidential argument and returns a non-confidential result, then suppress the warning diff --git a/docs/manual/figures/confidential.svg b/docs/manual/figures/confidential.svg index 665a69d7179..d1d32fbf236 100644 --- a/docs/manual/figures/confidential.svg +++ b/docs/manual/figures/confidential.svg @@ -5,7 +5,7 @@ viewBox="619 259 362.00001 293.33333" id="svg2" version="1.1" - inkscape:version="1.3.2 (091e20e, 2023-11-25, custom)" + inkscape:version="1.2.2 (b0a8486541, 2022-12-01)" sodipodi:docname="confidential.svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" @@ -112,18 +112,18 @@ guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" - inkscape:window-width="1920" - inkscape:window-height="1094" + inkscape:window-width="2560" + inkscape:window-height="1531" id="namedview76" showgrid="false" inkscape:snap-page="true" inkscape:zoom="2.5267749" - inkscape:cx="177.49899" - inkscape:cy="148.60841" - inkscape:window-x="-11" - inkscape:window-y="-11" + inkscape:cx="177.69687" + inkscape:cy="149.00417" + inkscape:window-x="0" + inkscape:window-y="0" inkscape:window-maximized="1" - inkscape:current-layer="svg2" + inkscape:current-layer="g4-7" inkscape:snap-others="true" fit-margin-top="0" fit-margin-left="0" @@ -160,7 +160,7 @@ id="text10-9-7">@NonConfidential + id="tspan12-7-6">@Confidential Date: Thu, 5 Jun 2025 18:51:07 -0700 Subject: [PATCH 177/184] Fix Javadoc style --- .../calledmethods/qual/EnsuresCalledMethodsOnException.java | 2 +- .../checkerframework/checker/nonempty/NonEmptyTransfer.java | 2 +- .../checker/optional/OptionalImplAnnotatedTypeFactory.java | 2 +- .../checker/resourceleak/MustCallConsistencyAnalyzer.java | 2 +- .../checkerframework/dataflow/analysis/AnalysisResult.java | 2 +- .../org/checkerframework/framework/source/SourceChecker.java | 2 +- .../util/typeinference8/types/AbstractQualifier.java | 4 ++-- .../framework/util/typeinference8/types/InvocationType.java | 2 +- .../framework/util/typeinference8/types/QualifierVar.java | 2 +- .../framework/util/typeinference8/types/VariableBounds.java | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsOnException.java b/checker-qual/src/main/java/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsOnException.java index f0f0cb43261..b9850da3c3e 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsOnException.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/calledmethods/qual/EnsuresCalledMethodsOnException.java @@ -63,7 +63,7 @@ // /** // * Returns the exception types under which the postcondition holds. // * - // * @return the exception types under which the postcondition holds. + // * @return the exception types under which the postcondition holds // */ // Class[] exceptions(); diff --git a/checker/src/main/java/org/checkerframework/checker/nonempty/NonEmptyTransfer.java b/checker/src/main/java/org/checkerframework/checker/nonempty/NonEmptyTransfer.java index 79e8ab25852..f9cba825835 100644 --- a/checker/src/main/java/org/checkerframework/checker/nonempty/NonEmptyTransfer.java +++ b/checker/src/main/java/org/checkerframework/checker/nonempty/NonEmptyTransfer.java @@ -182,7 +182,7 @@ private void strengthenAnnotationSizeEquals( * * @param in used to get the type of {@code methodAccessNode}. * @param methodAccessNode method access - * @return true if the receiver of {@code methodAccessNode} is non-empty according to {@code in}. + * @return true if the receiver of {@code methodAccessNode} is non-empty according to {@code in} */ private boolean isAccessOfNonEmptyCollection( TransferInput in, MethodInvocationNode methodAccessNode) { diff --git a/checker/src/main/java/org/checkerframework/checker/optional/OptionalImplAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/optional/OptionalImplAnnotatedTypeFactory.java index 4cba4a993ab..737c96692f6 100644 --- a/checker/src/main/java/org/checkerframework/checker/optional/OptionalImplAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/optional/OptionalImplAnnotatedTypeFactory.java @@ -117,7 +117,7 @@ private boolean isReturnTypeNullable(MemberReferenceTree memberReferenceTree) { * Returns true if {@code annos} contains an annotation named "Nullable". * * @param annos a collection of annotations - * @return true if {@code annos} contains an annotation named "Nullable". + * @return true if {@code annos} contains an annotation named "Nullable" */ private boolean containsNullable(Collection annos) { for (AnnotationMirror anno : annos) { diff --git a/checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallConsistencyAnalyzer.java b/checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallConsistencyAnalyzer.java index eb90a42a4fb..bdb5567a38e 100644 --- a/checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallConsistencyAnalyzer.java +++ b/checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallConsistencyAnalyzer.java @@ -2156,7 +2156,7 @@ private void propagateObligationsToSuccessorBlock( * * @param currentBlock source block of the CFG edge. Must contain no {@link Node}s. * @param successor target block of the CFG edge. - * @return store propagated by the {@link RLCCalledMethodsAnalysis} along the CFG edge. + * @return store propagated by the {@link RLCCalledMethodsAnalysis} along the CFG edge */ private AccumulationStore getStoreForEdgeFromEmptyBlock(Block currentBlock, Block successor) { switch (currentBlock.getType()) { diff --git a/dataflow/src/main/java/org/checkerframework/dataflow/analysis/AnalysisResult.java b/dataflow/src/main/java/org/checkerframework/dataflow/analysis/AnalysisResult.java index bb01637a33c..bbb14cfb79b 100644 --- a/dataflow/src/main/java/org/checkerframework/dataflow/analysis/AnalysisResult.java +++ b/dataflow/src/main/java/org/checkerframework/dataflow/analysis/AnalysisResult.java @@ -341,7 +341,7 @@ public S getStoreBefore(Block block) { * Returns the TransferInput for the given block. * * @param block a CFG Block - * @return the TransferInput for the given block. + * @return the TransferInput for the given block */ public @Nullable TransferInput getInput(Block block) { return inputs.get(block); diff --git a/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java b/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java index 7dc1a1736be..c124c17a06f 100644 --- a/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java +++ b/framework/src/main/java/org/checkerframework/framework/source/SourceChecker.java @@ -1228,7 +1228,7 @@ public List getSubcheckers() { /** * Get the shared TreePathCacher instance. * - * @return the shared TreePathCacher instance. + * @return the shared TreePathCacher instance */ public TreePathCacher getTreePathCacher() { if (treePathCacher == null) { diff --git a/framework/src/main/java/org/checkerframework/framework/util/typeinference8/types/AbstractQualifier.java b/framework/src/main/java/org/checkerframework/framework/util/typeinference8/types/AbstractQualifier.java index dc97fd6fbc4..a9b470a3e22 100644 --- a/framework/src/main/java/org/checkerframework/framework/util/typeinference8/types/AbstractQualifier.java +++ b/framework/src/main/java/org/checkerframework/framework/util/typeinference8/types/AbstractQualifier.java @@ -43,7 +43,7 @@ public abstract class AbstractQualifier { * Returns whether {@code other} is in the same hierarchy as this. * * @param other another abstract qualifier - * @return whether {@code other} is in the same hierarchy as this. + * @return whether {@code other} is in the same hierarchy as this */ public boolean sameHierarchy(AbstractQualifier other) { return this.hierarchyName == other.hierarchyName; @@ -52,7 +52,7 @@ public boolean sameHierarchy(AbstractQualifier other) { /** * Returns the instantiation of this. * - * @return the instantiation of this. + * @return the instantiation of this */ abstract AnnotationMirror getInstantiation(); diff --git a/framework/src/main/java/org/checkerframework/framework/util/typeinference8/types/InvocationType.java b/framework/src/main/java/org/checkerframework/framework/util/typeinference8/types/InvocationType.java index 844cd5c8865..b53fad23456 100644 --- a/framework/src/main/java/org/checkerframework/framework/util/typeinference8/types/InvocationType.java +++ b/framework/src/main/java/org/checkerframework/framework/util/typeinference8/types/InvocationType.java @@ -210,7 +210,7 @@ public List getParameterTypes(Theta map) { /** * Whether this method has type variables. * - * @return whether this method has type variables. + * @return whether this method has type variables */ public boolean hasTypeVariables() { return !annotatedExecutableType.getTypeVariables().isEmpty(); diff --git a/framework/src/main/java/org/checkerframework/framework/util/typeinference8/types/QualifierVar.java b/framework/src/main/java/org/checkerframework/framework/util/typeinference8/types/QualifierVar.java index 27b4ff6b0e5..2174e7c4ff9 100644 --- a/framework/src/main/java/org/checkerframework/framework/util/typeinference8/types/QualifierVar.java +++ b/framework/src/main/java/org/checkerframework/framework/util/typeinference8/types/QualifierVar.java @@ -84,7 +84,7 @@ public String toString() { * * @param kind a bound kind * @param otherQual the bound to add - * @return a set of constraints generated from adding this bound. + * @return a set of constraints generated from adding this bound */ @SuppressWarnings("interning:not.interned") // Checking for exact object. public ConstraintSet addBound(BoundKind kind, AbstractQualifier otherQual) { diff --git a/framework/src/main/java/org/checkerframework/framework/util/typeinference8/types/VariableBounds.java b/framework/src/main/java/org/checkerframework/framework/util/typeinference8/types/VariableBounds.java index 9bf00ccc0ba..e43ac27883b 100644 --- a/framework/src/main/java/org/checkerframework/framework/util/typeinference8/types/VariableBounds.java +++ b/framework/src/main/java/org/checkerframework/framework/util/typeinference8/types/VariableBounds.java @@ -397,7 +397,7 @@ private List getConstraintsFromParameterized(AbstractType s, AbstractTyp /** * Returns whether this variable only has bounds against proper types. * - * @return whether this variable only has bounds against proper types. + * @return whether this variable only has bounds against proper types */ public boolean onlyProperBounds() { for (BoundKind k : BoundKind.values()) { From 0ceb6a7578447c7283a11c8c5ef391a2b016fb84 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 5 Jun 2025 18:55:14 -0700 Subject: [PATCH 178/184] Fix Javadoc style --- .../checker/confidential/ConfidentialTransfer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java index e9403078e24..df43b0f4183 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java @@ -57,7 +57,7 @@ public TransferResult visitStringConcatenate( * @param rightOperand the right operand to be concatenated * @param p the input abstract values * @param result the result abstract values - * @return the resulting type of the string concatenation operation. + * @return the resulting type of the string concatenation operation */ public TransferResult stringConcatenation( Node leftOperand, @@ -119,7 +119,7 @@ private AnnotationMirror createAnnotationForStringConcatenation( * Returns the annotation in the Confidential type hierarchy for the given value. * * @param cfValue the value - * @return the value's AnnotationMirror from the Confidential hierarchy. + * @return the value's AnnotationMirror from the Confidential hierarchy */ private AnnotationMirror getValueAnnotation(CFValue cfValue) { return qualHierarchy.findAnnotationInHierarchy( From 166868a8c5fa8624ee1ce2fb1b1bca33fb8abfb3 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 5 Jun 2025 18:59:00 -0700 Subject: [PATCH 179/184] Documentation improvements --- .../checker/confidential/qual/Confidential.java | 5 +++-- .../checker/confidential/qual/UnknownConfidential.java | 3 ++- .../checker/confidential/ConfidentialVisitor.java | 3 +++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java index d9b0f6a6600..cbbaede733d 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/Confidential.java @@ -11,8 +11,9 @@ * Denotes a value that will not be exposed to end users or a sink that will not be able to be * accessed by end users. * - *

Typically, a Confidential value will contain sensitive, private, or otherwise - * privileged-access information, such as passwords, PII, and private keys. + *

A Confidential value may contain sensitive, private, or otherwise privileged-access + * information. Examples include passwords, PII (personally identifiable information), and private + * keys. * * @see NonConfidential * @see org.checkerframework.checker.confidential.ConfidentialChecker diff --git a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/UnknownConfidential.java b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/UnknownConfidential.java index 6bf37fd46fd..f0d356c915a 100644 --- a/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/UnknownConfidential.java +++ b/checker-qual/src/main/java/org/checkerframework/checker/confidential/qual/UnknownConfidential.java @@ -11,7 +11,8 @@ import org.checkerframework.framework.qual.TypeUseLocation; /** - * Represents the top of the Confidential qualifier hierarchy. + * Represents a value that might or might not be confidential. This is the top of the Confidential + * qualifier hierarchy. * * @checker_framework.manual #confidential-checker Confidential Checker */ diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialVisitor.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialVisitor.java index 59c39fbcdad..527e11b155b 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialVisitor.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialVisitor.java @@ -26,6 +26,8 @@ public ConfidentialVisitor(BaseTypeChecker checker) { /** * Don't check that the constructor result is top. Checking that the super() or this() call is a * subtype of the constructor result is sufficient. + * + *

{@inheritDoc} */ @Override protected void checkConstructorResult( @@ -39,6 +41,7 @@ protected boolean commonAssignmentCheck( Tree valueTree, @CompilerMessageKey String errorKey, Object... extraArgs) { + // Permit casting anything to @Confidential. if (varType.hasEffectiveAnnotation(Confidential.class)) { return true; } From ef98693295ab22bb9d27b067e2c07a4d7cf59a22 Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 10 Jun 2025 02:27:38 -0700 Subject: [PATCH 180/184] Updated confidential checker method documentation --- .../confidential/ConfidentialAnnotatedTypeFactory.java | 9 +++------ .../checker/confidential/ConfidentialTransfer.java | 4 +++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java index f645dd8aa7e..7953520d82d 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialAnnotatedTypeFactory.java @@ -96,14 +96,11 @@ public CFTransfer createFlowTransferFunction( } /** - * A TreeAnnotator to enforce Confidential String concatenation rules: + * A TreeAnnotator to enforce certain toString return type rules: * *

    - *
  • (Confidential + NonConfidential) returns Confidential (commutatively); - *
  • (Confidential + Confidential) returns Confidential; - *
  • (NonConfidential + NonConfidential) returns NonConfidential; - *
  • UnknownConfidential dominates other types in concatenation; - *
  • Non-bottom types dominate BottomConfidential in concatenation. + *
  • toString(@NonConfidential this) can return @NonConfidential or @Confidential String + *
  • toString(@Confidential this) can return @Confidential String *
*/ private class ConfidentialTreeAnnotator extends TreeAnnotator { diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java index 6a1a6170c53..2545480cdfa 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java @@ -75,7 +75,9 @@ public TransferResult stringConcatenation( * @param leftOperand the left operand to be concatenated * @param rightOperand the right operand to be concatenated * @param p the input types - * @return the resulting AnnotationMirror of the string concatenation operation. + * @return the resulting AnnotationMirror of the string concatenation operation, or + * null if either leftOperand or rightOperand are null or either operand does not + * belong to the Confidential hierarchy. */ private AnnotationMirror createAnnotationForStringConcatenation( Node leftOperand, Node rightOperand, TransferInput p) { From 29d699b5c603c3bdf77c706e37923d6093902eca Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 10 Jun 2025 02:31:07 -0700 Subject: [PATCH 181/184] Updated confidential checker method documentation --- .../checker/confidential/ConfidentialTransfer.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java index df43b0f4183..0c7320eea06 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java @@ -75,7 +75,9 @@ public TransferResult stringConcatenation( * @param leftOperand the left operand to be concatenated * @param rightOperand the right operand to be concatenated * @param p the input abstract values - * @return the resulting AnnotationMirror of the string concatenation operation + * @return the resulting AnnotationMirror of the string concatenation operation, + * or null if either leftOperand or rightOperand is null or either operand + * does not belong to the Confidential hierarchy. */ private AnnotationMirror createAnnotationForStringConcatenation( Node leftOperand, Node rightOperand, TransferInput p) { From 1ddbd4dbfe43229e4bf3952357f800113179016a Mon Sep 17 00:00:00 2001 From: iywang2016 Date: Tue, 10 Jun 2025 02:46:42 -0700 Subject: [PATCH 182/184] spotlessApply --- .../checker/confidential/ConfidentialTransfer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java index 0c7320eea06..10c260c5794 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java @@ -75,9 +75,9 @@ public TransferResult stringConcatenation( * @param leftOperand the left operand to be concatenated * @param rightOperand the right operand to be concatenated * @param p the input abstract values - * @return the resulting AnnotationMirror of the string concatenation operation, - * or null if either leftOperand or rightOperand is null or either operand - * does not belong to the Confidential hierarchy. + * @return the resulting AnnotationMirror of the string concatenation operation, or null if either + * leftOperand or rightOperand is null or either operand does not belong to the Confidential + * hierarchy. */ private AnnotationMirror createAnnotationForStringConcatenation( Node leftOperand, Node rightOperand, TransferInput p) { From ef604fb0156cb341c60a78b309262560ba34e18e Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Wed, 11 Jun 2025 08:33:03 -0700 Subject: [PATCH 183/184] Simplify code --- .../confidential/ConfidentialTransfer.java | 25 ++++--------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java index 10c260c5794..0482265ed12 100644 --- a/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java +++ b/checker/src/main/java/org/checkerframework/checker/confidential/ConfidentialTransfer.java @@ -86,35 +86,20 @@ private AnnotationMirror createAnnotationForStringConcatenation( if (leftAnno == null) { return null; } - String leftAnnoName = AnnotationUtils.annotationName(leftAnno); CFValue rightValue = p.getValueOfSubNode(rightOperand); AnnotationMirror rightAnno = getValueAnnotation(rightValue); if (rightAnno == null) { return null; } - String rightAnnoName = AnnotationUtils.annotationName(rightAnno); - if (leftAnnoName.equals(ConfidentialAnnotatedTypeFactory.UNKNOWN_CONFIDENTIAL_NAME) - || rightAnnoName.equals(ConfidentialAnnotatedTypeFactory.UNKNOWN_CONFIDENTIAL_NAME)) { - return atypeFactory.UNKNOWN_CONFIDENTIAL; - } - - if (leftAnnoName.equals(ConfidentialAnnotatedTypeFactory.BOTTOM_CONFIDENTIAL_NAME)) { - return rightAnno; - } else if (rightAnnoName.equals(ConfidentialAnnotatedTypeFactory.BOTTOM_CONFIDENTIAL_NAME)) { - return leftAnno; - } - - if (leftAnnoName.equals(ConfidentialAnnotatedTypeFactory.CONFIDENTIAL_NAME) - || rightAnnoName.equals(ConfidentialAnnotatedTypeFactory.CONFIDENTIAL_NAME)) { + if (AnnotationUtils.areSameByName(leftAnno, ConfidentialAnnotatedTypeFactory.CONFIDENTIAL_NAME) + || AnnotationUtils.areSameByName( + rightAnno, ConfidentialAnnotatedTypeFactory.CONFIDENTIAL_NAME)) { return atypeFactory.CONFIDENTIAL; } - if (leftAnnoName.equals(ConfidentialAnnotatedTypeFactory.NONCONFIDENTIAL_NAME) - && rightAnnoName.equals(ConfidentialAnnotatedTypeFactory.NONCONFIDENTIAL_NAME)) { - return atypeFactory.NONCONFIDENTIAL; - } - return null; + return qualHierarchy.leastUpperBoundShallow( + leftAnno, leftOperand.getType(), rightAnno, rightOperand.getType()); } /** From 1ac76ce2b8faabd6bbd42c175b721f92630f1b72 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Fri, 18 Jul 2025 16:23:21 -0700 Subject: [PATCH 184/184] Add changelog entry --- docs/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index df8f9a54a7c..c55cb5ac4d3 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -3,6 +3,8 @@ Version 3.49.6 (August 1, 2025) **User-visible changes:** +New Confidential Checker to identify sensitive information exposure. + **Implementation details:** **Closed issues:**