Avoid accidental locale-sensitive String.format()

%s is fairly safe (requires a Formattable to use Locale), so %d is the
main risk item. Places that really didn't need to use String.format()
were converted to plain string concatenation. Logging locations were
generally converted to using the log infrastructure's delayed
formatting, which is generally locale-sensitive but we're okay with
that. That wasn't done in okhttp, however, because Android frequently
doesn't use MessageFormat so we'd lose the parameters. Everywhere else
was explicitly defined to be Locale.US, to be consistent independent of
the default system locale.
This commit is contained in:
Eric Anderson 2022-07-19 14:41:34 -07:00 committed by GitHub
parent 7568f8cce7
commit 0e45e04041
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 89 additions and 50 deletions

View File

@ -66,6 +66,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
@ -240,6 +241,7 @@ final class InProcessTransport implements ServerTransport, ConnectionClientTrans
// statuscodes.md is updated.
Status status = Status.RESOURCE_EXHAUSTED.withDescription(
String.format(
Locale.US,
"Request metadata larger than %d: %d",
serverMaxInboundMetadataSize,
metadataSize));
@ -554,6 +556,7 @@ final class InProcessTransport implements ServerTransport, ConnectionClientTrans
// Status, which may need to be updated if statuscodes.md is updated.
Status failedStatus = Status.RESOURCE_EXHAUSTED.withDescription(
String.format(
Locale.US,
"Response header metadata larger than %d: %d",
clientMaxInboundMetadataSize,
metadataSize));
@ -593,6 +596,7 @@ final class InProcessTransport implements ServerTransport, ConnectionClientTrans
// Status, which may need to be updated if statuscodes.md is updated.
status = Status.RESOURCE_EXHAUSTED.withDescription(
String.format(
Locale.US,
"Response header metadata larger than %d: %d",
clientMaxInboundMetadataSize,
metadataSize));

View File

@ -331,8 +331,7 @@ public abstract class AbstractClientStream extends AbstractStream
if (compressedStream) {
deframeFailed(
Status.INTERNAL
.withDescription(
String.format("Full stream and gRPC message encoding cannot both be set"))
.withDescription("Full stream and gRPC message encoding cannot both be set")
.asRuntimeException());
return;
}

View File

