Skip to content
Permalink
Browse files
Fix memory bug in SnappyNifSink::Append
Previously `SnappyNifSink` assumed that `GetAppendBuffer` was always
called before `Append`. This turned out to be an invalid assumption.
This was definitely in the land of "How did that even work?". The simple
fix is simple.

This also pre-allocates the write buffer to 8192 bytes which just saves
us from the initial re-allocation on first `Append` since we allocated a
zero length buffer initially.
  • Loading branch information
davisp committed Oct 16, 2018
1 parent 60572a1 commit 2038ad13b1d6926468f25adea110028e3c0b4b0c
Showing 1 changed file with 19 additions and 10 deletions.
@@ -43,6 +43,8 @@ class SnappyNifSink : public snappy::Sink
ErlNifBinary& GetBin();

private:
void EnsureSize(size_t append_length);

ErlNifEnv* env;
ErlNifBinary bin;
size_t length;
@@ -67,6 +69,7 @@ void
SnappyNifSink::Append(const char *data, size_t n)
{
if(data != (SC_PTR(bin.data) + length)) {
EnsureSize(n);
memcpy(bin.data + length, data, n);
}
length += n;
@@ -75,16 +78,7 @@ SnappyNifSink::Append(const char *data, size_t n)
char*
SnappyNifSink::GetAppendBuffer(size_t len, char* scratch)
{
size_t sz;

if((length + len) > bin.size) {
sz = (len * 4) < 8192 ? 8192 : (len * 4);

if(!enif_realloc_binary_compat(env, &bin, bin.size + sz)) {
throw std::bad_alloc();
}
}

EnsureSize(len);
return SC_PTR(bin.data) + length;
}

@@ -100,6 +94,21 @@ SnappyNifSink::GetBin()
}


void
SnappyNifSink::EnsureSize(size_t append_length)
{
if((length + append_length) > bin.size) {
size_t sz = append_length * 4;
if(sz < 8192) {
sz = 8192;
}

if(!enif_realloc_binary_compat(env, &bin, bin.size + sz)) {
throw std::bad_alloc();
}
}
}

static inline ERL_NIF_TERM
make_atom(ErlNifEnv* env, const char* name)
{

0 comments on commit 2038ad1

Please sign in to comment.