diff --git a/src/java.base/share/classes/java/io/PrintStream.java b/src/java.base/share/classes/java/io/PrintStream.java index 0b77dbb1e1530..e1d07a313120a 100644 --- a/src/java.base/share/classes/java/io/PrintStream.java +++ b/src/java.base/share/classes/java/io/PrintStream.java @@ -25,6 +25,7 @@ package java.io; +import org.checkerframework.checker.confidential.qual.NonConfidential; import org.checkerframework.checker.formatter.qual.FormatMethod; import org.checkerframework.checker.i18n.qual.Localized; import org.checkerframework.checker.index.qual.IndexOrHigh; @@ -74,7 +75,7 @@ */ @CFComment({"lock: TODO: Should parameters be @GuardSatisfied, or is the default of @GuardedBy({}) appropriate? (@GuardedBy({}) is more conservative.)"}) -@AnnotatedFor({"formatter", "i18n", "index", "lock", "mustcall", "nullness", "signedness"}) +@AnnotatedFor({"formatter", "i18n", "index", "lock", "mustcall", "nullness", "signedness", "confidential"}) public class PrintStream extends FilterOutputStream implements Appendable, Closeable { @@ -790,7 +791,7 @@ public void print(@GuardSatisfied PrintStream this, boolean b) { * * @param c The {@code char} to be printed */ - public void print(@GuardSatisfied PrintStream this, char c) { + public void print(@GuardSatisfied PrintStream this, @NonConfidential char c) { write(String.valueOf(c)); } @@ -804,7 +805,7 @@ public void print(@GuardSatisfied PrintStream this, char c) { * @param i The {@code int} to be printed * @see java.lang.Integer#toString(int) */ - public void print(@GuardSatisfied PrintStream this, int i) { + public void print(@GuardSatisfied PrintStream this, @NonConfidential int i) { write(String.valueOf(i)); } @@ -818,7 +819,7 @@ public void print(@GuardSatisfied PrintStream this, int i) { * @param l The {@code long} to be printed * @see java.lang.Long#toString(long) */ - public void print(@GuardSatisfied PrintStream this, long l) { + public void print(@GuardSatisfied PrintStream this, @NonConfidential long l) { write(String.valueOf(l)); } @@ -832,7 +833,7 @@ public void print(@GuardSatisfied PrintStream this, long l) { * @param f The {@code float} to be printed * @see java.lang.Float#toString(float) */ - public void print(@GuardSatisfied PrintStream this, float f) { + public void print(@GuardSatisfied PrintStream this, @NonConfidential float f) { write(String.valueOf(f)); } @@ -846,7 +847,7 @@ public void print(@GuardSatisfied PrintStream this, float f) { * @param d The {@code double} to be printed * @see java.lang.Double#toString(double) */ - public void print(@GuardSatisfied PrintStream this, double d) { + public void print(@GuardSatisfied PrintStream this, @NonConfidential double d) { write(String.valueOf(d)); } @@ -860,7 +861,7 @@ public void print(@GuardSatisfied PrintStream this, double d) { * * @throws NullPointerException If {@code s} is {@code null} */ - public void print(@GuardSatisfied PrintStream this, @PolySigned char s[]) { + public void print(@GuardSatisfied PrintStream this, @NonConfidential @PolySigned char s[]) { write(s); } @@ -874,7 +875,7 @@ public void print(@GuardSatisfied PrintStream this, @PolySigned char s[]) { * * @param s The {@code String} to be printed */ - public void print(@GuardSatisfied PrintStream this, @Nullable String s) { + public void print(@GuardSatisfied PrintStream this, @NonConfidential @Nullable String s) { write(String.valueOf(s)); } @@ -888,7 +889,7 @@ public void print(@GuardSatisfied PrintStream this, @Nullable String s) { * @param obj The {@code Object} to be printed * @see java.lang.Object#toString() */ - public void print(@GuardSatisfied PrintStream this, @Nullable Object obj) { + public void print(@GuardSatisfied PrintStream this, @NonConfidential @Nullable Object obj) { write(String.valueOf(obj)); } @@ -930,7 +931,7 @@ public void println(@GuardSatisfied PrintStream this, boolean x) { * * @param x The {@code char} to be printed. */ - public void println(@GuardSatisfied PrintStream this, char x) { + public void println(@GuardSatisfied PrintStream this, @NonConfidential char x) { if (getClass() == PrintStream.class) { writeln(String.valueOf(x)); } else { @@ -948,7 +949,7 @@ public void println(@GuardSatisfied PrintStream this, char x) { * * @param x The {@code int} to be printed. */ - public void println(@GuardSatisfied PrintStream this, int x) { + public void println(@GuardSatisfied PrintStream this, @NonConfidential int x) { if (getClass() == PrintStream.class) { writeln(String.valueOf(x)); } else { @@ -966,7 +967,7 @@ public void println(@GuardSatisfied PrintStream this, int x) { * * @param x a The {@code long} to be printed. */ - public void println(@GuardSatisfied PrintStream this, long x) { + public void println(@GuardSatisfied PrintStream this, @NonConfidential long x) { if (getClass() == PrintStream.class) { writeln(String.valueOf(x)); } else { @@ -984,7 +985,7 @@ public void println(@GuardSatisfied PrintStream this, long x) { * * @param x The {@code float} to be printed. */ - public void println(@GuardSatisfied PrintStream this, float x) { + public void println(@GuardSatisfied PrintStream this, @NonConfidential float x) { if (getClass() == PrintStream.class) { writeln(String.valueOf(x)); } else { @@ -1002,7 +1003,7 @@ public void println(@GuardSatisfied PrintStream this, float x) { * * @param x The {@code double} to be printed. */ - public void println(@GuardSatisfied PrintStream this, double x) { + public void println(@GuardSatisfied PrintStream this, @NonConfidential double x) { if (getClass() == PrintStream.class) { writeln(String.valueOf(x)); } else { @@ -1020,7 +1021,7 @@ public void println(@GuardSatisfied PrintStream this, double x) { * * @param x an array of chars to print. */ - public void println(@GuardSatisfied PrintStream this, char[] x) { + public void println(@GuardSatisfied PrintStream this, @NonConfidential char[] x) { if (getClass() == PrintStream.class) { writeln(x); } else { @@ -1038,7 +1039,7 @@ public void println(@GuardSatisfied PrintStream this, char[] x) { * * @param x The {@code String} to be printed. */ - public void println(@GuardSatisfied PrintStream this, @Nullable @Localized String x) { + public void println(@GuardSatisfied PrintStream this, @NonConfidential @Nullable @Localized String x) { if (getClass() == PrintStream.class) { writeln(String.valueOf(x)); } else { @@ -1058,7 +1059,7 @@ public void println(@GuardSatisfied PrintStream this, @Nullable @Localized Strin * * @param x The {@code Object} to be printed. */ - public void println(@GuardSatisfied PrintStream this, @Nullable Object x) { + public void println(@GuardSatisfied PrintStream this, @NonConfidential @Nullable Object x) { String s = String.valueOf(x); if (getClass() == PrintStream.class) { // need to apply String.valueOf again since first invocation @@ -1118,7 +1119,7 @@ public void println(@GuardSatisfied PrintStream this, @Nullable Object x) { */ @CFComment({"lock/nullness: The vararg arrays can actually be null, but let's not annotate them because passing null is bad style; see whether this annotation is useful."}) @FormatMethod - public @NotOwning PrintStream printf(@GuardSatisfied PrintStream this, String format, @Nullable Object ... args) { + public @NotOwning @NonConfidential PrintStream printf(@GuardSatisfied PrintStream this, @NonConfidential String format, @NonConfidential @Nullable Object ... args) { return format(format, args); } @@ -1171,7 +1172,7 @@ public void println(@GuardSatisfied PrintStream this, @Nullable Object x) { * @since 1.5 */ @FormatMethod - public @NotOwning PrintStream printf(@GuardSatisfied PrintStream this, @Nullable Locale l, String format, @Nullable Object ... args) { + public @NotOwning @NonConfidential PrintStream printf(@GuardSatisfied PrintStream this, @Nullable Locale l, @NonConfidential String format, @NonConfidential @Nullable Object ... args) { return format(l, format, args); } diff --git a/src/java.base/share/classes/java/lang/Exception.java b/src/java.base/share/classes/java/lang/Exception.java index 117400bfdaa39..8f91bfc0ba25b 100644 --- a/src/java.base/share/classes/java/lang/Exception.java +++ b/src/java.base/share/classes/java/lang/Exception.java @@ -25,10 +25,11 @@ package java.lang; +import org.checkerframework.checker.confidential.qual.PolyConfidential; import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.common.aliasing.qual.Unique; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; -import org.checkerframework.common.aliasing.qual.Unique; /** * The class {@code Exception} and its subclasses are a form of @@ -47,7 +48,7 @@ * @jls 11.2 Compile-Time Checking of Exceptions * @since 1.0 */ -@AnnotatedFor({"aliasing", "nullness"}) +@AnnotatedFor({"aliasing", "nullness", "confidential"}) public class Exception extends Throwable { @java.io.Serial static final long serialVersionUID = -3387516993124229948L; @@ -71,7 +72,7 @@ public class Exception extends Throwable { * later retrieval by the {@link #getMessage()} method. */ @SideEffectFree - public @Unique Exception(@Nullable String message) { + public @Unique Exception(@Nullable @PolyConfidential String message) { super(message); } @@ -90,7 +91,7 @@ public class Exception extends Throwable { * @since 1.4 */ @SideEffectFree - public @Unique Exception(@Nullable String message, @Nullable Throwable cause) { + public @Unique Exception(@Nullable @PolyConfidential String message, @Nullable @PolyConfidential Throwable cause) { super(message, cause); } @@ -109,7 +110,7 @@ public class Exception extends Throwable { * @since 1.4 */ @SideEffectFree - public @Unique Exception(@Nullable Throwable cause) { + public @Unique Exception(@Nullable @PolyConfidential Throwable cause) { super(cause); } @@ -127,7 +128,7 @@ public class Exception extends Throwable { * be writable * @since 1.7 */ - protected @Unique Exception(@Nullable String message, @Nullable Throwable cause, + protected @Unique Exception(@Nullable @PolyConfidential String message, @Nullable @PolyConfidential Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); diff --git a/src/java.base/share/classes/java/lang/Object.java b/src/java.base/share/classes/java/lang/Object.java index 8da3a8c0cb900..38467f1b77a6e 100644 --- a/src/java.base/share/classes/java/lang/Object.java +++ b/src/java.base/share/classes/java/lang/Object.java @@ -25,6 +25,7 @@ package java.lang; +import org.checkerframework.checker.confidential.qual.PolyConfidential; import org.checkerframework.checker.guieffect.qual.PolyUI; import org.checkerframework.checker.guieffect.qual.PolyUIType; import org.checkerframework.checker.guieffect.qual.SafeEffect; @@ -53,7 +54,7 @@ * @see java.lang.Class * @since 1.0 */ -@AnnotatedFor({"aliasing", "guieffect", "index", "lock", "nullness"}) +@AnnotatedFor({"aliasing", "guieffect", "index", "lock", "nullness", "confidential"}) @PolyUIType public class Object { @@ -186,7 +187,7 @@ public class Object { */ @Pure @EnsuresNonNullIf(expression="#1", result=true) - public boolean equals(@GuardSatisfied Object this, @GuardSatisfied @Nullable Object obj) { + public boolean equals(@GuardSatisfied @PolyConfidential Object this, @GuardSatisfied @Nullable @PolyConfidential Object obj) { return (this == obj); } @@ -284,7 +285,7 @@ public boolean equals(@GuardSatisfied Object this, @GuardSatisfied @Nullable Obj "that differs according to ==, and @Deterministic requires that the results of", "two calls of the method are ==."}) @SideEffectFree - public String toString(@GuardSatisfied Object this) { + public @Confidential String toString(@PolyConfidential @GuardSatisfied Object this) { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } diff --git a/src/java.base/share/classes/java/lang/RuntimeException.java b/src/java.base/share/classes/java/lang/RuntimeException.java index 14283e6536461..0099c1c3ee268 100644 --- a/src/java.base/share/classes/java/lang/RuntimeException.java +++ b/src/java.base/share/classes/java/lang/RuntimeException.java @@ -25,6 +25,7 @@ package java.lang; +import org.checkerframework.checker.confidential.qual.PolyConfidential; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; @@ -44,7 +45,7 @@ * @jls 11.2 Compile-Time Checking of Exceptions * @since 1.0 */ -@AnnotatedFor({"nullness"}) +@AnnotatedFor({"nullness", "confidential"}) public class RuntimeException extends Exception { @java.io.Serial static final long serialVersionUID = -7034897190745766939L; @@ -66,7 +67,7 @@ public RuntimeException() { * later retrieval by the {@link #getMessage()} method. */ @SideEffectFree - public RuntimeException(@Nullable String message) { + public RuntimeException(@Nullable @PolyConfidential String message) { super(message); } @@ -85,7 +86,7 @@ public RuntimeException(@Nullable String message) { * @since 1.4 */ @SideEffectFree - public RuntimeException(@Nullable String message, @Nullable Throwable cause) { + public RuntimeException(@Nullable @PolyConfidential String message, @Nullable @PolyConfidential Throwable cause) { super(message, cause); } @@ -102,7 +103,7 @@ public RuntimeException(@Nullable String message, @Nullable Throwable cause) { * @since 1.4 */ @SideEffectFree - public RuntimeException(@Nullable Throwable cause) { + public RuntimeException(@Nullable @PolyConfidential Throwable cause) { super(cause); } @@ -121,7 +122,7 @@ public RuntimeException(@Nullable Throwable cause) { * * @since 1.7 */ - protected RuntimeException(@Nullable String message, @Nullable Throwable cause, + protected RuntimeException(@Nullable @PolyConfidential String message, @Nullable @PolyConfidential Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index babbf173c80c8..9f039500876a2 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -25,6 +25,7 @@ package java.lang; +import org.checkerframework.checker.confidential.qual.PolyConfidential; import org.checkerframework.checker.formatter.qual.FormatMethod; import org.checkerframework.checker.index.qual.IndexFor; import org.checkerframework.checker.index.qual.IndexOrHigh; @@ -171,7 +172,7 @@ * @jls 15.18.1 String Concatenation Operator + */ -@AnnotatedFor({"aliasing", "formatter", "index", "interning", "lock", "nullness", "regex", "signature", "signedness"}) +@AnnotatedFor({"aliasing", "formatter", "index", "interning", "lock", "nullness", "regex", "signature", "signedness", "confidential"}) public final class String implements java.io.Serializable, Comparable, CharSequence, Constable, ConstantDesc { @@ -1910,7 +1911,7 @@ public void getBytes(@IndexOrHigh({"this"}) int srcBegin, @IndexOrHigh({"this"}) @EnsuresNonNullIf(expression={"#1"}, result=true) @Pure @StaticallyExecutable - public boolean equals(@GuardSatisfied @Nullable Object anObject) { + public boolean equals(@PolyConfidential String this, @GuardSatisfied @Nullable @PolyConfidential Object anObject) { if (this == anObject) { return true; } @@ -4327,7 +4328,7 @@ public IntStream codePoints() { @SideEffectFree @StaticallyExecutable @FormatMethod - public static String format(String format, @GuardSatisfied @Nullable Object @GuardSatisfied ... args) { + public static @PolyConfidential String format(String format, @PolyConfidential @GuardSatisfied @Nullable Object @GuardSatisfied ... args) { return new Formatter().format(format, args).toString(); } diff --git a/src/java.base/share/classes/java/lang/Throwable.java b/src/java.base/share/classes/java/lang/Throwable.java index bc8a4fee78b50..74c28da3acdd9 100644 --- a/src/java.base/share/classes/java/lang/Throwable.java +++ b/src/java.base/share/classes/java/lang/Throwable.java @@ -25,6 +25,8 @@ package java.lang; +import org.checkerframework.checker.confidential.qual.NonConfidential; +import org.checkerframework.checker.confidential.qual.PolyConfidential; import org.checkerframework.checker.initialization.qual.UnknownInitialization; import org.checkerframework.checker.interning.qual.UsesObjectEquals; import org.checkerframework.checker.lock.qual.GuardSatisfied; @@ -119,7 +121,7 @@ * @jls 11.2 Compile-Time Checking of Exceptions * @since 1.0 */ -@AnnotatedFor({"interning", "lock", "nullness"}) +@AnnotatedFor({"interning", "lock", "nullness", "confidential"}) public @UsesObjectEquals class Throwable implements Serializable { /** use serialVersionUID from JDK 1.0.2 for interoperability */ @java.io.Serial @@ -394,7 +396,8 @@ protected Throwable(@Nullable String message, @Nullable Throwable cause, * (which may be {@code null}). */ @Pure - public @Nullable String getMessage(@GuardSatisfied Throwable this) { + // TODO: The type should be @Poly. Change it later. + public @Nullable @NonConfidential String getMessage(@PolyConfidential @GuardSatisfied Throwable this) { return detailMessage; } diff --git a/src/java.base/share/classes/java/util/Map.java b/src/java.base/share/classes/java/util/Map.java index a4accc42e817e..63301c95805d6 100644 --- a/src/java.base/share/classes/java/util/Map.java +++ b/src/java.base/share/classes/java/util/Map.java @@ -25,6 +25,7 @@ package java.util; +import org.checkerframework.checker.confidential.qual.PolyConfidential; import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.lock.qual.ReleasesNoLocks; @@ -275,7 +276,7 @@ public interface Map { * (optional) */ @Pure - @Nullable V get(@GuardSatisfied Map this, @UnknownSignedness @GuardSatisfied Object key); + @Nullable V get(@GuardSatisfied @PolyConfidential Map this, @UnknownSignedness @GuardSatisfied Object key); // Modification Operations diff --git a/src/java.base/share/classes/java/util/Optional.java b/src/java.base/share/classes/java/util/Optional.java index 5ec98f55bcf03..381b0274e9bf0 100644 --- a/src/java.base/share/classes/java/util/Optional.java +++ b/src/java.base/share/classes/java/util/Optional.java @@ -33,6 +33,7 @@ import org.checkerframework.checker.optional.qual.OptionalCreator; import org.checkerframework.checker.optional.qual.OptionalEliminator; import org.checkerframework.checker.optional.qual.OptionalPropagator; +import org.checkerframework.checker.confidential.qual.UnknownConfidential; import org.checkerframework.checker.optional.qual.Present; import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.SideEffectFree; @@ -85,10 +86,10 @@ "meaning, but are unrelated by the Java type hierarchy.", "@Covariant makes Optional<@NonNull String> a subtype of Optional<@Nullable String>." }) -@AnnotatedFor({"lock", "nullness", "optional"}) +@AnnotatedFor({"lock", "nullness", "optional", "confidential"}) @Covariant(0) @jdk.internal.ValueBased -public final @NonNull class Optional { +public final @NonNull class Optional<@UnknownConfidential T> { /** * Common instance for {@code empty()}. */ diff --git a/src/java.base/share/classes/java/util/stream/Stream.java b/src/java.base/share/classes/java/util/stream/Stream.java index c63fcc78295bf..5c1623ed3bd1f 100644 --- a/src/java.base/share/classes/java/util/stream/Stream.java +++ b/src/java.base/share/classes/java/util/stream/Stream.java @@ -24,6 +24,7 @@ */ package java.util.stream; +import org.checkerframework.checker.confidential.qual.PolyConfidential; import org.checkerframework.checker.lock.qual.GuardSatisfied; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmpty; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; @@ -172,7 +173,7 @@ * @see DoubleStream * @see java.util.stream */ -@AnnotatedFor({"lock", "mustcall", "nullness"}) +@AnnotatedFor({"lock", "mustcall", "nullness", "confidential"}) @CFComment({"MustCall: most Streams do not need to be closed. There is no need for", "`@InheritableMustCall({})` because `AutoCloseable` already has that class annotation."}) public interface Stream extends BaseStream> { @@ -1182,7 +1183,7 @@ R collect(Supplier supplier, */ @CFComment("@SideEffectFree: the collector should not have side effects") @SideEffectFree - R collect(Collector collector); + R collect(@PolyConfidential Collector collector); /** * Accumulates the elements of this stream into a {@code List}. The elements in diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index 67bd3901e5727..49dec9ad421e8 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -79,6 +79,7 @@ exports org.checkerframework.checker.builder.qual; exports org.checkerframework.checker.calledmethods.qual; exports org.checkerframework.checker.compilermsgs.qual; + exports org.checkerframework.checker.confidential.qual; exports org.checkerframework.checker.fenum.qual; exports org.checkerframework.checker.formatter.qual; exports org.checkerframework.checker.guieffect.qual; diff --git a/src/java.base/share/classes/org/checkerframework/checker/confidential/qual/BottomConfidential.java b/src/java.base/share/classes/org/checkerframework/checker/confidential/qual/BottomConfidential.java new file mode 100644 index 0000000000000..79968aa803acd --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/confidential/qual/BottomConfidential.java @@ -0,0 +1,27 @@ +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.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; + +/** + * 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}) +@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/src/java.base/share/classes/org/checkerframework/checker/confidential/qual/Confidential.java b/src/java.base/share/classes/org/checkerframework/checker/confidential/qual/Confidential.java new file mode 100644 index 0000000000000..d9b0f6a66007c --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/confidential/qual/Confidential.java @@ -0,0 +1,25 @@ +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.SubtypeOf; + +/** + * 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 + * @checker_framework.manual #confidential-checker Confidential Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(UnknownConfidential.class) +public @interface Confidential {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/confidential/qual/NonConfidential.java b/src/java.base/share/classes/org/checkerframework/checker/confidential/qual/NonConfidential.java new file mode 100644 index 0000000000000..76f9997cc96a5 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/confidential/qual/NonConfidential.java @@ -0,0 +1,29 @@ +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.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 + * users. NonConfidential locations will never contain sensitive, private, or otherwise + * privileged-access information. + * + * @checker_framework.manual #confidential-checker Confidential Checker + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@SubtypeOf(UnknownConfidential.class) +@QualifierForLiterals({LiteralKind.STRING, LiteralKind.PRIMITIVE}) +@DefaultQualifierInHierarchy +@DefaultFor(value = {TypeUseLocation.LOCAL_VARIABLE, TypeUseLocation.UPPER_BOUND}) +public @interface NonConfidential {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/confidential/qual/PolyConfidential.java b/src/java.base/share/classes/org/checkerframework/checker/confidential/qual/PolyConfidential.java new file mode 100644 index 0000000000000..e0bc07155f3a3 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/confidential/qual/PolyConfidential.java @@ -0,0 +1,20 @@ +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.PolymorphicQualifier; + +/** + * A polymorphic qualifier for the Confidential type system. + * + * @checker_framework.manual #confidential-checker Confidential Checker + * @checker_framework.manual #qualifier-polymorphism Qualifier polymorphism + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@PolymorphicQualifier(UnknownConfidential.class) +public @interface PolyConfidential {} diff --git a/src/java.base/share/classes/org/checkerframework/checker/confidential/qual/UnknownConfidential.java b/src/java.base/share/classes/org/checkerframework/checker/confidential/qual/UnknownConfidential.java new file mode 100644 index 0000000000000..6bf37fd46fda2 --- /dev/null +++ b/src/java.base/share/classes/org/checkerframework/checker/confidential/qual/UnknownConfidential.java @@ -0,0 +1,24 @@ +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.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({}) +public @interface UnknownConfidential {} diff --git a/src/java.logging/share/classes/java/util/logging/Formatter.java b/src/java.logging/share/classes/java/util/logging/Formatter.java index 50410d340c801..233f11456e1d4 100644 --- a/src/java.logging/share/classes/java/util/logging/Formatter.java +++ b/src/java.logging/share/classes/java/util/logging/Formatter.java @@ -26,6 +26,7 @@ package java.util.logging; +import org.checkerframework.checker.confidential.qual.NonConfidential; import org.checkerframework.checker.interning.qual.UsesObjectEquals; import org.checkerframework.framework.qual.AnnotatedFor; @@ -43,7 +44,7 @@ * @since 1.4 */ -@AnnotatedFor({"interning"}) +@AnnotatedFor({"interning", "confidential"}) public abstract @UsesObjectEquals class Formatter { /** @@ -63,7 +64,7 @@ protected Formatter() { * @param record the log record to be formatted. * @return the formatted log record */ - public abstract String format(LogRecord record); + public abstract String format(@NonConfidential LogRecord record); /** diff --git a/src/java.logging/share/classes/java/util/logging/Handler.java b/src/java.logging/share/classes/java/util/logging/Handler.java index 6a5672b7eb202..90824b35506af 100644 --- a/src/java.logging/share/classes/java/util/logging/Handler.java +++ b/src/java.logging/share/classes/java/util/logging/Handler.java @@ -26,6 +26,7 @@ package java.util.logging; +import org.checkerframework.checker.confidential.qual.NonConfidential; import org.checkerframework.checker.interning.qual.UsesObjectEquals; import org.checkerframework.framework.qual.AnnotatedFor; @@ -52,7 +53,7 @@ * @since 1.4 */ -@AnnotatedFor({"interning"}) +@AnnotatedFor({"interning", "confidential"}) public abstract @UsesObjectEquals class Handler { private static final int offValue = Level.OFF.intValue(); private final LogManager manager = LogManager.getLogManager(); @@ -138,7 +139,7 @@ public Void run() { * @param record description of the log event. A null record is * silently ignored and is not published */ - public abstract void publish(LogRecord record); + public abstract void publish(@NonConfidential LogRecord record); /** * Flush any buffered output. diff --git a/src/java.logging/share/classes/java/util/logging/Logger.java b/src/java.logging/share/classes/java/util/logging/Logger.java index b8d9e92b33a5c..2393cb96035bd 100644 --- a/src/java.logging/share/classes/java/util/logging/Logger.java +++ b/src/java.logging/share/classes/java/util/logging/Logger.java @@ -25,6 +25,7 @@ package java.util.logging; +import org.checkerframework.checker.confidential.qual.NonConfidential; import org.checkerframework.checker.interning.qual.Interned; import org.checkerframework.checker.interning.qual.UsesObjectEquals; import org.checkerframework.checker.lock.qual.GuardSatisfied; @@ -34,6 +35,7 @@ import org.checkerframework.dataflow.qual.SideEffectFree; import org.checkerframework.framework.qual.AnnotatedFor; import org.checkerframework.framework.qual.CFComment; +import org.checkerframework.checker.confidential.qual.NonConfidential; import java.lang.ref.WeakReference; import java.security.AccessController; @@ -234,7 +236,7 @@ "public boolean containsAll(@GuardSatisfied LinkedList this, Collection c);", "public int hashCode(@GuardSatisfied LinkedList this);", "public boolean equals(@GuardSatisfied LinkedList this, Object o);"}) -@AnnotatedFor({"index", "interning", "lock", "signature"}) +@AnnotatedFor({"index", "interning", "lock", "signature", "confidential"}) public @UsesObjectEquals class Logger { private static final Handler emptyHandlers[] = new Handler[0]; private static final int offValue = Level.OFF.intValue(); @@ -983,7 +985,7 @@ public void setFilter(@GuardSatisfied Logger this, @Nullable Filter newFilter) t * @param record the LogRecord to be published */ @SideEffectFree - public void log(@GuardSatisfied Logger this, LogRecord record) { + public void log(@GuardSatisfied Logger this, @NonConfidential LogRecord record) { if (!isLoggable(record.getLevel())) { return; } @@ -1049,7 +1051,7 @@ private void doLog(@GuardSatisfied Logger this, LogRecord lr) { * @param msg The string message (or a key in the message catalog) */ @SideEffectFree - public void log(@GuardSatisfied Logger this, @GuardSatisfied Level level, @Nullable String msg) { + public void log(@GuardSatisfied Logger this, @GuardSatisfied Level level, @NonConfidential @Nullable String msg) { if (!isLoggable(level)) { return; } @@ -1072,7 +1074,7 @@ public void log(@GuardSatisfied Logger this, @GuardSatisfied Level level, @Nulla * @since 1.8 */ @SideEffectFree - public void log(@GuardSatisfied Logger this, @GuardSatisfied Level level, @GuardSatisfied Supplier msgSupplier) { + public void log(@GuardSatisfied Logger this, @GuardSatisfied Level level, @NonConfidential @GuardSatisfied Supplier msgSupplier) { if (!isLoggable(level)) { return; } @@ -1092,7 +1094,7 @@ public void log(@GuardSatisfied Logger this, @GuardSatisfied Level level, @Guard * @param param1 parameter to the message */ @SideEffectFree - public void log(@GuardSatisfied Logger this, @GuardSatisfied Level level, @Nullable String msg, @GuardSatisfied @Nullable Object param1) { + public void log(@GuardSatisfied Logger this, @GuardSatisfied Level level, @NonConfidential @Nullable String msg, @NonConfidential @GuardSatisfied @Nullable Object param1) { if (!isLoggable(level)) { return; } @@ -1114,7 +1116,7 @@ public void log(@GuardSatisfied Logger this, @GuardSatisfied Level level, @Nulla * @param params array of parameters to the message */ @SideEffectFree - public void log(@GuardSatisfied Logger this, @GuardSatisfied Level level, @Nullable String msg, @Nullable Object params @GuardSatisfied @Nullable []) { + public void log(@GuardSatisfied Logger this, @GuardSatisfied Level level, @NonConfidential @Nullable String msg, @NonConfidential @Nullable Object params @GuardSatisfied @Nullable []) { if (!isLoggable(level)) { return; } @@ -1140,7 +1142,7 @@ public void log(@GuardSatisfied Logger this, @GuardSatisfied Level level, @Nulla * @param thrown Throwable associated with log message. */ @SideEffectFree - public void log(@GuardSatisfied Logger this, @GuardSatisfied Level level, @Nullable String msg, @GuardSatisfied @Nullable Throwable thrown) { + public void log(@GuardSatisfied Logger this, @GuardSatisfied Level level, @NonConfidential @Nullable String msg, @NonConfidential @GuardSatisfied @Nullable Throwable thrown) { if (!isLoggable(level)) { return; } @@ -1169,7 +1171,7 @@ public void log(@GuardSatisfied Logger this, @GuardSatisfied Level level, @Nulla * @since 1.8 */ @SideEffectFree - public void log(@GuardSatisfied Logger this, @GuardSatisfied Level level, @GuardSatisfied @Nullable Throwable thrown, @GuardSatisfied Supplier msgSupplier) { + public void log(@GuardSatisfied Logger this, @GuardSatisfied Level level, @NonConfidential @GuardSatisfied @Nullable Throwable thrown, @NonConfidential @GuardSatisfied Supplier msgSupplier) { if (!isLoggable(level)) { return; } @@ -1196,7 +1198,7 @@ public void log(@GuardSatisfied Logger this, @GuardSatisfied Level level, @Guard * @param msg The string message (or a key in the message catalog) */ @SideEffectFree - public void logp(@GuardSatisfied Logger this, @GuardSatisfied Level level, @Nullable String sourceClass, @Nullable String sourceMethod, @Nullable String msg) { + public void logp(@GuardSatisfied Logger this, @GuardSatisfied Level level, @NonConfidential @Nullable String sourceClass, @NonConfidential @Nullable String sourceMethod, @NonConfidential @Nullable String msg) { if (!isLoggable(level)) { return; } @@ -1223,8 +1225,8 @@ public void logp(@GuardSatisfied Logger this, @GuardSatisfied Level level, @Null * @since 1.8 */ @SideEffectFree - public void logp(@GuardSatisfied Logger this, Level level, @Nullable String sourceClass, @Nullable String sourceMethod, - Supplier msgSupplier) { + public void logp(@GuardSatisfied Logger this, Level level, @NonConfidential @Nullable String sourceClass, @NonConfidential @Nullable String sourceMethod, + @NonConfidential Supplier msgSupplier) { if (!isLoggable(level)) { return; } @@ -1249,8 +1251,8 @@ public void logp(@GuardSatisfied Logger this, Level level, @Nullable String sour * @param param1 Parameter to the log message. */ @SideEffectFree - public void logp(@GuardSatisfied Logger this, Level level, @Nullable String sourceClass, @Nullable String sourceMethod, - @Nullable String msg, @Nullable Object param1) { + public void logp(@GuardSatisfied Logger this, Level level, @NonConfidential @Nullable String sourceClass, @NonConfidential @Nullable String sourceMethod, + @NonConfidential @Nullable String msg, @NonConfidential @Nullable Object param1) { if (!isLoggable(level)) { return; } @@ -1277,8 +1279,8 @@ public void logp(@GuardSatisfied Logger this, Level level, @Nullable String sour * @param params Array of parameters to the message */ @SideEffectFree - public void logp(@GuardSatisfied Logger this, Level level, @Nullable String sourceClass, @Nullable String sourceMethod, - @Nullable String msg, @Nullable Object params @Nullable []) { + public void logp(@GuardSatisfied Logger this, Level level, @NonConfidential @Nullable String sourceClass, @NonConfidential @Nullable String sourceMethod, + @NonConfidential @Nullable String msg, @NonConfidential @Nullable Object params @Nullable []) { if (!isLoggable(level)) { return; } @@ -1309,8 +1311,8 @@ public void logp(@GuardSatisfied Logger this, Level level, @Nullable String sour * @param thrown Throwable associated with log message. */ @SideEffectFree - public void logp(@GuardSatisfied Logger this, Level level, @Nullable String sourceClass, @Nullable String sourceMethod, - @Nullable String msg, @Nullable Throwable thrown) { + public void logp(@GuardSatisfied Logger this, Level level, @NonConfidential @Nullable String sourceClass, @NonConfidential @Nullable String sourceMethod, + @NonConfidential @Nullable String msg, @NonConfidential @Nullable Throwable thrown) { if (!isLoggable(level)) { return; } @@ -1344,8 +1346,8 @@ public void logp(@GuardSatisfied Logger this, Level level, @Nullable String sour * @since 1.8 */ @SideEffectFree - public void logp(@GuardSatisfied Logger this, Level level, @Nullable String sourceClass, @Nullable String sourceMethod, - @Nullable Throwable thrown, Supplier msgSupplier) { + public void logp(@GuardSatisfied Logger this, Level level, @NonConfidential @Nullable String sourceClass, @NonConfidential @Nullable String sourceMethod, + @NonConfidential @Nullable Throwable thrown, @NonConfidential Supplier msgSupplier) { if (!isLoggable(level)) { return; } @@ -1515,8 +1517,8 @@ public void logrb(@GuardSatisfied Logger this, Level level, @Nullable String sou * @param params Parameters to the message (optional, may be none). * @since 1.8 */ - public void logrb(Level level, String sourceClass, String sourceMethod, - ResourceBundle bundle, String msg, Object... params) { + public void logrb(Level level, @NonConfidential String sourceClass, @NonConfidential String sourceMethod, + ResourceBundle bundle, @NonConfidential String msg, @NonConfidential Object... params) { if (!isLoggable(level)) { return; } @@ -1548,7 +1550,7 @@ public void logrb(Level level, String sourceClass, String sourceMethod, * @param params Parameters to the message (optional, may be none). * @since 9 */ - public void logrb(Level level, ResourceBundle bundle, String msg, Object... params) { + public void logrb(Level level, ResourceBundle bundle, @NonConfidential String msg, @NonConfidential Object... params) { if (!isLoggable(level)) { return; } @@ -1628,8 +1630,8 @@ public void logrb(@GuardSatisfied Logger this, Level level, @Nullable String sou * @param thrown Throwable associated with the log message. * @since 1.8 */ - public void logrb(Level level, String sourceClass, String sourceMethod, - ResourceBundle bundle, String msg, Throwable thrown) { + public void logrb(Level level, @NonConfidential String sourceClass, @NonConfidential String sourceMethod, + ResourceBundle bundle, @NonConfidential String msg, @NonConfidential Throwable thrown) { if (!isLoggable(level)) { return; } @@ -1666,8 +1668,8 @@ public void logrb(Level level, String sourceClass, String sourceMethod, * @param thrown Throwable associated with the log message. * @since 9 */ - public void logrb(Level level, ResourceBundle bundle, String msg, - Throwable thrown) { + public void logrb(Level level, ResourceBundle bundle, @NonConfidential String msg, + @NonConfidential Throwable thrown) { if (!isLoggable(level)) { return; } @@ -1823,7 +1825,7 @@ public void throwing(@GuardSatisfied Logger this, @Nullable String sourceClass, * @param msg The string message (or a key in the message catalog) */ @SideEffectFree - public void severe(@GuardSatisfied Logger this, @Nullable String msg) { + public void severe(@GuardSatisfied Logger this, @NonConfidential @Nullable String msg) { log(Level.SEVERE, msg); } @@ -1837,7 +1839,7 @@ public void severe(@GuardSatisfied Logger this, @Nullable String msg) { * @param msg The string message (or a key in the message catalog) */ @SideEffectFree - public void warning(@GuardSatisfied Logger this, @Nullable String msg) { + public void warning(@GuardSatisfied Logger this, @NonConfidential @Nullable String msg) { log(Level.WARNING, msg); } @@ -1851,7 +1853,7 @@ public void warning(@GuardSatisfied Logger this, @Nullable String msg) { * @param msg The string message (or a key in the message catalog) */ @SideEffectFree - public void info(@GuardSatisfied Logger this, @Nullable String msg) { + public void info(@GuardSatisfied Logger this, @NonConfidential @Nullable String msg) { log(Level.INFO, msg); } @@ -1865,7 +1867,7 @@ public void info(@GuardSatisfied Logger this, @Nullable String msg) { * @param msg The string message (or a key in the message catalog) */ @SideEffectFree - public void config(@GuardSatisfied Logger this, @Nullable String msg) { + public void config(@GuardSatisfied Logger this, @NonConfidential @Nullable String msg) { log(Level.CONFIG, msg); } @@ -1879,7 +1881,7 @@ public void config(@GuardSatisfied Logger this, @Nullable String msg) { * @param msg The string message (or a key in the message catalog) */ @SideEffectFree - public void fine(@GuardSatisfied Logger this, @Nullable String msg) { + public void fine(@GuardSatisfied Logger this, @NonConfidential @Nullable String msg) { log(Level.FINE, msg); } @@ -1893,7 +1895,7 @@ public void fine(@GuardSatisfied Logger this, @Nullable String msg) { * @param msg The string message (or a key in the message catalog) */ @SideEffectFree - public void finer(@GuardSatisfied Logger this, @Nullable String msg) { + public void finer(@GuardSatisfied Logger this, @NonConfidential @Nullable String msg) { log(Level.FINER, msg); } @@ -1907,7 +1909,7 @@ public void finer(@GuardSatisfied Logger this, @Nullable String msg) { * @param msg The string message (or a key in the message catalog) */ @SideEffectFree - public void finest(@GuardSatisfied Logger this, @Nullable String msg) { + public void finest(@GuardSatisfied Logger this, @NonConfidential @Nullable String msg) { log(Level.FINEST, msg); } @@ -1930,7 +1932,7 @@ public void finest(@GuardSatisfied Logger this, @Nullable String msg) { * @since 1.8 */ @SideEffectFree - public void severe(@GuardSatisfied Logger this, Supplier msgSupplier) { + public void severe(@GuardSatisfied Logger this, @NonConfidential Supplier msgSupplier) { log(Level.SEVERE, msgSupplier); } @@ -1948,7 +1950,7 @@ public void severe(@GuardSatisfied Logger this, Supplier msgSupplier) { * @since 1.8 */ @SideEffectFree - public void warning(@GuardSatisfied Logger this, Supplier msgSupplier) { + public void warning(@GuardSatisfied Logger this, @NonConfidential Supplier msgSupplier) { log(Level.WARNING, msgSupplier); } @@ -1966,7 +1968,7 @@ public void warning(@GuardSatisfied Logger this, Supplier msgSupplier) { * @since 1.8 */ @SideEffectFree - public void info(@GuardSatisfied Logger this, Supplier msgSupplier) { + public void info(@GuardSatisfied Logger this, @NonConfidential Supplier msgSupplier) { log(Level.INFO, msgSupplier); } @@ -1984,7 +1986,7 @@ public void info(@GuardSatisfied Logger this, Supplier msgSupplier) { * @since 1.8 */ @SideEffectFree - public void config(@GuardSatisfied Logger this, Supplier msgSupplier) { + public void config(@GuardSatisfied Logger this, @NonConfidential Supplier msgSupplier) { log(Level.CONFIG, msgSupplier); } @@ -2002,7 +2004,7 @@ public void config(@GuardSatisfied Logger this, Supplier msgSupplier) { * @since 1.8 */ @SideEffectFree - public void fine(@GuardSatisfied Logger this, Supplier msgSupplier) { + public void fine(@GuardSatisfied Logger this, @NonConfidential Supplier msgSupplier) { log(Level.FINE, msgSupplier); } @@ -2020,7 +2022,7 @@ public void fine(@GuardSatisfied Logger this, Supplier msgSupplier) { * @since 1.8 */ @SideEffectFree - public void finer(@GuardSatisfied Logger this, Supplier msgSupplier) { + public void finer(@GuardSatisfied Logger this, @NonConfidential Supplier msgSupplier) { log(Level.FINER, msgSupplier); } @@ -2038,7 +2040,7 @@ public void finer(@GuardSatisfied Logger this, Supplier msgSupplier) { * @since 1.8 */ @SideEffectFree - public void finest(@GuardSatisfied Logger this, Supplier msgSupplier) { + public void finest(@GuardSatisfied Logger this, @NonConfidential Supplier msgSupplier) { log(Level.FINEST, msgSupplier); }