@ -358,12 +358,13 @@ final class ClientCallImpl<ReqT, RespT> extends ClientCall<ReqT, RespT> {
long effectiveTimeout = max(0, effectiveDeadline.timeRemaining(TimeUnit.NANOSECONDS));
StringBuilder builder = new StringBuilder(String.format(
Locale.US,
"Call timeout set to '%d' ns, due to context deadline.", effectiveTimeout));
if (callDeadline == null) {
builder.append(" Explicit call timeout was not set.");
} else {
long callTimeout = callDeadline.timeRemaining(TimeUnit.NANOSECONDS);
builder.append(String.format(" Explicit call timeout was '%d' ns.", callTimeout));
builder.append(String.format(Locale.US, " Explicit call timeout was '%d' ns.", callTimeout));
}
log.fine(builder.toString());

View File

@ -98,12 +98,14 @@ public class DelayedClientCall<ReqT, RespT> extends ClientCall<ReqT, RespT> {
StringBuilder builder =
new StringBuilder(
String.format(
Locale.US,
"Call timeout set to '%d' ns, due to context deadline.", remainingNanos));
if (deadline == null) {
builder.append(" Explicit call timeout was not set.");
} else {
long callTimeout = deadline.timeRemaining(TimeUnit.NANOSECONDS);
builder.append(String.format(" Explicit call timeout was '%d' ns.", callTimeout));
builder.append(String.format(
Locale.US, " Explicit call timeout was '%d' ns.", callTimeout));
}
logger.fine(builder.toString());
}

View File

@ -20,6 +20,7 @@ import static com.google.common.math.LongMath.checkedAdd;
import java.text.ParseException;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
@ -244,7 +245,8 @@ public class JsonUtil {
for (int i = 0; i < rawList.size(); i++) {
if (!(rawList.get(i) instanceof Map)) {
throw new ClassCastException(
String.format("value %s for idx %d in %s is not object", rawList.get(i), i, rawList));
String.format(
Locale.US, "value %s for idx %d in %s is not object", rawList.get(i), i, rawList));
}
}
return (List<Map<String, ?>>) rawList;
@ -260,6 +262,7 @@ public class JsonUtil {
if (!(rawList.get(i) instanceof String)) {
throw new ClassCastException(
String.format(
Locale.US,
"value '%s' for idx %d in '%s' is not string", rawList.get(i), i, rawList));
}
}

View File

@ -28,6 +28,7 @@ import java.io.Closeable;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;
import java.util.zip.DataFormatException;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
@ -386,7 +387,7 @@ public class MessageDeframer implements Closeable, Deframer {
requiredLength = nextFrame.readInt();
if (requiredLength < 0 || requiredLength > maxInboundMessageSize) {
throw Status.RESOURCE_EXHAUSTED.withDescription(
String.format("gRPC message exceeds maximum size %d: %d",
String.format(Locale.US, "gRPC message exceeds maximum size %d: %d",
maxInboundMessageSize, requiredLength))
.asRuntimeException();
}
@ -516,9 +517,9 @@ public class MessageDeframer implements Closeable, Deframer {
private void verifySize() {
if (count > maxMessageSize) {
throw Status.RESOURCE_EXHAUSTED.withDescription(String.format(
"Decompressed gRPC message exceeds maximum size %d",
maxMessageSize)).asRuntimeException();
throw Status.RESOURCE_EXHAUSTED
.withDescription("Decompressed gRPC message exceeds maximum size " + maxMessageSize)
.asRuntimeException();
}
}
}

View File

@ -34,6 +34,7 @@ import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import javax.annotation.Nullable;
/**
@ -172,7 +173,8 @@ public class MessageFramer implements Framer {
if (maxOutboundMessageSize >= 0 && written > maxOutboundMessageSize) {
throw Status.RESOURCE_EXHAUSTED
.withDescription(
String.format("message too large %d > %d", written , maxOutboundMessageSize))
String.format(
Locale.US, "message too large %d > %d", written , maxOutboundMessageSize))
.asRuntimeException();
}
writeBufferChain(bufferChain, false);
@ -192,7 +194,8 @@ public class MessageFramer implements Framer {
if (maxOutboundMessageSize >= 0 && written > maxOutboundMessageSize) {
throw Status.RESOURCE_EXHAUSTED
.withDescription(
String.format("message too large %d > %d", written , maxOutboundMessageSize))
String.format(
Locale.US, "message too large %d > %d", written , maxOutboundMessageSize))
.asRuntimeException();
}
@ -215,7 +218,8 @@ public class MessageFramer implements Framer {
if (maxOutboundMessageSize >= 0 && messageLength > maxOutboundMessageSize) {
throw Status.RESOURCE_EXHAUSTED
.withDescription(
String.format("message too large %d > %d", messageLength , maxOutboundMessageSize))
String.format(
Locale.US, "message too large %d > %d", messageLength , maxOutboundMessageSize))
.asRuntimeException();
}
headerScratch.clear();

View File

@ -133,7 +133,7 @@ class ProxyDetectorImpl implements ProxyDetector {
// let url be null
log.log(
Level.WARNING,
String.format("failed to create URL for Authenticator: %s %s", protocol, host));
"failed to create URL for Authenticator: {0} {1}", new Object[] {protocol, host});
}
// TODO(spencerfang): consider using java.security.AccessController here
return Authenticator.requestPasswordAuthentication(

View File

@ -49,6 +49,7 @@ import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.zip.GZIPOutputStream;
import org.junit.Before;
@ -507,7 +508,7 @@ public class MessageDeframerTest {
for (int i = 0; i < count; i++) {
assertEquals("inboundMessage(" + i + ")", tracer.nextInboundEvent());
assertEquals(
String.format("inboundMessageRead(%d, %d, -1)", i, sizes[i * 2]),
String.format(Locale.US, "inboundMessageRead(%d, %d, -1)", i, sizes[i * 2]),
tracer.nextInboundEvent());
expectedWireSize += sizes[i * 2];
expectedUncompressedSize += sizes[i * 2 + 1];

View File

@ -34,6 +34,7 @@ import java.io.ByteArrayInputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.Locale;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@ -382,7 +383,8 @@ public class MessageFramerTest {
for (int i = 0; i < count; i++) {
assertEquals("outboundMessage(" + i + ")", tracer.nextOutboundEvent());
assertEquals(
String.format("outboundMessageSent(%d, %d, %d)", i, sizes[i * 2], sizes[i * 2 + 1]),
String.format(
Locale.US, "outboundMessageSent(%d, %d, %d)", i, sizes[i * 2], sizes[i * 2 + 1]),
tracer.nextOutboundEvent());
expectedWireSize += sizes[i * 2];
expectedUncompressedSize += sizes[i * 2 + 1];

View File

@ -28,6 +28,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.logging.Handler;
@ -102,6 +103,7 @@ public final class NettyClientInteropServlet extends HttpServlet {
resp.setStatus(200);
writer.println(
String.format(
Locale.US,
"PASS! Tests ran %d, tests ignored %d",
result.getRunCount(),
result.getIgnoreCount()));
@ -109,6 +111,7 @@ public final class NettyClientInteropServlet extends HttpServlet {
resp.setStatus(500);
writer.println(
String.format(
Locale.US,
"FAILED! Tests ran %d, tests failed %d, tests ignored %d",
result.getRunCount(),
result.getFailureCount(),

View File

@ -115,6 +115,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
@ -2058,6 +2059,7 @@ public abstract class AbstractInteropTest {
.get().getAttributes().get(Grpc.TRANSPORT_ATTR_REMOTE_ADDR);
System.err.print(
String.format(
Locale.US,
"soak iteration: %d elapsed_ms: %d peer: %s",
i, result.getLatencyMs(), peer != null ? peer.toString() : "null"));
if (!result.getStatus().equals(Status.OK)) {
@ -2066,8 +2068,7 @@ public abstract class AbstractInteropTest {
} else if (result.getLatencyMs() > maxAcceptablePerIterationLatencyMs) {
totalFailures++;
System.err.println(
String.format(
" exceeds max acceptable latency: %d", maxAcceptablePerIterationLatencyMs));
" exceeds max acceptable latency: " + maxAcceptablePerIterationLatencyMs);
} else {
System.err.println(" succeeded");
}
@ -2082,6 +2083,7 @@ public abstract class AbstractInteropTest {
soakChannel.awaitTermination(10, TimeUnit.SECONDS);
System.err.println(
String.format(
Locale.US,
"soak test ran: %d / %d iterations\n"
+ "total failures: %d\n"
+ "max failures threshold: %d\n"
@ -2102,6 +2104,7 @@ public abstract class AbstractInteropTest {
// check if we timed out
String timeoutErrorMessage =
String.format(
Locale.US,
"soak test consumed all %d seconds of time and quit early, only "
+ "having ran %d out of desired %d iterations.",
overallTimeoutSeconds,
@ -2111,6 +2114,7 @@ public abstract class AbstractInteropTest {
// check if we had too many failures
String tooManyFailuresErrorMessage =
String.format(
Locale.US,
"soak test total failures: %d exceeds max failures threshold: %d.",
totalFailures, maxFailures);
assertTrue(tooManyFailuresErrorMessage, totalFailures <= maxFailures);
@ -2353,9 +2357,10 @@ public abstract class AbstractInteropTest {
long uncompressedSentSize = 0;
int seqNo = 0;
for (MessageLite msg : sentMessages) {
assertThat(tracer.nextOutboundEvent()).isEqualTo(String.format("outboundMessage(%d)", seqNo));
assertThat(tracer.nextOutboundEvent())
.isEqualTo(String.format(Locale.US, "outboundMessage(%d)", seqNo));
assertThat(tracer.nextOutboundEvent()).matches(
String.format("outboundMessageSent\\(%d, -?[0-9]+, -?[0-9]+\\)", seqNo));
String.format(Locale.US, "outboundMessageSent\\(%d, -?[0-9]+, -?[0-9]+\\)", seqNo));
seqNo++;
uncompressedSentSize += msg.getSerializedSize();
}
@ -2363,9 +2368,10 @@ public abstract class AbstractInteropTest {
long uncompressedReceivedSize = 0;
seqNo = 0;
for (MessageLite msg : receivedMessages) {
assertThat(tracer.nextInboundEvent()).isEqualTo(String.format("inboundMessage(%d)", seqNo));
assertThat(tracer.nextInboundEvent())
.isEqualTo(String.format(Locale.US, "inboundMessage(%d)", seqNo));
assertThat(tracer.nextInboundEvent()).matches(
String.format("inboundMessageRead\\(%d, -?[0-9]+, -?[0-9]+\\)", seqNo));
String.format(Locale.US, "inboundMessageRead\\(%d, -?[0-9]+, -?[0-9]+\\)", seqNo));
uncompressedReceivedSize += msg.getSerializedSize();
seqNo++;
}

View File

@ -54,6 +54,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
@ -231,8 +232,8 @@ public class StressTestClient {
ManagedChannel channel = createChannel(address);
channels.add(channel);
for (int j = 0; j < stubsPerChannel; j++) {
String gaugeName =
String.format("/stress_test/server_%d/channel_%d/stub_%d/qps", serverIdx, i, j);
String gaugeName = String.format(
Locale.US, "/stress_test/server_%d/channel_%d/stub_%d/qps", serverIdx, i, j);
Worker worker =
new Worker(channel, testCaseWeightPairs, durationSecs, gaugeName);

View File

@ -310,9 +310,7 @@ public final class XdsTestServer {
} catch (NumberFormatException e) {
newCall.close(
Status.INVALID_ARGUMENT.withDescription(
String.format(
"Invalid format for grpc-previous-rpc-attempts header (%s)",
attemptNumHeader)),
"Invalid format for grpc-previous-rpc-attempts header: " + attemptNumHeader),
new Metadata());
return noopListener;
}
@ -329,7 +327,7 @@ public final class XdsTestServer {
} else {
newCall.close(
Status.INVALID_ARGUMENT.withDescription(
String.format("Invalid format for rpc-behavior header (%s)", callBehavior)),
"Invalid format for rpc-behavior header: " + callBehavior),
new Metadata()
);
return noopListener;
@ -344,7 +342,7 @@ public final class XdsTestServer {
} catch (NumberFormatException e) {
newCall.close(
Status.INVALID_ARGUMENT.withDescription(
String.format("Invalid format for rpc-behavior header (%s)", callBehavior)),
"Invalid format for rpc-behavior header: " + callBehavior),
new Metadata());
return noopListener;
} catch (InterruptedException e) {
@ -364,7 +362,7 @@ public final class XdsTestServer {
} catch (NumberFormatException e) {
newCall.close(
Status.INVALID_ARGUMENT.withDescription(
String.format("Invalid format for rpc-behavior header (%s)", callBehavior)),
"Invalid format for rpc-behavior header: " + callBehavior),
new Metadata());
return noopListener;
}
@ -390,7 +388,7 @@ public final class XdsTestServer {
} catch (NumberFormatException e) {
newCall.close(
Status.INVALID_ARGUMENT.withDescription(
String.format("Invalid format for rpc-behavior header (%s)", callBehavior)),
"Invalid format for rpc-behavior header: " + callBehavior),
new Metadata());
return noopListener;
}

View File

@ -951,17 +951,16 @@ class NettyClientHandler extends AbstractNettyHandler {
Http2Ping p = ping;
if (ackPayload == flowControlPing().payload()) {
flowControlPing().updateWindow();
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, String.format("Window: %d",
decoder().flowController().initialWindowSize(connection().connectionStream())));
}
logger.log(Level.FINE, "Window: {0}",
decoder().flowController().initialWindowSize(connection().connectionStream()));
} else if (p != null) {
if (p.payload() == ackPayload) {
p.complete();
ping = null;
} else {
logger.log(Level.WARNING, String.format(
"Received unexpected ping ack. Expecting %d, got %d", p.payload(), ackPayload));
logger.log(Level.WARNING,
"Received unexpected ping ack. Expecting {0}, got {1}",
new Object[] {p.payload(), ackPayload});
}
} else {
logger.warning("Received unexpected ping ack. No ping outstanding");

View File

@ -894,10 +894,8 @@ class NettyServerHandler extends AbstractNettyHandler {
}
if (data == flowControlPing().payload()) {
flowControlPing().updateWindow();
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, String.format("Window: %d",
decoder().flowController().initialWindowSize(connection().connectionStream())));
}
logger.log(Level.FINE, "Window: {0}",
decoder().flowController().initialWindowSize(connection().connectionStream()));
} else if (data == GRACEFUL_SHUTDOWN_PING) {
if (gracefulShutdown == null) {
// this should never happen

View File

@ -80,6 +80,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
@ -642,7 +643,8 @@ class OkHttpClientTransport implements ConnectionClientTransport, TransportExcep
// Prepare headers and request method line
Request proxyRequest = createHttpProxyRequest(address, proxyUsername, proxyPassword);
HttpUrl url = proxyRequest.httpUrl();
String requestLine = String.format("CONNECT %s:%d HTTP/1.1", url.host(), url.port());
String requestLine =
String.format(Locale.US, "CONNECT %s:%d HTTP/1.1", url.host(), url.port());
// Write request to socket
sink.writeUtf8(requestLine).writeUtf8("\r\n");
@ -674,6 +676,7 @@ class OkHttpClientTransport implements ConnectionClientTransport, TransportExcep
// ignored
}
String message = String.format(
Locale.US,
"Response returned from proxy was not successful (expected 2xx, got %d %s). "
+ "Response body:\n%s",
statusLine.code, statusLine.message, body.readUtf8());
@ -1185,6 +1188,7 @@ class OkHttpClientTransport implements ConnectionClientTransport, TransportExcep
if (metadataSize > maxInboundMetadataSize) {
failedStatus = Status.RESOURCE_EXHAUSTED.withDescription(
String.format(
Locale.US,
"Response %s metadata larger than %d: %d",
inFinished ? "trailer" : "header",
maxInboundMetadataSize,
@ -1300,8 +1304,9 @@ class OkHttpClientTransport implements ConnectionClientTransport, TransportExcep
p = ping;
ping = null;
} else {
log.log(Level.WARNING, String.format("Received unexpected ping ack. "
+ "Expecting %d, got %d", ping.payload(), ackPayload));
log.log(Level.WARNING, String.format(
Locale.US, "Received unexpected ping ack. Expecting %d, got %d",
ping.payload(), ackPayload));
}
} else {
log.warning("Received unexpected ping ack. No ping outstanding");

View File

@ -22,6 +22,7 @@ package io.grpc.okhttp.internal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
/**
* The header fields of a single HTTP message. Values are uninterpreted strings;
@ -132,6 +133,7 @@ public final class Headers {
char c = name.charAt(i);
if (c <= '\u001f' || c >= '\u007f') {
throw new IllegalArgumentException(String.format(
Locale.US,
"Unexpected char %#04x at %d in header name: %s", (int) c, i, name));
}
}
@ -140,6 +142,7 @@ public final class Headers {
char c = value.charAt(i);
if (c <= '\u001f' || c >= '\u007f') {
throw new IllegalArgumentException(String.format(
Locale.US,
"Unexpected char %#04x at %d in header value: %s", (int) c, i, value));
}
}

View File

@ -23,6 +23,7 @@ import com.google.errorprone.annotations.FormatMethod;
import io.grpc.okhttp.internal.Protocol;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.logging.Logger;
import okio.Buffer;
@ -590,12 +591,12 @@ public final class Http2 implements Variant {
@FormatMethod
private static IllegalArgumentException illegalArgument(String message, Object... args) {
throw new IllegalArgumentException(format(message, args));
throw new IllegalArgumentException(format(Locale.US, message, args));
}
@FormatMethod
private static IOException ioException(String message, Object... args) throws IOException {
throw new IOException(format(message, args));
throw new IOException(format(Locale.US, message, args));
}
/**
@ -684,7 +685,7 @@ public final class Http2 implements Variant {
static String formatHeader(boolean inbound, int streamId, int length, byte type, byte flags) {
String formattedType = type < TYPES.length ? TYPES[type] : format("0x%02x", type);
String formattedFlags = formatFlags(type, flags);
return format("%s 0x%08x %5d %-13s %s", inbound ? "<<" : ">>", streamId, length,
return format(Locale.US, "%s 0x%08x %5d %-13s %s", inbound ? "<<" : ">>", streamId, length,
formattedType, formattedFlags);
}

View File

@ -18,6 +18,7 @@ package io.grpc.internal.testing;
import io.grpc.Status;
import io.grpc.StreamTracer;
import java.util.Locale;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@ -180,6 +181,7 @@ public interface TestStreamTracer {
int seqNo, long optionalWireSize, long optionalUncompressedSize) {
outboundEvents.add(
String.format(
Locale.US,
"outboundMessageSent(%d, %d, %d)",
seqNo, optionalWireSize, optionalUncompressedSize));
}
@ -189,6 +191,7 @@ public interface TestStreamTracer {
int seqNo, long optionalWireSize, long optionalUncompressedSize) {
inboundEvents.add(
String.format(
Locale.US,
"inboundMessageRead(%d, %d, %d)", seqNo, optionalWireSize, optionalUncompressedSize));
}

View File

@ -1795,8 +1795,8 @@ final class ClientXdsClient extends XdsClient implements XdsResponseHandler, Res
"Cluster " + clusterName
+ ": LOGICAL DNS clusters socket_address must have port_value");
}
String dnsHostName =
String.format("%s:%d", socketAddress.getAddress(), socketAddress.getPortValue());
String dnsHostName = String.format(
Locale.US, "%s:%d", socketAddress.getAddress(), socketAddress.getPortValue());
return StructOrError.fromStruct(CdsUpdate.forLogicalDns(
clusterName, dnsHostName, lrsServerInfo, maxConcurrentRequests, upstreamTlsContext));
}

View File

@ -60,6 +60,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@ -470,7 +471,7 @@ final class ClusterResolverLoadBalancer extends LoadBalancer {
}
}
if ("".equals(foundName)) {
foundName = String.format("%s[child%d]", name, priorityNameGenId++);
foundName = String.format(Locale.US, "%s[child%d]", name, priorityNameGenId++);
}
for (Locality locality : todo.get(priority)) {
newNames.put(locality, foundName);

View File

@ -48,6 +48,7 @@ import io.grpc.xds.FaultConfig.FaultAbort;
import io.grpc.xds.FaultConfig.FaultDelay;
import io.grpc.xds.Filter.ClientInterceptorBuilder;
import io.grpc.xds.ThreadSafeRandom.ThreadSafeRandomImpl;
import java.util.Locale;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
@ -255,6 +256,7 @@ final class FaultFilter implements Filter, ClientInterceptorBuilder {
// only sent out after the delay. There could be a race between local and
// remote, but it is rather rare.)
String description = String.format(
Locale.US,
"Deadline exceeded after up to %d ns of fault-injected delay",
finalDelayNanos);
if (status.getDescription() != null) {

View File

@ -31,6 +31,7 @@ import io.grpc.internal.JsonParser;
import io.grpc.xds.RingHashLoadBalancer.RingHashConfig;
import java.io.IOException;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Locale;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -117,7 +118,8 @@ public class RingHashLoadBalancerProviderTest {
@Test
public void parseLoadBalancingConfig_invalid_ringTooLarge() throws IOException {
long ringSize = RingHashLoadBalancerProvider.MAX_RING_SIZE + 1;
String lbConfig = String.format("{\"minRingSize\" : 10, \"maxRingSize\" : %d}", ringSize);
String lbConfig =
String.format(Locale.US, "{\"minRingSize\" : 10, \"maxRingSize\" : %d}", ringSize);
ConfigOrError configOrError =
provider.parseLoadBalancingPolicyConfig(parseJsonObject(lbConfig));
assertThat(configOrError.getError()).isNotNull();