From dd75c914030e394ff4b8dbb326a6d486d7042356 Mon Sep 17 00:00:00 2001 From: TennesseeTrash Date: Mon, 9 Jun 2025 01:42:12 +0200 Subject: [PATCH] [Base64] Add validation --- Garbage/Include/Garbage/Base64.hpp | 27 +++++++++++++++++++++++++++ Tests/Base64/Tests.cpp | 11 +++++++++++ 2 files changed, 38 insertions(+) diff --git a/Garbage/Include/Garbage/Base64.hpp b/Garbage/Include/Garbage/Base64.hpp index e7536e8..9eea07f 100644 --- a/Garbage/Include/Garbage/Base64.hpp +++ b/Garbage/Include/Garbage/Base64.hpp @@ -138,6 +138,33 @@ namespace Garbage::Base64 return result; } + + [[nodiscard]] constexpr + bool Validate(std::string_view data) + { + // Technically superfluous - the decoder can deal with unpadded data. + if (data.size() % 4 != 0) { + return false; + } + + std::size_t i = 0; + for (char ch : data) { + bool condition = (ch == '+') || + (ch >= '/' && ch <= '9') || + (ch >= 'A' && ch <= 'Z') || + (ch >= 'a' && ch <= 'z'); + if (!condition) { + // Allow '=' for the last two character + if (i >= data.size() - 2 && ch == '=') { + continue; + } + return false; + } + ++i; + } + + return true; + } } #endif // GARBAGE_BASE64_HPP diff --git a/Tests/Base64/Tests.cpp b/Tests/Base64/Tests.cpp index 67a6784..bb940eb 100644 --- a/Tests/Base64/Tests.cpp +++ b/Tests/Base64/Tests.cpp @@ -10,6 +10,8 @@ TEST_CASE("Base64 encoding/decoding tests") std::string encoded = Garbage::Base64::Encode(data); REQUIRE(encoded.size() == 0); + REQUIRE(Garbage::Base64::Validate(encoded)); + std::vector decoded = Garbage::Base64::Decode(encoded); REQUIRE(encoded.size() == 0); } @@ -21,12 +23,15 @@ TEST_CASE("Base64 encoding/decoding tests") std::string encoded = Garbage::Base64::Encode(data); REQUIRE(encoded == "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu"); + REQUIRE(Garbage::Base64::Validate(encoded)); } SECTION("Decoding short data") { std::string data("TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu"); + REQUIRE(Garbage::Base64::Validate(data)); + std::vector decoded = Garbage::Base64::Decode(data); std::string destination(decoded.begin(), decoded.end()); REQUIRE(destination == "Many hands make light work."); @@ -39,12 +44,15 @@ TEST_CASE("Base64 encoding/decoding tests") std::string encoded = Garbage::Base64::Encode(data); REQUIRE(encoded == "V2l0aCBhIHBhZGRpbmc="); + REQUIRE(Garbage::Base64::Validate(encoded)); } SECTION("Decoding with a padding char") { std::string data("V2l0aCBhIHBhZGRpbmc="); + REQUIRE(Garbage::Base64::Validate(data)); + std::vector decoded = Garbage::Base64::Decode(data); std::string destination(decoded.begin(), decoded.end()); REQUIRE(destination == "With a padding"); @@ -57,12 +65,15 @@ TEST_CASE("Base64 encoding/decoding tests") std::string encoded = Garbage::Base64::Encode(data); REQUIRE(encoded == "V2l0aCB0d28gcGFkZGluZw=="); + REQUIRE(Garbage::Base64::Validate(encoded)); } SECTION("Decoding with two padding chars") { std::string data("V2l0aCB0d28gcGFkZGluZw=="); + REQUIRE(Garbage::Base64::Validate(data)); + std::vector decoded = Garbage::Base64::Decode(data); std::string destination(decoded.begin(), decoded.end()); REQUIRE(destination == "With two padding");