UploadPartCopy: Fail if improper source range.

S3Proxy should check the format of the x-amz-copy-source-range value
when handling an UploadPartCopy request. The patch changes the behavior
to return an InvalidArgument error along with the matching error
description to AWS S3. To match the error format, the S3Exception class
is modified to return the actual error message, rather than the String
version of the error code.

Corresponding tests will be added to ceph/s3-tests.

Fixes: #304
pull/311/head
Timur Alperovich 2019-06-24 15:03:55 -07:00 zatwierdzone przez Andrew Gaul
rodzic 1966efc269
commit e37300dd3f
2 zmienionych plików z 28 dodań i 15 usunięć

Wyświetl plik

@ -63,7 +63,7 @@ public final class S3Exception extends Exception {
@Override
public String getMessage() {
StringBuilder builder = new StringBuilder().append(error);
StringBuilder builder = new StringBuilder().append(super.getMessage());
if (!elements.isEmpty()) {
builder.append(" ").append(elements);
}

Wyświetl plik

@ -2469,20 +2469,33 @@ public class S3ProxyHandler {
GetOptions options = new GetOptions();
String range = request.getHeader(AwsHttpHeaders.COPY_SOURCE_RANGE);
long expectedSize = -1;
if (range != null && range.startsWith("bytes=") &&
// ignore multiple ranges
range.indexOf(',') == -1) {
range = range.substring("bytes=".length());
String[] ranges = range.split("-", 2);
if (ranges[0].isEmpty()) {
options.tail(Long.parseLong(ranges[1]));
} else if (ranges[1].isEmpty()) {
options.startAt(Long.parseLong(ranges[0]));
} else {
long start = Long.parseLong(ranges[0]);
long end = Long.parseLong(ranges[1]);
expectedSize = end - start + 1;
options.range(start, end);
if (range != null) {
if (!range.startsWith("bytes=") || range.indexOf(',') != -1 ||
range.indexOf('-') == -1) {
throw new S3Exception(S3ErrorCode.INVALID_ARGUMENT,
"The x-amz-copy-source-range value must be of the form " +
"bytes=first-last where first and last are the " +
"zero-based offsets of the first and last bytes to copy");
}
try {
range = range.substring("bytes=".length());
String[] ranges = range.split("-", 2);
if (ranges[0].isEmpty()) {
options.tail(Long.parseLong(ranges[1]));
} else if (ranges[1].isEmpty()) {
options.startAt(Long.parseLong(ranges[0]));
} else {
long start = Long.parseLong(ranges[0]);
long end = Long.parseLong(ranges[1]);
expectedSize = end - start + 1;
options.range(start, end);
}
} catch (NumberFormatException nfe) {
throw new S3Exception(S3ErrorCode.INVALID_ARGUMENT,
"The x-amz-copy-source-range value must be of the form " +
"bytes=first-last where first and last are the " +
"zero-based offsets of the first and last bytes to copy",
nfe);
}
}