diff --git a/src/java.base/share/classes/java/io/PrintStream.java b/src/java.base/share/classes/java/io/PrintStream.java index f60a2fa43790f..c03817d21d8c8 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; @@ -78,7 +79,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 { @@ -923,7 +924,7 @@ public void print(@GuardSatisfied PrintStream this, boolean b) { * @param c The {@code char} to be printed * @see Charset#defaultCharset() */ - public void print(@GuardSatisfied PrintStream this, char c) { + public void print(@GuardSatisfied PrintStream this, @NonConfidential char c) { write(String.valueOf(c)); } @@ -938,7 +939,7 @@ public void print(@GuardSatisfied PrintStream this, char c) { * @see java.lang.Integer#toString(int) * @see Charset#defaultCharset() */ - public void print(@GuardSatisfied PrintStream this, int i) { + public void print(@GuardSatisfied PrintStream this, @NonConfidential int i) { write(String.valueOf(i)); } @@ -953,7 +954,7 @@ public void print(@GuardSatisfied PrintStream this, int i) { * @see java.lang.Long#toString(long) * @see Charset#defaultCharset() */ - public void print(@GuardSatisfied PrintStream this, long l) { + public void print(@GuardSatisfied PrintStream this, @NonConfidential long l) { write(String.valueOf(l)); } @@ -968,7 +969,7 @@ public void print(@GuardSatisfied PrintStream this, long l) { * @see java.lang.Float#toString(float) * @see Charset#defaultCharset() */ - public void print(@GuardSatisfied PrintStream this, float f) { + public void print(@GuardSatisfied PrintStream this, @NonConfidential float f) { write(String.valueOf(f)); } @@ -983,7 +984,7 @@ public void print(@GuardSatisfied PrintStream this, float f) { * @see java.lang.Double#toString(double) * @see Charset#defaultCharset() */ - public void print(@GuardSatisfied PrintStream this, double d) { + public void print(@GuardSatisfied PrintStream this, @NonConfidential double d) { write(String.valueOf(d)); } @@ -998,7 +999,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); } @@ -1013,7 +1014,7 @@ public void print(@GuardSatisfied PrintStream this, @PolySigned char[] s) { * @param s The {@code String} to be printed * @see Charset#defaultCharset() */ - public void print(@GuardSatisfied PrintStream this, @Nullable String s) { + public void print(@GuardSatisfied PrintStream this, @NonConfidential @Nullable String s) { write(String.valueOf(s)); } @@ -1028,7 +1029,7 @@ public void print(@GuardSatisfied PrintStream this, @Nullable String s) { * @see java.lang.Object#toString() * @see Charset#defaultCharset() */ - public void print(@GuardSatisfied PrintStream this, @Nullable Object obj) { + public void print(@GuardSatisfied PrintStream this, @NonConfidential @Nullable Object obj) { write(String.valueOf(obj)); } @@ -1070,7 +1071,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 { @@ -1088,7 +1089,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 { @@ -1106,7 +1107,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 { @@ -1124,7 +1125,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 { @@ -1142,7 +1143,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 { @@ -1160,7 +1161,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 { @@ -1178,7 +1179,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 { @@ -1198,7 +1199,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 @@ -1258,7 +1259,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); } @@ -1311,7 +1312,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 71c06491648c2..1c9ac5192d67d 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; @@ -54,7 +55,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 { @@ -187,7 +188,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); } @@ -285,7 +286,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 0a6d2f8f404aa..6c4d741d6b449 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; @@ -174,7 +175,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 { @@ -1948,7 +1949,7 @@ public void getBytes(@IndexOrHigh({"this"}) int srcBegin, @IndexOrHigh({"this"}) @Pure @EnsuresNonNullIf(expression={"#1"}, result=true) @StaticallyExecutable - public boolean equals(@GuardSatisfied @Nullable Object anObject) { + public boolean equals(@PolyConfidential String this, @GuardSatisfied @Nullable @PolyConfidential Object anObject) { if (this == anObject) { return true; } @@ -4582,7 +4583,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 94b262351c64f..63862f8e1007b 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; @@ -121,7 +123,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 @@ -395,7 +397,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 a4894dfa10a19..dee896b068d12 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; @@ -272,7 +273,7 @@ public interface Map { * does not permit null keys ({@linkplain Collection##optional-restrictions 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 38063491bf235..6d3e75a4ef162 100644 --- a/src/java.base/share/classes/java/util/Optional.java +++ b/src/java.base/share/classes/java/util/Optional.java @@ -24,6 +24,7 @@ */ package java.util; +import org.checkerframework.checker.confidential.qual.UnknownConfidential; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -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 { /** * 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 4e592f283465f..43bd3fc615db6 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> { @@ -1181,7 +1182,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 5a4f09b96283a..f853653edab64 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 59be7beaf11b8..a99d10014b07c 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; @@ -53,7 +54,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(); @@ -161,7 +162,7 @@ void unlock() { * @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 17fe22c131038..955f6073244c5 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; @@ -235,7 +237,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(); @@ -986,7 +988,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; } @@ -1052,7 +1054,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; } @@ -1075,7 +1077,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; } @@ -1095,7 +1097,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; } @@ -1117,7 +1119,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; } @@ -1143,7 +1145,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; } @@ -1172,7 +1174,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; } @@ -1199,7 +1201,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; } @@ -1226,8 +1228,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; } @@ -1252,8 +1254,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; } @@ -1280,8 +1282,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; } @@ -1312,8 +1314,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; } @@ -1347,8 +1349,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; } @@ -1518,8 +1520,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; } @@ -1551,7 +1553,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; } @@ -1631,8 +1633,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; } @@ -1669,8 +1671,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; } @@ -1826,7 +1828,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); } @@ -1840,7 +1842,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); } @@ -1854,7 +1856,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); } @@ -1868,7 +1870,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); } @@ -1882,7 +1884,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); } @@ -1896,7 +1898,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); } @@ -1910,7 +1912,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); } @@ -1933,7 +1935,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); } @@ -1951,7 +1953,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); } @@ -1969,7 +1971,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); } @@ -1987,7 +1989,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); } @@ -2005,7 +2007,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); } @@ -2023,7 +2025,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); } @@ -2041,7 +2043,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); }