Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed bug where query params were being parsed incorrectly if an encoded comma was the query value #17655

Merged
merged 3 commits into from
Nov 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ import com.azure.storage.blob.options.BlobSetAccessTierOptions
import com.azure.storage.blob.options.PageBlobCreateOptions
import com.azure.storage.blob.specialized.AppendBlobClient
import com.azure.storage.blob.specialized.BlobClientBase
import com.azure.storage.common.StorageSharedKeyCredential
import com.azure.storage.common.Utility
import com.azure.storage.common.implementation.StorageImplUtils
import reactor.test.StepVerifier
import spock.lang.Requires
import spock.lang.Unroll
Expand Down Expand Up @@ -909,6 +911,20 @@ class ContainerAPITest extends APISpec {
.verifyComplete()
}

def "List blobs prefix with comma"() {
setup:
def prefix = generateBlobName() + ", " + generateBlobName()
def b = cc.getBlobClient(prefix).getBlockBlobClient()
b.upload(defaultInputStream.get(), defaultData.remaining())

when:
ListBlobsOptions options = new ListBlobsOptions().setPrefix(prefix)
def blob = cc.listBlobs(options, null).iterator().next()

then:
blob.getName() == prefix
}

def "List blobs flat options fail"() {
when:
new ListBlobsOptions().setMaxResultsPerPage(0)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
{
"networkCallRecords" : [ {
"Method" : "PUT",
"Uri" : "https://REDACTED.blob.core.windows.net/jtclistblobsprefixwithcomma097102c4f575e414a74be?restype=container",
"Headers" : {
"x-ms-version" : "2020-02-10",
"User-Agent" : "azsdk-java-azure-storage-blob/12.10.0-beta.1 (11.0.7; Windows 10; 10.0)",
"x-ms-client-request-id" : "4197dd95-684f-4280-af03-5754c699537a"
},
"Response" : {
"x-ms-version" : "2020-02-10",
"Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0",
"ETag" : "0x8D88C040CD150A7",
"Last-Modified" : "Wed, 18 Nov 2020 20:53:49 GMT",
"retry-after" : "0",
"Content-Length" : "0",
"StatusCode" : "201",
"x-ms-request-id" : "5a0b9c11-c01e-0073-35ec-bd7d3a000000",
"Date" : "Wed, 18 Nov 2020 20:53:49 GMT",
"x-ms-client-request-id" : "4197dd95-684f-4280-af03-5754c699537a"
},
"Exception" : null
}, {
"Method" : "PUT",
"Uri" : "https://REDACTED.blob.core.windows.net/jtclistblobsprefixwithcomma097102c4f575e414a74be/javabloblistblobsprefixwithcomma199461a7d43fde3c03%2C%20javabloblistblobsprefixwithcomma235482222869197945",
"Headers" : {
"x-ms-version" : "2020-02-10",
"User-Agent" : "azsdk-java-azure-storage-blob/12.10.0-beta.1 (11.0.7; Windows 10; 10.0)",
"x-ms-client-request-id" : "e98643a2-72d7-4436-89f2-2cdac3d230c2",
"Content-Type" : "application/octet-stream"
},
"Response" : {
"x-ms-version" : "2020-02-10",
"Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0",
"x-ms-content-crc64" : "6RYQPwaVsyQ=",
"Last-Modified" : "Wed, 18 Nov 2020 20:53:50 GMT",
"x-ms-version-id" : "2020-11-18T20:53:50.0957813Z",
"retry-after" : "0",
"StatusCode" : "201",
"x-ms-request-server-encrypted" : "true",
"Date" : "Wed, 18 Nov 2020 20:53:50 GMT",
"Content-MD5" : "wh+Wm18D0z1D4E+PE252gg==",
"ETag" : "0x8D88C040D212075",
"Content-Length" : "0",
"x-ms-request-id" : "5a0b9c51-c01e-0073-69ec-bd7d3a000000",
"x-ms-client-request-id" : "e98643a2-72d7-4436-89f2-2cdac3d230c2"
},
"Exception" : null
}, {
"Method" : "GET",
"Uri" : "https://REDACTED.blob.core.windows.net/jtclistblobsprefixwithcomma097102c4f575e414a74be?prefix=javabloblistblobsprefixwithcomma199461a7d43fde3c03%2C%20javabloblistblobsprefixwithcomma235482222869197945&restype=container&comp=list",
"Headers" : {
"x-ms-version" : "2020-02-10",
"User-Agent" : "azsdk-java-azure-storage-blob/12.10.0-beta.1 (11.0.7; Windows 10; 10.0)",
"x-ms-client-request-id" : "3e79fbb3-6e16-43ac-b977-91dab3004419"
},
"Response" : {
"Transfer-Encoding" : "chunked",
"x-ms-version" : "2020-02-10",
"Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0",
"retry-after" : "0",
"StatusCode" : "200",
"x-ms-request-id" : "5a0b9c60-c01e-0073-74ec-bd7d3a000000",
"Body" : "<?xml version=\"1.0\" encoding=\"utf-8\"?><EnumerationResults ServiceEndpoint=\"https://gapracanary.blob.core.windows.net/\" ContainerName=\"jtclistblobsprefixwithcomma097102c4f575e414a74be\"><Prefix>javabloblistblobsprefixwithcomma199461a7d43fde3c03, javabloblistblobsprefixwithcomma235482222869197945</Prefix><Blobs><Blob><Name>javabloblistblobsprefixwithcomma199461a7d43fde3c03, javabloblistblobsprefixwithcomma235482222869197945</Name><VersionId>2020-11-18T20:53:50.0957813Z</VersionId><IsCurrentVersion>true</IsCurrentVersion><Properties><Creation-Time>Wed, 18 Nov 2020 20:53:50 GMT</Creation-Time><Last-Modified>Wed, 18 Nov 2020 20:53:50 GMT</Last-Modified><Etag>0x8D88C040D212075</Etag><Content-Length>7</Content-Length><Content-Type>application/octet-stream</Content-Type><Content-Encoding /><Content-Language /><Content-CRC64 /><Content-MD5>wh+Wm18D0z1D4E+PE252gg==</Content-MD5><Cache-Control /><Content-Disposition /><LastAccessTime>Wed, 18 Nov 2020 20:53:50 GMT</LastAccessTime><BlobType>BlockBlob</BlobType><AccessTier>Hot</AccessTier><AccessTierInferred>true</AccessTierInferred><LeaseStatus>unlocked</LeaseStatus><LeaseState>available</LeaseState><ServerEncrypted>true</ServerEncrypted></Properties><OrMetadata /></Blob></Blobs><NextMarker /></EnumerationResults>",
"Date" : "Wed, 18 Nov 2020 20:53:50 GMT",
"x-ms-client-request-id" : "3e79fbb3-6e16-43ac-b977-91dab3004419",
"Content-Type" : "application/xml"
},
"Exception" : null
}, {
"Method" : "GET",
"Uri" : "https://REDACTED.blob.core.windows.net?prefix=jtclistblobsprefixwithcomma&comp=list",
"Headers" : {
"x-ms-version" : "2020-02-10",
"User-Agent" : "azsdk-java-azure-storage-blob/12.10.0-beta.1 (11.0.7; Windows 10; 10.0)",
"x-ms-client-request-id" : "3e01836f-8769-45a6-926e-d3df8cd56a2c"
},
"Response" : {
"Transfer-Encoding" : "chunked",
"x-ms-version" : "2020-02-10",
"Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0",
"retry-after" : "0",
"StatusCode" : "200",
"x-ms-request-id" : "5a0b9c6a-c01e-0073-7bec-bd7d3a000000",
"Body" : "<?xml version=\"1.0\" encoding=\"utf-8\"?><EnumerationResults ServiceEndpoint=\"https://gapracanary.blob.core.windows.net/\"><Prefix>jtclistblobsprefixwithcomma</Prefix><Containers><Container><Name>jtclistblobsprefixwithcomma097102c4f575e414a74be</Name><Properties><Last-Modified>Wed, 18 Nov 2020 20:53:49 GMT</Last-Modified><Etag>\"0x8D88C040CD150A7\"</Etag><LeaseStatus>unlocked</LeaseStatus><LeaseState>available</LeaseState><DefaultEncryptionScope>$account-encryption-key</DefaultEncryptionScope><DenyEncryptionScopeOverride>false</DenyEncryptionScopeOverride><HasImmutabilityPolicy>false</HasImmutabilityPolicy><HasLegalHold>false</HasLegalHold></Properties></Container></Containers><NextMarker /></EnumerationResults>",
"Date" : "Wed, 18 Nov 2020 20:53:50 GMT",
"x-ms-client-request-id" : "3e01836f-8769-45a6-926e-d3df8cd56a2c",
"Content-Type" : "application/xml"
},
"Exception" : null
}, {
"Method" : "DELETE",
"Uri" : "https://REDACTED.blob.core.windows.net/jtclistblobsprefixwithcomma097102c4f575e414a74be?restype=container",
"Headers" : {
"x-ms-version" : "2020-02-10",
"User-Agent" : "azsdk-java-azure-storage-blob/12.10.0-beta.1 (11.0.7; Windows 10; 10.0)",
"x-ms-client-request-id" : "1bce1177-17a1-4aa4-b4b2-a6b84369685c"
},
"Response" : {
"x-ms-version" : "2020-02-10",
"Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0",
"retry-after" : "0",
"Content-Length" : "0",
"StatusCode" : "202",
"x-ms-request-id" : "5a0b9c78-c01e-0073-04ec-bd7d3a000000",
"Date" : "Wed, 18 Nov 2020 20:53:50 GMT",
"x-ms-client-request-id" : "1bce1177-17a1-4aa4-b4b2-a6b84369685c"
},
"Exception" : null
} ],
"variables" : [ "jtclistblobsprefixwithcomma097102c4f575e414a74be", "javabloblistblobsprefixwithcomma199461a7d43fde3c03", "javabloblistblobsprefixwithcomma235482222869197945" ]
}
1 change: 1 addition & 0 deletions sdk/storage/azure-storage-common/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## 12.10.0-beta.1 (Unreleased)
- Added ability to specify timeout units in RequestRetryOptions.
- Fixed bug where query params were being parsed incorrectly if an encoded comma was the query value.

## 12.9.0 (2020-11-11)
- GA release
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,18 @@ public static Map<String, String> parseQueryString(final String queryString) {
* @return a mapping of query string pieces as key-value pairs.
*/
public static Map<String, String[]> parseQueryStringSplitValues(final String queryString) {
return parseQueryStringHelper(queryString, (value) -> urlDecode(value).split(","));
// We need to first split by comma and then decode each piece since we don't want to confuse legitimate separate
// query values from query values that container a comma.
// Example 1: prefix=a%2cb => prefix={decode(a%2cb)} => prefix={"a,b"}
// Example 2: prefix=a,b => prefix={decode(a),decode(b)} => prefix={"a", "b"}
return parseQueryStringHelper(queryString, value -> {
String[] v = value.split(",");
String[] ret = new String[v.length];
for (int i = 0; i < v.length; i++) {
ret[i] = urlDecode(v[i]);
}
return ret;
});
}

private static <T> Map<String, T> parseQueryStringHelper(final String queryString,
Expand Down