Skip to content
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
36 changes: 25 additions & 11 deletions plugins/s3_auth/aws_auth_v4.cc
Original file line number Diff line number Diff line change
Expand Up @@ -168,18 +168,19 @@ canonicalEncode(const String &in, bool isObjectName)
}

/**
* @brief trim the white-space character from the beginning and the end of the string ("in-place", just moving pointers around)
* @brief Trim white spaces from beginning and end. Squeeze consecutive spaces from middle.
*
* @see AWS spec: https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
*
* @param in ptr to an input string
* @param inLen input character count
* @param newLen trimmed string character count.
* @return pointer to the trimmed string.
*/
const char *
trimWhiteSpaces(const char *in, size_t inLen, size_t &newLen)
std::string
trimWhiteSpacesAndSqueezeInnerSpaces(const char *in, size_t inLen)
{
if (nullptr == in || inLen == 0) {
return in;
return std::string(in, inLen);
}

const char *first = in;
Expand All @@ -192,8 +193,22 @@ trimWhiteSpaces(const char *in, size_t inLen, size_t &newLen)
last--;
}

newLen = last - first + 1;
return first;
std::stringstream result;
int consecutiveSpaces = 0;
while (first <= last) {
if (*first == ' ') {
consecutiveSpaces++;
} else {
if (consecutiveSpaces > 0) {
result << ' ';
}
consecutiveSpaces = 0;
result << *first;
}
first++;
}

return result.str();
}

/**
Expand Down Expand Up @@ -381,14 +396,13 @@ getCanonicalRequestSha256Hash(TsInterface &api, bool signPayload, const StringSe
}
}

size_t trimValueLen = 0;
const char *trimValue = trimWhiteSpaces(value, valueLen, trimValueLen);
std::string trimValue = trimWhiteSpacesAndSqueezeInnerSpaces(value, valueLen);

signedHeadersSet.insert(lowercaseName);
if (headersMap.find(lowercaseName) == headersMap.end()) {
headersMap[lowercaseName] = String(trimValue, trimValueLen);
headersMap[lowercaseName] = trimValue;
} else {
headersMap[lowercaseName].append(",").append(String(trimValue, trimValueLen));
headersMap[lowercaseName].append(",").append(trimValue);
}
}

Expand Down
86 changes: 58 additions & 28 deletions plugins/s3_auth/unit_tests/test_aws_auth_v4.cc
Original file line number Diff line number Diff line change
Expand Up @@ -172,74 +172,104 @@ TEST_CASE("base16Encode(): base16 encode RFC4648 test vectors", "[utility]")

/* trimWhiteSpaces() ******************************************************************************************************** */

TEST_CASE("trimWhiteSpaces(): trim invalid arguments, check pointers", "[utility]")
TEST_CASE("trimWhiteSpacesAndSqueezeInnerSpaces(): trim invalid arguments, check string", "[utility]")
{
const char *in = nullptr;
size_t inLen = 0;
size_t outLen = 0;

const char *start = trimWhiteSpaces(in, inLen, outLen);
const std::string trimmed = trimWhiteSpacesAndSqueezeInnerSpaces(in, inLen);

CHECK(in == start);
CHECK_FALSE(trimmed.compare(""));
CHECK(inLen == trimmed.length());
}

TEST_CASE("trimWhiteSpaces(): trim empty input, check pointers", "[utility]")
TEST_CASE("trimWhiteSpacesAndSqueezeInnerSpaces(): trim empty input, check string", "[utility]")
{
const char *in = "";
size_t inLen = 0;
size_t outLen = 0;

const char *start = trimWhiteSpaces(in, inLen, outLen);
const std::string trimmed = trimWhiteSpacesAndSqueezeInnerSpaces(in, inLen);

CHECK(in == start);
CHECK_FALSE(trimmed.compare(""));
CHECK(inLen == trimmed.length());
}

TEST_CASE("trimWhiteSpaces(): trim nothing to trim, check pointers", "[utility]")
TEST_CASE("trimWhiteSpacesAndSqueezeInnerSpaces(): trim nothing to trim, check string", "[utility]")
{
const char in[] = "Important Message";
size_t inLen = strlen(in);
size_t newLen = 0;

const char *start = trimWhiteSpaces(in, inLen, newLen);
const std::string trimmed = trimWhiteSpacesAndSqueezeInnerSpaces(in, inLen);

CHECK(in == start);
CHECK(inLen == newLen);
CHECK_FALSE(trimmed.compare("Important Message"));
CHECK(inLen == trimmed.length());
}

