This is an automated email from the ASF dual-hosted git repository. nickva pushed a commit to tag 1.1.5 in repository https://gitbox.apache.org/repos/asf/couchdb-jiffy.git
commit e140b344a62653f9686d4772810da34bf6b0d5b1 Author: Nick Vatamaniuc <[email protected]> AuthorDate: Fri Jun 12 18:00:05 2026 -0400 Fix unitialized var access on allocation failure Fix two places where we didn't handle allocation failures. While `enif_alloc_resource()` blows up on allocation failure, `enif_alloc()` and `enif_alloc_binary()` don't. During encoder and decoder resource creation if small (a few KB) mallocs fail we could end up calling the resource destructor with some uninitalized flags like `have_buffer`. To prevent this class of errors in the future opt to memset the encoder and decoder structure so new fields in the future are by default 0-initialized. Thanks to @qzhuyan (William) in https://github.com/davisp/jiffy/pull/296 for pointing this issue out and providing a fix. --- c_src/decoder.c | 19 +++++++++---------- c_src/encoder.c | 16 ++++------------ 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/c_src/decoder.c b/c_src/decoder.c index 27d101a..01d0215 100644 --- a/c_src/decoder.c +++ b/c_src/decoder.c @@ -66,6 +66,7 @@ typedef struct { int st_top; } Decoder; +// Returns an allocated resource or NULL on allocation failure Decoder* dec_new(ErlNifEnv* env) { @@ -77,23 +78,21 @@ dec_new(ErlNifEnv* env) return NULL; } - d->atoms = st; + // Zero everything and only set non-0 fields + memset(d, 0, sizeof(*d)); + d->atoms = st; d->bytes_per_red = DEFAULT_BYTES_PER_REDUCTION; - d->is_partial = 0; - d->return_maps = 0; - d->return_trailer = 0; - d->dedupe_keys = 0; - d->copy_strings = 0; d->null_term = d->atoms->atom_null; - - d->p = NULL; d->len = -1; - d->i = 0; d->st_data = (char*) enif_alloc(STACK_SIZE_INC); + if(d->st_data == NULL) { + enif_release_resource(d); + return NULL; + } + d->st_size = STACK_SIZE_INC; - d->st_top = 0; for(i = 0; i < d->st_size; i++) { d->st_data[i] = st_invalid; diff --git a/c_src/encoder.c b/c_src/encoder.c index 03c5500..2ec0dd8 100644 --- a/c_src/encoder.c +++ b/c_src/encoder.c @@ -72,29 +72,21 @@ enc_new(ErlNifEnv* env) jiffy_st* st = (jiffy_st*) enif_priv_data(env); Encoder* e = enif_alloc_resource(st->res_enc, sizeof(Encoder)); + // Zero everything so enc_destroy() never sees an uninitialized + // have_buffer if we bail out before the encoder is fully built + memset(e, 0, sizeof(*e)); + e->atoms = st; e->bytes_per_red = DEFAULT_BYTES_PER_REDUCTION; - e->uescape = 0; - e->pretty = 0; - e->use_nil = 0; - e->escape_forward_slashes = 0; - e->shiftcnt = 0; - e->count = 0; - - e->iosize = 0; e->iolist = enif_make_list(env, 0); - e->partial_output = 0; - if(!enif_alloc_binary(BIN_INC_SIZE, &e->buffer)) { enif_release_resource(e); return NULL; } e->have_buffer = 1; - e->p = e->buffer.data; - e->i = 0; return e; }
