Skip to content

Commit

Permalink
libs/libc/obstack: fix allocated chunk overrun due to invalid limit
Browse files Browse the repository at this point in the history
This primarily fixes allocated memory overrun due to invalidly
calculated limit of the chunk. The function here allocates chunk of size
that includes required header. The error was that size of the chunk was
invalidly again added when limit was being calculated. This was causing
memory overrun and issues especially with object growing (reallocation).

The secondary fix here is to the algorithm that rounds the required size
to the multiple of chunk size. In short chunk size must be reduced by
one to get the correct mask. The condition that was generating the mask
was also invalid because it must perform shift with at most one less
than number of bits (not bytes).
  • Loading branch information
Cynerd authored and acassis committed Oct 30, 2024
1 parent 36b891c commit b851916
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 8 deletions.
2 changes: 1 addition & 1 deletion include/obstack.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ void obstack_free(FAR struct obstack *h, FAR void *object);
* size: number of bytes to be free for growth
*
* Assumptions/Limitations:
* The obstack's chunk_size is expected to be power of two. This helps to
* The obstack's chunk_size is rounded up to be power of two. This helps to
* eliminate division that might not be implemented in the HW and thus
* inefficient.
*
Expand Down
20 changes: 13 additions & 7 deletions libs/libc/obstack/lib_obstack_make_room.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include <obstack.h>
#include <assert.h>
#include <string.h>
#include <sys/param.h>
#include <syslog.h>
#include "lib_obstack_malloc.h"

/****************************************************************************
Expand All @@ -47,7 +49,7 @@
* size: number of bytes to be free for growth
*
* Assumptions/Limitations:
* The obstack's chunk_size is expected to be power of two. This helps to
* The obstack's chunk_size is rounded up to be power of two. This helps to
* eliminate division that might not be implemented in the HW and thus
* inefficient.
*
Expand All @@ -69,13 +71,18 @@ void obstack_make_room(FAR struct obstack *h, size_t size)

size += object_size + sizeof(struct _obstack_chunk);

/* Note: this is rounding up to the multiple of chunk size that is power of
* two. Thus this creates limitation that chunks can be only power of two.
/* Note: this is rounding up to the multiple of chunk size that is rounded
* up to the power of two.
*/

mask = h->chunk_size;
for (i = 1; i < sizeof(size_t); i <<= 1)
DEBUGASSERT(h->chunk_size > 0);
mask = h->chunk_size - 1;

for (i = 1; i < sizeof(size_t) * 8; i <<= 1)
{
mask |= mask >> i;
}

size = (size + mask) & ~mask;

if (h->chunk == NULL ||
Expand All @@ -100,8 +107,7 @@ void obstack_make_room(FAR struct obstack *h, size_t size)
h->chunk = lib_obstack_realloc(h->chunk, size);
}

h->chunk->limit =
(FAR char *)h->chunk + sizeof(struct _obstack_chunk) + size;
h->chunk->limit = (FAR char *)h->chunk + size;
h->object_base = (FAR char *)h->chunk + sizeof(struct _obstack_chunk);
h->next_free = h->object_base + object_size;
}

0 comments on commit b851916

Please sign in to comment.