Skip to content

Commit

Permalink
mpm-ac: fix integer overflow on allocation
Browse files Browse the repository at this point in the history
The size of a memory buffer to be allocated was kept in a signed int
instead of a size_t, leading to an overflow when large lists of long
and diverse patterns cause the amount of AC states to blow up (>2GB).
Fixes Redmine issues #1827 and #1843.

Signed-off-by: Sascha Steinbiss <sascha@steinbiss.name>
  • Loading branch information
satta authored and victorjulien committed Feb 8, 2017
1 parent b25b067 commit 5e96977
Showing 1 changed file with 36 additions and 10 deletions.
46 changes: 36 additions & 10 deletions src/util-mpm-ac.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,28 @@ static void SCACGetConfig()
return;
}

/**
* \internal
* \brief Check if size_t multiplication would overflow and perform operation
* if safe. In case of an overflow we exit().
*
* \param a First size_t value to multiplicate.
* \param b Second size_t value to multiplicate.
*
* \retval The product of a and b, guaranteed to not overflow.
*/
static inline size_t SCACCheckSafeSizetMult(size_t a, size_t b)
{
/* check for safety of multiplication operation */
if (b > 0 && a > SIZE_MAX / b) {
SCLogError(SC_ERR_MEM_ALLOC, "%"PRIuMAX" * %"PRIuMAX" > %"
PRIuMAX" would overflow size_t calculating buffer size",
(uintmax_t) a, (uintmax_t) b, (uintmax_t) SIZE_MAX);
exit(EXIT_FAILURE);
}
return a * b;
}

/**
* \internal
* \brief Initialize a new state in the goto and output tables.
Expand All @@ -130,12 +152,13 @@ static void SCACGetConfig()
*/
static inline int SCACReallocState(SCACCtx *ctx, uint32_t cnt)
{
void *ptmp;
int size = 0;
void *ptmp = NULL;
size_t size = 0;

/* reallocate space in the goto table to include a new state */
size = cnt * ctx->single_state_size;
ptmp = SCRealloc(ctx->goto_table, size);
size = SCACCheckSafeSizetMult((size_t) cnt, (size_t) ctx->single_state_size);
if (size > 0)
ptmp = SCRealloc(ctx->goto_table, size);
if (ptmp == NULL) {
SCFree(ctx->goto_table);
ctx->goto_table = NULL;
Expand All @@ -145,12 +168,15 @@ static inline int SCACReallocState(SCACCtx *ctx, uint32_t cnt)
ctx->goto_table = ptmp;

/* reallocate space in the output table for the new state */
int oldsize = ctx->state_count * sizeof(SCACOutputTable);
size = cnt * sizeof(SCACOutputTable);
SCLogDebug("oldsize %d size %d cnt %u ctx->state_count %u",
oldsize, size, cnt, ctx->state_count);

ptmp = SCRealloc(ctx->output_table, size);
size_t oldsize = SCACCheckSafeSizetMult((size_t) ctx->state_count,
sizeof(SCACOutputTable));
size = SCACCheckSafeSizetMult((size_t) cnt, sizeof(SCACOutputTable));
SCLogDebug("oldsize %"PRIuMAX" size %"PRIuMAX" cnt %d ctx->state_count %u",
(uintmax_t) oldsize, (uintmax_t) size, cnt, ctx->state_count);

ptmp = NULL;
if (size > 0)
ptmp = SCRealloc(ctx->output_table, size);
if (ptmp == NULL) {
SCFree(ctx->output_table);
ctx->output_table = NULL;
Expand Down

0 comments on commit 5e96977

Please sign in to comment.