From 8b053f90ba495462cc2db562ac1c3066a0637c8f Mon Sep 17 00:00:00 2001 From: Carter Kozak Date: Mon, 11 Apr 2022 05:35:29 -0700 Subject: [PATCH] Support safety annotations on type-use e.g. `Collection<@Safe String>` (#2187) Support safety annotations on type-use e.g. `Collection<@Safe String>` --- .../IllegalSafeLoggingArgument.java | 33 ++++- .../errorprone/safety/SafetyAnnotations.java | 131 ++++++++++++++++-- .../safety/SafetyPropagationTransfer.java | 29 ++-- .../IllegalSafeLoggingArgumentTest.java | 127 +++++++++++++++++ changelog/@unreleased/pr-2187.v2.yml | 5 + versions.lock | 12 +- versions.props | 2 +- 7 files changed, 298 insertions(+), 41 deletions(-) create mode 100644 changelog/@unreleased/pr-2187.v2.yml diff --git a/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/IllegalSafeLoggingArgument.java b/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/IllegalSafeLoggingArgument.java index 3a432ad42..0ba122aa6 100644 --- a/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/IllegalSafeLoggingArgument.java +++ b/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/IllegalSafeLoggingArgument.java @@ -40,8 +40,12 @@ import com.sun.source.tree.VariableTree; import com.sun.source.util.TreePath; import com.sun.tools.javac.code.Symbol.MethodSymbol; +import com.sun.tools.javac.code.Symbol.TypeVariableSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; +import com.sun.tools.javac.code.Type; +import com.sun.tools.javac.code.Type.TypeVar; import java.util.List; +import java.util.Objects; /** * Ensures that safe-logging annotated elements are handled correctly by annotated method parameters. @@ -72,6 +76,28 @@ public final class IllegalSafeLoggingArgument extends BugChecker .onClass("com.palantir.logsafe.SafeArg") .named("of"); + private static Type resolveParameterType(Type input, MethodInvocationTree tree, VisitorState state) { + if (input instanceof TypeVar) { + TypeVar typeVar = (TypeVar) input; + + Type receiver = ASTHelpers.getReceiverType(tree); + if (receiver == null) { + return input; + } + MethodSymbol methodSymbol = ASTHelpers.getSymbol(tree); + // List -> Collection gives us Collection + Type boundToMethodOwner = state.getTypes().asSuper(receiver, methodSymbol.owner); + List ownerTypeVars = methodSymbol.owner.getTypeParameters(); + for (int i = 0; i < ownerTypeVars.size(); i++) { + TypeVariableSymbol ownerVar = ownerTypeVars.get(i); + if (Objects.equals(ownerVar, typeVar.tsym)) { + return boundToMethodOwner.getTypeArguments().get(i); + } + } + } + return input; + } + @Override public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) { List arguments = tree.getArguments(); @@ -85,7 +111,10 @@ public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState List parameters = methodSymbol.getParameters(); for (int i = 0; i < parameters.size(); i++) { VarSymbol parameter = parameters.get(i); - Safety parameterSafety = SafetyAnnotations.getSafety(parameter, state); + Type resolvedParameterType = resolveParameterType(parameter.type, tree, state); + Safety parameterSafety = Safety.mergeAssumingUnknownIsSame( + SafetyAnnotations.getSafety(parameter, state), + SafetyAnnotations.getSafety(resolvedParameterType, state)); if (parameterSafety.allowsAll()) { // Fast path: all types are accepted, there's no reason to do further analysis. continue; @@ -164,7 +193,7 @@ public Description matchCompoundAssignment(CompoundAssignmentTree tree, VisitorS private Description handleAssignment( ExpressionTree assignmentTree, ExpressionTree variable, ExpressionTree expression, VisitorState state) { - Safety variableDeclaredSafety = SafetyAnnotations.getSafety(ASTHelpers.getSymbol(variable), state); + Safety variableDeclaredSafety = SafetyAnnotations.getSafety(variable, state); if (variableDeclaredSafety.allowsAll()) { return Description.NO_MATCH; } diff --git a/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/safety/SafetyAnnotations.java b/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/safety/SafetyAnnotations.java index 014cbda50..ec71e46fa 100644 --- a/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/safety/SafetyAnnotations.java +++ b/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/safety/SafetyAnnotations.java @@ -16,31 +16,56 @@ package com.palantir.baseline.errorprone.safety; +import com.google.common.collect.Multimap; import com.google.errorprone.VisitorState; +import com.google.errorprone.suppliers.Suppliers; import com.google.errorprone.util.ASTHelpers; import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.Tree; +import com.sun.tools.javac.code.Attribute; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.util.List; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Stream; import javax.annotation.Nullable; +import javax.lang.model.element.Name; +import javax.lang.model.element.TypeElement; public final class SafetyAnnotations { private static final String SAFE = "com.palantir.logsafe.Safe"; private static final String UNSAFE = "com.palantir.logsafe.Unsafe"; private static final String DO_NOT_LOG = "com.palantir.logsafe.DoNotLog"; - public static Safety getSafety(ExpressionTree input, VisitorState state) { - // Check the result type - ExpressionTree tree = ASTHelpers.stripParentheses(input); - Safety resultTypeSafet = getResultTypeSafety(tree, state); + private static final TypeArgumentHandlers SAFETY_IS_COMBINATION_OF_TYPE_ARGUMENTS = new TypeArgumentHandlers( + new TypeArgumentHandler(Iterable.class), + new TypeArgumentHandler(Iterator.class), + new TypeArgumentHandler(Map.class), + new TypeArgumentHandler(Map.Entry.class), + new TypeArgumentHandler(Multimap.class), + new TypeArgumentHandler(Stream.class), + new TypeArgumentHandler(Optional.class)); - // Check the argument symbol itself: - Symbol argumentSymbol = ASTHelpers.getSymbol(tree); - Safety symbolSafety = argumentSymbol != null ? getSafety(argumentSymbol, state) : Safety.UNKNOWN; - return Safety.mergeAssumingUnknownIsSame(resultTypeSafet, symbolSafety); + public static Safety getSafety(Tree tree, VisitorState state) { + // Check the symbol itself: + Symbol treeSymbol = ASTHelpers.getSymbol(tree); + Safety symbolSafety = getSafety(treeSymbol, state); + Type type = tree instanceof ExpressionTree + ? ASTHelpers.getResultType((ExpressionTree) tree) + : ASTHelpers.getType(tree); + + if (type == null) { + return symbolSafety; + } else { + return Safety.mergeAssumingUnknownIsSame(symbolSafety, getSafety(type, state), getSafety(type.tsym, state)); + } } public static Safety getSafety(@Nullable Symbol symbol, VisitorState state) { @@ -66,6 +91,91 @@ public static Safety getSafety(@Nullable Symbol symbol, VisitorState state) { return Safety.UNKNOWN; } + public static Safety getSafety(@Nullable Type type, VisitorState state) { + if (type != null) { + return getSafetyInternal(type, state, null); + } + return Safety.UNKNOWN; + } + + private static Safety getSafetyInternal(Type type, VisitorState state, Set dejaVu) { + List typeAnnotations = type.getAnnotationMirrors(); + for (Attribute.TypeCompound annotation : typeAnnotations) { + TypeElement annotationElement = + (TypeElement) annotation.getAnnotationType().asElement(); + Name name = annotationElement.getQualifiedName(); + if (name.contentEquals(DO_NOT_LOG)) { + return Safety.DO_NOT_LOG; + } + if (name.contentEquals(UNSAFE)) { + return Safety.UNSAFE; + } + if (name.contentEquals(SAFE)) { + return Safety.SAFE; + } + } + return SAFETY_IS_COMBINATION_OF_TYPE_ARGUMENTS.getSafety(type, state, dejaVu); + } + + private static final class TypeArgumentHandlers { + private final TypeArgumentHandler[] handlers; + + TypeArgumentHandlers(TypeArgumentHandler... handlers) { + this.handlers = handlers; + } + + Safety getSafety(Type type, VisitorState state, @Nullable Set dejaVu) { + for (TypeArgumentHandler handler : handlers) { + Safety result = handler.getSafety(type, state, dejaVu); + if (result != null) { + return result; + } + } + return Safety.UNKNOWN; + } + } + + private static final class TypeArgumentHandler { + private final com.google.errorprone.suppliers.Supplier typeSupplier; + + TypeArgumentHandler(Class clazz) { + if (clazz.getTypeParameters().length == 0) { + throw new IllegalStateException("Class " + clazz + " has no type parameters"); + } + this.typeSupplier = Suppliers.typeFromClass(clazz); + } + + @Nullable + Safety getSafety(Type type, VisitorState state, @Nullable Set dejaVu) { + Type baseType = typeSupplier.get(state); + if (ASTHelpers.isSubtype(type, baseType, state)) { + // ensure we're matching the expected type arguments + Set deJaVuToPass = dejaVu == null ? new HashSet<>() : dejaVu; + // Use the string value for cycle detection, the type itself is not guaranteed + // to declare hash/equals. + String typeString = type.toString(); + if (!deJaVuToPass.add(typeString)) { + return Safety.UNKNOWN; + } + // Apply the input type arguments to the base type + Type asSubtype = state.getTypes().asSuper(type, baseType.tsym); + Safety safety = Safety.SAFE; + List typeArguments = asSubtype.getTypeArguments(); + for (Type typeArgument : typeArguments) { + Safety safetyBasedOnType = SafetyAnnotations.getSafetyInternal(typeArgument, state, deJaVuToPass); + Safety safetyBasedOnSymbol = SafetyAnnotations.getSafety(typeArgument.tsym, state); + Safety typeArgumentSafety = + Safety.mergeAssumingUnknownIsSame(safetyBasedOnType, safetyBasedOnSymbol); + safety = safety.leastUpperBound(typeArgumentSafety); + } + // remove the type on the way out, otherwise map would break. + deJaVuToPass.remove(typeString); + return safety; + } + return null; + } + } + private static Safety getSuperMethodSafety(MethodSymbol method, VisitorState state) { Safety safety = Safety.UNKNOWN; if (!method.isStaticOrInstanceInit()) { @@ -99,10 +209,5 @@ private static Safety getSuperMethodParameterSafety(VarSymbol varSymbol, Visitor return safety; } - public static Safety getResultTypeSafety(ExpressionTree expression, VisitorState state) { - Type resultType = ASTHelpers.getResultType(expression); - return resultType == null ? Safety.UNKNOWN : getSafety(resultType.tsym, state); - } - private SafetyAnnotations() {} } diff --git a/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/safety/SafetyPropagationTransfer.java b/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/safety/SafetyPropagationTransfer.java index 8fc81781e..15803d7c8 100644 --- a/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/safety/SafetyPropagationTransfer.java +++ b/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/safety/SafetyPropagationTransfer.java @@ -45,7 +45,6 @@ import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; -import com.sun.tools.javac.code.Type; import com.sun.tools.javac.processing.JavacProcessingEnvironment; import java.io.Closeable; import java.util.Arrays; @@ -291,7 +290,7 @@ public AccessPathStore initialStore(UnderlyingAST _underlyingAst, List result = AccessPathStore.empty().toBuilder(); for (LocalVariableNode param : parameters) { - Safety declared = SafetyAnnotations.getSafety((Symbol) param.getElement(), state); + Safety declared = SafetyAnnotations.getSafety(param.getTree(), state); result.setInformation(AccessPath.fromLocalVariable(param), declared); } return result.build(); @@ -668,9 +667,8 @@ public TransferResult> visitAssignment( AssignmentNode node, TransferInput> input) { ReadableUpdates updates = new ReadableUpdates(); Safety expressionSafety = getValueOfSubNode(input, node.getExpression()); - Safety targetSymbolSafety = SafetyAnnotations.getSafety( - ASTHelpers.getSymbol(node.getTarget().getTree()), state); - Safety safety = Safety.mergeAssumingUnknownIsSame(expressionSafety, targetSymbolSafety); + Safety targetSafety = SafetyAnnotations.getSafety(node.getTarget().getTree(), state); + Safety safety = Safety.mergeAssumingUnknownIsSame(expressionSafety, targetSafety); Node target = node.getTarget(); if (target instanceof LocalVariableNode) { updates.trySet(target, safety); @@ -771,9 +769,8 @@ private static boolean hasNonNullConstantValue(LocalVariableNode node) { @Override public TransferResult> visitVariableDeclaration( VariableDeclarationNode node, TransferInput> input) { - Safety variableTypeSafety = - SafetyAnnotations.getSafety(ASTHelpers.getSymbol(node.getTree().getType()), state); - Safety variableSafety = SafetyAnnotations.getSafety(ASTHelpers.getSymbol(node.getTree()), state); + Safety variableTypeSafety = SafetyAnnotations.getSafety(node.getTree().getType(), state); + Safety variableSafety = SafetyAnnotations.getSafety(node.getTree(), state); Safety safety = Safety.mergeAssumingUnknownIsSame(variableTypeSafety, variableSafety); return noStoreChanges(safety, input); } @@ -781,13 +778,11 @@ public TransferResult> visitVariableDeclaration( @Override public TransferResult> visitFieldAccess( FieldAccessNode node, TransferInput> input) { - Safety fieldSafety = SafetyAnnotations.getSafety(ASTHelpers.getSymbol(node.getTree()), state); - Type fieldType = ASTHelpers.getType(node.getTree()); - Safety typeSafety = fieldType == null ? Safety.UNKNOWN : SafetyAnnotations.getSafety(fieldType.tsym, state); + Safety fieldSafety = SafetyAnnotations.getSafety(node.getTree(), state); VarSymbol symbol = (VarSymbol) ASTHelpers.getSymbol(node.getTree()); AccessPath maybeAccessPath = AccessPath.fromFieldAccess(node); Safety flowSafety = fieldSafety(symbol, maybeAccessPath, input.getRegularStore()); - Safety safety = Safety.mergeAssumingUnknownIsSame(fieldSafety, typeSafety, flowSafety); + Safety safety = Safety.mergeAssumingUnknownIsSame(fieldSafety, flowSafety); return noStoreChanges(safety, input); } @@ -950,9 +945,7 @@ public TransferResult> visitTypeCast( private TransferResult> handleTypeConversion( Tree newType, Node original, TransferInput> input) { Safety valueSafety = getValueOfSubNode(input, original); - Type targetType = ASTHelpers.getType(newType); - Safety narrowTargetSafety = - targetType == null ? Safety.UNKNOWN : SafetyAnnotations.getSafety(targetType.tsym, state); + Safety narrowTargetSafety = SafetyAnnotations.getSafety(newType, state); Safety resultSafety = Safety.mergeAssumingUnknownIsSame(valueSafety, narrowTargetSafety); return noStoreChanges(resultSafety, input); } @@ -1024,18 +1017,16 @@ private Safety getKnownMethodSafety( private Safety getMethodSymbolSafety( MethodInvocationNode node, TransferInput> input) { - Safety resultTypeSafety = SafetyAnnotations.getResultTypeSafety(node.getTree(), state); + Safety methodSafety = SafetyAnnotations.getSafety(node.getTree(), state); MethodSymbol methodSymbol = ASTHelpers.getSymbol(node.getTree()); if (methodSymbol != null) { - Safety methodSafety = Safety.mergeAssumingUnknownIsSame( - SafetyAnnotations.getSafety(methodSymbol, state), resultTypeSafety); // non-annotated toString inherits type-level safety. if (methodSafety == Safety.UNKNOWN && TO_STRING.matches(node.getTree(), state)) { return getValueOfSubNode(input, node.getTarget().getReceiver()); } return methodSafety; } - return resultTypeSafety; + return methodSafety; } @Override diff --git a/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/IllegalSafeLoggingArgumentTest.java b/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/IllegalSafeLoggingArgumentTest.java index 937477447..c4635c7cd 100644 --- a/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/IllegalSafeLoggingArgumentTest.java +++ b/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/IllegalSafeLoggingArgumentTest.java @@ -203,6 +203,133 @@ public void testSafeReturn() { .doTest(); } + @Test + public void testUnsafeTypeParameterProvidesSafety() { + helper().addSourceLines( + "Test.java", + "import com.palantir.logsafe.*;", + "import java.util.*;", + "class Test {", + " void f(List<@Unsafe String> input) {", + " // BUG: Diagnostic contains: Dangerous argument value: arg is 'UNSAFE' " + + "but the parameter requires 'SAFE'.", + " fun(input.get(0));", + " }", + " private static void fun(@Safe Object obj) {}", + "}") + .doTest(); + } + + @Test + public void testUnsafeTypeParameterProvidesReceiverSafety_iterable() { + helper().addSourceLines( + "Test.java", + "import com.palantir.logsafe.*;", + "import java.util.*;", + "class Test {", + " void f(List<@Unsafe String> input) {", + " // BUG: Diagnostic contains: Dangerous argument value: arg is 'UNSAFE' " + + "but the parameter requires 'SAFE'.", + " fun(input);", + " }", + " private static void fun(@Safe Object obj) {}", + "}") + .doTest(); + } + + @Test + public void testUnsafeTypeParameterProvidesReceiverSafety_map() { + helper().addSourceLines( + "Test.java", + "import com.palantir.logsafe.*;", + "import java.util.*;", + "class Test {", + " void f(Map<@Unsafe String, @Safe String> one, Map<@Safe String, @Unsafe String> two) {", + " // BUG: Diagnostic contains: Dangerous argument value: arg is 'UNSAFE' " + + "but the parameter requires 'SAFE'.", + " fun(one);", + " // BUG: Diagnostic contains: Dangerous argument value: arg is 'UNSAFE' " + + "but the parameter requires 'SAFE'.", + " fun(two);", + " // BUG: Diagnostic contains: Dangerous argument value: arg is 'UNSAFE' " + + "but the parameter requires 'SAFE'.", + " fun(one.keySet());", + " fun(two.keySet());", + " fun(one.values());", + " // BUG: Diagnostic contains: Dangerous argument value: arg is 'UNSAFE' " + + "but the parameter requires 'SAFE'.", + " fun(two.values());", + " // BUG: Diagnostic contains: Dangerous argument value: arg is 'UNSAFE' " + + "but the parameter requires 'SAFE'.", + " fun(one.entrySet());", + " // BUG: Diagnostic contains: Dangerous argument value: arg is 'UNSAFE' " + + "but the parameter requires 'SAFE'.", + " fun(two.entrySet());", + " // BUG: Diagnostic contains: Dangerous argument value: arg is 'UNSAFE' " + + "but the parameter requires 'SAFE'.", + " fun(one.entrySet().iterator().next().getKey());", + " fun(two.entrySet().iterator().next().getKey());", + " fun(one.entrySet().iterator().next().getValue());", + " // BUG: Diagnostic contains: Dangerous argument value: arg is 'UNSAFE' " + + "but the parameter requires 'SAFE'.", + " fun(two.entrySet().iterator().next().getValue());", + " }", + " private static void fun(@Safe Object obj) {}", + "}") + .doTest(); + } + + @Test + public void testUnsafeTypeParameterConsumesSafety() { + helper().addSourceLines( + "Test.java", + "import com.palantir.logsafe.*;", + "import java.util.*;", + "class Test {", + " void f(List<@Safe String> collection, @Unsafe String data) {", + " // BUG: Diagnostic contains: Dangerous argument value: arg is 'UNSAFE' " + + "but the parameter requires 'SAFE'.", + " collection.add(data);", + " }", + "}") + .doTest(); + } + + @Test + public void testUnsafeTypeParameterConsumesSafety_wildcard() { + helper().addSourceLines( + "Test.java", + "import com.palantir.logsafe.*;", + "import java.util.function.*;", + "class Test {", + " void f(Consumer<@Safe ? super CharSequence> consumer, @Unsafe String data) {", + " // BUG: Diagnostic contains: Dangerous argument value: arg is 'UNSAFE' " + + "but the parameter requires 'SAFE'.", + " consumer.accept(data);", + " }", + "}") + .doTest(); + } + + @Test + public void testTypeParamsDifferFromBase() { + helper().addSourceLines( + "Test.java", + "import com.palantir.logsafe.*;", + "import java.util.*;", + "class Test {", + " @Unsafe static class UnsafeClass {}", + " interface Foo extends Iterable {}", + " void f(Foo<@Safe String> foo) {", + " // BUG: Diagnostic contains: Dangerous argument value: arg is 'UNSAFE' " + + "but the parameter requires 'SAFE'.", + " fun(foo);", + " }", + " private static void fun(@Safe Object obj) {}", + "}") + .doTest(); + } + @Test public void testSafeReturnIndirect() { helper().addSourceLines( diff --git a/changelog/@unreleased/pr-2187.v2.yml b/changelog/@unreleased/pr-2187.v2.yml new file mode 100644 index 000000000..7f0045990 --- /dev/null +++ b/changelog/@unreleased/pr-2187.v2.yml @@ -0,0 +1,5 @@ +type: improvement +improvement: + description: Support safety annotations on type-use e.g. `Collection<@Safe String>` + links: + - https://github.com/palantir/gradle-baseline/pull/2187 diff --git a/versions.lock b/versions.lock index 8ddcd9abc..622c6862f 100644 --- a/versions.lock +++ b/versions.lock @@ -39,8 +39,8 @@ com.googlecode.java-diff-utils:diffutils:1.3.0 (1 constraints: 0605f935) com.googlecode.javaewah:JavaEWAH:1.1.12 (1 constraints: 750eee5e) com.palantir.javaformat:gradle-palantir-java-format:1.1.0 (1 constraints: 0405f335) com.palantir.javaformat:palantir-java-format-spi:1.1.0 (1 constraints: 711560be) -com.palantir.safe-logging:preconditions:1.25.0 (6 constraints: 4258d856) -com.palantir.safe-logging:safe-logging:1.25.0 (7 constraints: 2d69ce8e) +com.palantir.safe-logging:preconditions:1.26.0 (6 constraints: 44582458) +com.palantir.safe-logging:safe-logging:1.26.0 (7 constraints: 3269f391) com.palantir.tritium:tritium-registry:0.46.0 (1 constraints: 3c05413b) com.squareup.okhttp3:okhttp:4.3.1 (1 constraints: bf0b0dea) com.squareup.okio:okio:2.4.3 (2 constraints: 10183f8e) @@ -109,10 +109,10 @@ com.palantir.conjure.java:conjure-lib:6.41.0 (1 constraints: 3d05563b) com.palantir.conjure.java.api:errors:2.24.0 (2 constraints: 6b218cb0) com.palantir.conjure.java.api:test-utils:2.24.0 (1 constraints: 3a053f3b) com.palantir.ri:resource-identifier:2.3.0 (1 constraints: ed0f7399) -com.palantir.safe-logging:logger:1.25.0 (2 constraints: 4013f356) -com.palantir.safe-logging:logger-slf4j:1.25.0 (1 constraints: 330e8e50) -com.palantir.safe-logging:logger-spi:1.25.0 (2 constraints: 751ea2b0) -com.palantir.safe-logging:preconditions-assertj:1.25.0 (1 constraints: 3a053c3b) +com.palantir.safe-logging:logger:1.26.0 (2 constraints: 41131f57) +com.palantir.safe-logging:logger-slf4j:1.26.0 (1 constraints: 340e9150) +com.palantir.safe-logging:logger-spi:1.26.0 (2 constraints: 771ed8b0) +com.palantir.safe-logging:preconditions-assertj:1.26.0 (1 constraints: 3b053f3b) com.palantir.tokens:auth-tokens:3.14.0 (2 constraints: 591563da) com.sun.activation:jakarta.activation:2.0.0 (1 constraints: 8b0f4491) io.r2dbc:r2dbc-spi:0.9.0.RELEASE (1 constraints: f2083e99) diff --git a/versions.props b/versions.props index 6d9c586c4..e91b9d597 100644 --- a/versions.props +++ b/versions.props @@ -3,7 +3,7 @@ com.fasterxml.jackson.core:jackson-databind = 2.13.2.1 com.google.auto.service:auto-service = 1.0.1 com.google.errorprone:error_prone_* = 2.12.1 com.google.guava:guava = 31.1-jre -com.palantir.safe-logging:* = 1.25.0 +com.palantir.safe-logging:* = 1.26.0 commons-lang:commons-lang = 2.6 org.apache.maven.shared:maven-dependency-analyzer = 1.12.0 org.inferred:freebuilder = 1.14.6