diff --git a/lib/core-net/lws-dsh.c b/lib/core-net/lws-dsh.c index 3391b1c85..c641f79d0 100644 --- a/lib/core-net/lws-dsh.c +++ b/lib/core-net/lws-dsh.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2021 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -60,6 +60,7 @@ lws_dsh_create(lws_dll2_owner_t *owner, size_t buf_len, int count_kinds) assert(buf_len); assert(count_kinds > 1); assert(buf_len > sizeof(lws_dsh_t) + oha_len); + buf_len += 64; dsh = lws_malloc(sizeof(lws_dsh_t) + buf_len + oha_len, __func__); if (!dsh) @@ -76,8 +77,10 @@ lws_dsh_create(lws_dll2_owner_t *owner, size_t buf_len, int count_kinds) /* clear down the obj heads array */ memset(dsh->oha, 0, oha_len); - for (n = 0; n < count_kinds; n++) + for (n = 0; n < count_kinds; n++) { dsh->oha[n].kind = n; + dsh->oha[n].total_size = 0; + } /* initially the whole buffer is on the free kind (0) list */ @@ -296,6 +299,7 @@ _lws_dsh_alloc_tail(lws_dsh_t *dsh, int kind, const void *src1, size_t size1, */ lws_dll2_remove(&s.best->list); s.best->dsh = s.dsh; + s.best->kind = kind; s.best->size = size1 + size2; memcpy(&s.best[1], src1, size1); if (src2) @@ -310,12 +314,15 @@ _lws_dsh_alloc_tail(lws_dsh_t *dsh, int kind, const void *src1, size_t size1, if (replace->next) replace->next->prev = &s.best->list; } else - if (dsh) + if (dsh) { + assert(!(((unsigned long)(intptr_t)(s.best)) & (sizeof(int *) - 1))); lws_dll2_add_tail(&s.best->list, &dsh->oha[kind].owner); + } assert(s.dsh->locally_free >= s.best->asize); s.dsh->locally_free -= s.best->asize; s.dsh->locally_in_use += s.best->asize; + dsh->oha[kind].total_size += s.best->asize; assert(s.dsh->locally_in_use <= s.dsh->buffer_size); } else { lws_dsh_obj_t *obj; @@ -334,10 +341,11 @@ _lws_dsh_alloc_tail(lws_dsh_t *dsh, int kind, const void *src1, size_t size1, /* latter part becomes new object */ - obj = (lws_dsh_obj_t *)(((uint8_t *)s.best) + s.best->asize); + obj = (lws_dsh_obj_t *)(((uint8_t *)s.best) + lws_dsh_align(s.best->asize)); lws_dll2_clear(&obj->list); obj->dsh = s.dsh; + obj->kind = kind; obj->size = size1 + size2; obj->asize = asize; @@ -354,12 +362,15 @@ _lws_dsh_alloc_tail(lws_dsh_t *dsh, int kind, const void *src1, size_t size1, if (replace->next) replace->next->prev = &s.best->list; } else - if (dsh) + if (dsh) { + assert(!(((unsigned long)(intptr_t)(obj)) & (sizeof(int *) - 1))); lws_dll2_add_tail(&obj->list, &dsh->oha[kind].owner); + } assert(s.dsh->locally_free >= asize); s.dsh->locally_free -= asize; s.dsh->locally_in_use += asize; + dsh->oha[kind].total_size += asize; assert(s.dsh->locally_in_use <= s.dsh->buffer_size); } @@ -402,6 +413,7 @@ lws_dsh_free(void **pobj) assert(dsh->locally_in_use >= _o->asize); dsh->locally_free += _o->asize; dsh->locally_in_use -= _o->asize; + dsh->oha[_o->kind].total_size -= _o->asize; /* account for usage by kind */ assert(dsh->locally_in_use <= dsh->buffer_size); /* @@ -469,7 +481,7 @@ lws_dsh_get_head(lws_dsh_t *dsh, int kind, void **obj, size_t *size) *size = _obj->size; /* anything coming out of here must be aligned */ - assert(!(((unsigned long)(*obj)) & (sizeof(int *) - 1))); + assert(!(((unsigned long)(intptr_t)(*obj)) & (sizeof(int *) - 1))); return 0; /* we returned the head */ } diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 9cbb0c2bb..eac480352 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -270,6 +270,7 @@ struct lws_timed_vh_protocol { typedef struct lws_dsh_obj_head { lws_dll2_owner_t owner; + size_t total_size; /* for this kind in dsh */ int kind; } lws_dsh_obj_head_t; @@ -278,6 +279,7 @@ typedef struct lws_dsh_obj { struct lws_dsh *dsh; /* invalid when on free list */ size_t size; /* invalid when on free list */ size_t asize; + int kind; /* so we can account at free */ } lws_dsh_obj_t; typedef struct lws_dsh {