TEST_CASE("trimWhiteSpaces(): trim beginning, check pointers", "[utility]")
TEST_CASE("trimWhiteSpacesAndSqueezeInnerSpaces(): trim beginning, check string", "[utility]")
{
const char in[] = " \t\nImportant Message";
size_t inLen = strlen(in);
size_t newLen = 0;

const char *start = trimWhiteSpaces(in, inLen, newLen);
const std::string trimmed = trimWhiteSpacesAndSqueezeInnerSpaces(in, inLen);

CHECK(in + 3 == start);
CHECK(inLen - 3 == newLen);
CHECK_FALSE(trimmed.compare("Important Message"));
CHECK(inLen - 3 == trimmed.length());
}

TEST_CASE("trimWhiteSpaces(): trim end, check pointers", "[utility]")
TEST_CASE("trimWhiteSpacesAndSqueezeInnerSpaces(): trim end, check string", "[utility]")
{
const char in[] = "Important Message \t\n";
size_t inLen = strlen(in);
size_t newLen = 0;

const char *start = trimWhiteSpaces(in, inLen, newLen);
const std::string trimmed = trimWhiteSpacesAndSqueezeInnerSpaces(in, inLen);

CHECK(in == start);
CHECK(inLen - 3 == newLen);
CHECK_FALSE(trimmed.compare("Important Message"));
CHECK(inLen - 3 == trimmed.length());
}

TEST_CASE("trimWhiteSpaces(): trim both ends, check pointers", "[utility]")
TEST_CASE("trimWhiteSpacesAndSqueezeInnerSpaces(): trim both ends, check string", "[utility]")
{
const char in[] = "\v\t\n Important Message \t\n";
size_t inLen = strlen(in);
size_t newLen = 0;

const char *start = trimWhiteSpaces(in, inLen, newLen);
const std::string trimmed = trimWhiteSpacesAndSqueezeInnerSpaces(in, inLen);

CHECK_FALSE(trimmed.compare("Important Message"));
CHECK(inLen - 7 == trimmed.length());
}

TEST_CASE("trimWhiteSpacesAndSqueezeInnerSpaces(): trim both ends and squeeze middle spaces, check string", "[utility]")
{
const char in[] = "\v\t\n Important Message \t\n";
size_t inLen = strlen(in);

const std::string trimmed = trimWhiteSpacesAndSqueezeInnerSpaces(in, inLen);

CHECK_FALSE(trimmed.compare("Important Message"));
CHECK(inLen - 11 == trimmed.length());
}

TEST_CASE("trimWhiteSpacesAndSqueezeInnerSpaces(): squeeze middle spaces multiple groups, check string", "[utility]")
{
const char in[] = "Very Important Message";
size_t inLen = strlen(in);

const std::string trimmed = trimWhiteSpacesAndSqueezeInnerSpaces(in, inLen);

CHECK_FALSE(trimmed.compare("Very Important Message"));
CHECK(inLen - 6 == trimmed.length());
}

TEST_CASE("trimWhiteSpacesAndSqueezeInnerSpaces(): does not squeeze middle whitespaces different from spaces, check string",
"[utility]")
{
const char in[] = "Very \t\tImportant \t\t\tMessage";
size_t inLen = strlen(in);

const std::string trimmed = trimWhiteSpacesAndSqueezeInnerSpaces(in, inLen);

CHECK(in + 4 == start);
CHECK(inLen - 7 == newLen);
CHECK_FALSE(trimmed.compare("Very \t\tImportant \t\t\tMessage"));
CHECK(inLen == trimmed.length());
}

TEST_CASE("trimWhiteSpaces(): trim both, check string", "[utility]")
Expand Down
2 changes: 1 addition & 1 deletion plugins/s3_auth/unit_tests/test_aws_auth_v4.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ String base16Encode(const char *in, size_t inLen);
String uriEncode(const String &in, bool isObjectName = false);
bool isUriEncoded(const String &in, bool isObjectName = false);
String lowercase(const char *in, size_t inLen);
const char *trimWhiteSpaces(const char *in, size_t inLen, size_t &newLen);
String trimWhiteSpacesAndSqueezeInnerSpaces(const char *in, size_t inLen);

String getCanonicalRequestSha256Hash(TsInterface &api, bool signPayload, const StringSet &includeHeaders,
const StringSet &excludeHeaders, String &signedHeaders);
Expand Down