diff --git a/src/output-json.c b/src/output-json.c index 1d9f8b214692..00d99fc6972c 100644 --- a/src/output-json.c +++ b/src/output-json.c @@ -987,8 +987,23 @@ int OutputJsonBuilderBuffer(JsonBuilder *js, OutputJsonThreadCtx *ctx) } size_t jslen = jb_len(js); - if (MEMBUFFER_OFFSET(*buffer) + jslen >= MEMBUFFER_SIZE(*buffer)) { - MemBufferExpand(buffer, jslen); + DEBUG_VALIDATE_BUG_ON(jb_len(js) > UINT32_MAX); + size_t remaining = MEMBUFFER_SIZE(*buffer) - MEMBUFFER_OFFSET(*buffer); + if (jslen >= remaining) { + size_t expand_by = jslen + 1 - remaining; + if (MemBufferExpand(buffer, (uint32_t)expand_by) < 0) { + if (!ctx->too_large_warning) { + /* Log a warning once, and include enough of the log + * message to hopefully identify the event_type. */ + char partial[120]; + size_t partial_len = MIN(sizeof(partial), jslen); + memcpy(partial, jb_ptr(js), partial_len - 1); + partial[partial_len - 1] = '\0'; + SCLogWarning("Formatted JSON EVE record too large, will be dropped: %s", partial); + ctx->too_large_warning = true; + } + return 0; + } } MemBufferWriteRaw((*buffer), jb_ptr(js), jslen); diff --git a/src/output-json.h b/src/output-json.h index 74d07bb8a2c8..dca6e88e700a 100644 --- a/src/output-json.h +++ b/src/output-json.h @@ -90,6 +90,7 @@ typedef struct OutputJsonThreadCtx_ { OutputJsonCtx *ctx; LogFileCtx *file_ctx; MemBuffer *buffer; + bool too_large_warning; } OutputJsonThreadCtx; json_t *SCJsonString(const char *val); diff --git a/src/util-buffer.c b/src/util-buffer.c index 05b365825818..cfc190087ee7 100644 --- a/src/util-buffer.c +++ b/src/util-buffer.c @@ -65,6 +65,11 @@ int MemBufferExpand(MemBuffer **buffer, uint32_t expand_by) { return -1; } + /* Adjust expand_by to next multiple of 4k. */ + if (expand_by % 4096 != 0) { + expand_by = expand_by - (expand_by % 4096) + 4096; + } + size_t total_size = (*buffer)->size + sizeof(MemBuffer) + expand_by; MemBuffer *tbuffer = SCRealloc(*buffer, total_size);