Subject: Re: [Boost-bugs] [Boost C++ Libraries] #5629: base64 encode/decode for std::istreambuf_iterator/std::ostreambuf_iterator
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2012-12-14 14:51:08
#5629: base64 encode/decode for std::istreambuf_iterator/std::ostreambuf_iterator
--------------------------------+-------------------------------------------
Reporter: nen777w@⦠| Owner: ramey
Type: Bugs | Status: assigned
Milestone: To Be Determined | Component: serialization
Version: Boost 1.45.0 | Severity: Problem
Resolution: | Keywords:
--------------------------------+-------------------------------------------
Comment (by iGene):
The root cause is that sequences whose size doesn't divide by four get a
buffer overrun.
Here is my workaround.
{{{
#include <sstream>
#include <cassert>
struct to_base64 : public std::stringstream {
to_base64(const std::string& str);
to_base64(const char* begin, const char* end);
};
struct from_base64 : public std::stringstream {
from_base64(const std::string& str);
from_base64(const char* begin, const char* end);
};
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/archive/iterators/ostream_iterator.hpp>
// slightly generalized version of the example here:
// http://stackoverflow.com/questions/7053538/how-do-i-encode-a-string-to-
base64-using-only-boost
template <typename TransformIterator>
static void apply(const char* begin, const char* end, std::stringstream&
target) {
std::copy(TransformIterator(begin), TransformIterator(end),
std::ostreambuf_iterator<char>(target));
}
template <typename TransformIterator>
static void applyTwice(const char* begin, const char* end,
std::stringstream& target) {
long size = end - begin;
int remainder = size % 4;
const char* truncated = end - remainder;
apply<TransformIterator>(begin, truncated, target);
if (remainder) {
assert(remainder != 1); /* it can never be =1 if this
whole thing about dividing by four is correct */
char padded[4] = { 'A', 'A', 'A', 'A' };
const char* src = truncated;
char* dest = &padded[0];
while (src != end)
*(dest++) = *(src++);
apply<TransformIterator>(&padded[0],
&padded[sizeof(padded)], target);
std::ios::streampos pos = target.tellp();
pos -= (4 - remainder);
target.seekp(pos);
}
}
using namespace boost::archive::iterators;
typedef base64_from_binary<transform_width<const char*, 6, 8> > to;
to_base64::to_base64(const char* begin, const char* end) {
apply<to>(begin, end, *this); }
to_base64::to_base64(const std::string& str) { apply<to>(str.c_str(),
str.c_str() + str.length(), *this); }
typedef transform_width<binary_from_base64<const char*>, 8, 6> from;
from_base64::from_base64(const char* begin, const char* end) {
applyTwice<from>(begin, end, *this); }
from_base64::from_base64(const std::string& str) {
applyTwice<from>(str.c_str(), str.c_str() + str.length(), *this); }
int main()
{
size_t length = 0;
do {
// generate source bytes
char source[RAND_MAX + 1];
for (size_t pos = 0; pos < length; ++pos)
source[pos] = '0' + char(rand() % 32);
source[length] = '\0';
// convert them to base64
to_base64 b(&source[0], &source[length]);
std::string b64 = b.str();
// and convert them back
from_base64 result(b64.c_str(), b64.c_str() + b64.size());
// compare as binary
size_t size = (size_t)result.tellp();
assert(size == length);
char dest[RAND_MAX];
result.read(&dest[0], size);
for (size_t pos = 0; pos < length; ++pos)
assert(source[pos] == dest[pos]);
// compare as text
std::string asString = result.str();
assert(!strcmp(asString.c_str(), &source[0]));
} while (++length < 100);
return 0;
}
}}}
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/5629#comment:7> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.
This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:11 UTC