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.
diff --git a/c_src/snappy_nif.cc b/c_src/snappy_nif.cc
index 0cec923..50e9018 100644
--- a/c_src/snappy_nif.cc
+++ b/c_src/snappy_nif.cc
@@ -43,6 +43,8 @@
ErlNifBinary& GetBin();
private:
+ void EnsureSize(size_t append_length);
+
ErlNifEnv* env;
ErlNifBinary bin;
size_t length;
@@ -67,6 +69,7 @@
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 @@
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 @@
}
+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)
{