8000 SQL tainting qualifiers and basic tests by iywang2016 · Pull Request #1 · iywang2016/checker-framework · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

SQL tainting qualifiers and basic tests #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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 {}
Original file line number Diff line number Diff line change
@@ -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 {}
Original file line number Diff line number Diff line change
@@ -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.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 for SQL query use.
*
* <p>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(stringPatterns = "^(\\w|\\s|\\\\'|\\\\\"|\\\\\\\\|\\\\-|\\\\%|\\\\_)*$")
@DefaultFor(TypeUseLocation.LOWER_BOUND)
public @interface SqlSanitized {}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -11,11 +11,12 @@
/** Annotated type factory for the SQL Tainting Checker. */
public class SqlTaintingAnnotatedTypeFactory extends BaseAnnotatedTypeFactory {

/** The {@code @}{@link SqlSafe} annotation mirror. */
private final AnnotationMirror SQLSAFE;

/** A singleton set containing the {@code @}{@link SqlSafe} annotation mirror. */
private final AnnotationMirrorSet setOfSqlSafe;
/** 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}.
Expand All @@ -24,13 +25,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<AnnotationMirror> getEnumConstructorQualifiers() {
return setOfSqlSafe;
return setOfSqlSanitized;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@
*
* @checker_framework.manual #tainting-checker Tainting Checker
*/
@SuppressWarningsPrefix({"sqlsafe", "sqltainting"})

@SuppressWarningsPrefix({"sqlsanitized", "sqltainting"})
public class SqlTaintingChecker extends BaseTypeChecker {}
48 changes: 48 additions & 0 deletions checker/tests/sqltainting/SimpleSqlQueryValue.java
Original file line number Diff line number Diff line change
@@ -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);
}
}
43 changes: 43 additions & 0 deletions checker/tests/sqltainting/SqlSanitizedRegex.java
Original file line number Diff line number Diff line change
@@ -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
}
}
0