Skip to content

EC2 DescribeInstances query uses locale-dependent formatting #5968

Open
@DaveCTurner

Description

@DaveCTurner

Describe the bug

When calling Ec2Client#describeInstances with one or more filter expressions, the filters contain numbers formatted using the current locale rather than the root locale. Thus for instance running in the ne (Nepalese) local the query uses Filter.%E0%A5%A7.Name rather than Filter.1.Name, where %E0%A5%A7 is the UTF-8 encoding for U+0967 DEVANAGARI DIGIT ONE which is the rendering for the integer 1 in this locale. The full HTTP request in this case is as follows:

POST / HTTP/1.1
Host: 127.0.0.1:60608
amz-sdk-invocation-id: a5d80d84-b502-096b-bef6-da85818cb947
amz-sdk-request: attempt=1; max=10
Authorization: AWS4-HMAC-SHA256 Credential=ec2_key/20250318/es-test-region/ec2/aws4_request, SignedHeaders=amz-sdk-invocation-id;amz-sdk-request;content-length;content-type;host;x-amz-content-sha256;x-amz-date, Signature=749ddaeccbe94b749d6c1e7446a070dcca7ec2845068053883f28fdd9129ded3
Content-Type: application/x-www-form-urlencoded; charset=utf-8
User-Agent: aws-sdk-java/2.30.38 md/io#sync md/http#Apache ua/2.1 os/Mac_OS_X#15.3.2 lang/java#23 md/OpenJDK_64-Bit_Server_VM#23+37 md/vendor#Eclipse_Adoptium md/en_GB cfg/auth-source#stat m/D
x-amz-content-sha256: 1380541b646459c65b2316cb6c26f03a41760ebe57c48ecbe55697c5da1b3938
X-Amz-Date: 20250318T142438Z
Content-Length: 239
Connection: Keep-Alive

Action=DescribeInstances&Version=2016-11-15&Filter.%E0%A5%A7.Name=instance-state-name&Filter.%E0%A5%A7.Value.%E0%A5%A7=running&Filter.%E0%A5%A7.Value.%E0%A5%A8=pending&Filter.%E0%A5%A8.Name=tag%3Astage&Filter.%E0%A5%A8.Value.%E0%A5%A7=prod

EC2 rejects this with a 400 Bad request:

[2025-03-19T09:36:24,478][DEBUG][o.e.d.e.AwsEc2SeedHostsProvider] [node-0] Full exception:software.amazon.awssdk.services.ec2.model.Ec2Exception: Value (१) for parameter QueryStringParameter is invalid. Invalid or illegal XML character specified (Service: Ec2, Status Code: 400, Request ID: 7405f831-6f63-4bd1-b54f-f96be228b4c8) (SDK Attempt Count: 1)

The problem is that software.amazon.awssdk.protocols.query.internal.marshall.ListQueryMarshaller#EC2_QUERY_PATH_RESOLVER uses a bare String.format("%s.%d", path, i + 1) rather than String.format(Locale.ROOT, "%s.%d", path, i + 1)

Regression Issue

  • Select this option if this issue appears to be a regression.

Expected Behavior

In all locales, we should render the filters using ASCII digits 0 to 9 only:

Action=DescribeInstances&Version=2016-11-15&Filter.1.Name=instance-state-name&Filter.1.Value.1=running&Filter.1.Value.2=pending&Filter.2.Name=tag%3Astage&Filter.2.Value.1=prod

Current Behavior

We render the filters using locale-dependent numerals, UTF-8-encoded, for instance in the ne locale:

Action=DescribeInstances&Version=2016-11-15&Filter.%E0%A5%A7.Name=instance-state-name&Filter.%E0%A5%A7.Value.%E0%A5%A7=running&Filter.%E0%A5%A7.Value.%E0%A5%A8=pending&Filter.%E0%A5%A8.Name=tag%3Astage&Filter.%E0%A5%A8.Value.%E0%A5%A7=prod

Reproduction Steps

Attempt to invoke Ec2Client#describeInstances in a locale that does not render numerals using the ASCII digits 0 to 9, such as for instance ne.

Possible Solution

diff --git a/core/protocols/aws-query-protocol/src/main/java/software/amazon/awssdk/protocols/query/internal/marshall/ListQueryMarshaller.java b/core/protocols/aws-query-protocol/src/main/java/software/amazon/awssdk/protocols/query/internal/marshall/ListQueryMarshaller.java
index 971dbb96f95..4323fd80b1c 100644
--- a/core/protocols/aws-query-protocol/src/main/java/software/amazon/awssdk/protocols/query/internal/marshall/ListQueryMarshaller.java
+++ b/core/protocols/aws-query-protocol/src/main/java/software/amazon/awssdk/protocols/query/internal/marshall/ListQueryMarshaller.java
@@ -31,7 +31,7 @@ public class ListQueryMarshaller implements QueryMarshaller<List<?>> {
         listTrait.isFlattened() ?
         String.format("%s.%d", path, i + 1) :
         String.format("%s.%s.%d", path, listTrait.memberFieldInfo().locationName(), i + 1);
-    private static final PathResolver EC2_QUERY_PATH_RESOLVER = (path, i, listTrait) -> String.format("%s.%d", path, i + 1);
+    private static final PathResolver EC2_QUERY_PATH_RESOLVER = (path, i, listTrait) -> String.format(Locale.ROOT, "%s.%d", path, i + 1);

     private static final EmptyListMarshaller AWS_QUERY_EMPTY_LIST_MARSHALLER =
         (context, path) -> context.request().putRawQueryParameter(path, "");

Additional Information/Context

No response

AWS Java SDK version used

2.30.38

JDK version used

OpenJDK Runtime Environment Temurin-23+37 (build 23+37)

Operating System and version

Mac OS X 15.3.2 aarch64/Oracle Corporation 23 (64-bit)/cpus=12,threads=1,free=493903224,total=536870912

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugThis issue is a bug.p2This is a standard priority issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions