diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2019-05-22 00:10:35 +0200 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2019-05-25 10:01:17 +0200 |
commit | a9d7ec4587d8eb20f12ebecc427ad818fb0e4971 (patch) | |
tree | 4a3ec8787e9dae501ea2c1430c13c174f289ac4b | |
parent | 4769deb36a54c3b2a4a2d2addb2937c1aa7dd629 (diff) | |
download | rneovim-a9d7ec4587d8eb20f12ebecc427ad818fb0e4971.tar.gz rneovim-a9d7ec4587d8eb20f12ebecc427ad818fb0e4971.tar.bz2 rneovim-a9d7ec4587d8eb20f12ebecc427ad818fb0e4971.zip |
refactor: introduce XFREE_CLEAR()
Unfortunately we cannot indiscriminately replace xfree() with
XFREE_CLEAR(), because comparing pointers after freeing them is a common
pattern. Example in `tv_list_remove_items()`:
xfree(li);
if (li == item2) {
break;
}
Instead we can do it selectively/explicitly.
ref #1375
-rw-r--r-- | src/nvim/lib/kbtree.h | 14 | ||||
-rw-r--r-- | src/nvim/lib/khash.h | 2 | ||||
-rw-r--r-- | src/nvim/lib/klist.h | 6 | ||||
-rw-r--r-- | src/nvim/lib/kvec.h | 6 | ||||
-rw-r--r-- | src/nvim/lib/ringbuf.h | 4 | ||||
-rw-r--r-- | src/nvim/memory.c | 2 | ||||
-rw-r--r-- | src/nvim/memory.h | 11 | ||||
-rw-r--r-- | test/functional/autocmd/autocmd_spec.lua | 8 |
8 files changed, 33 insertions, 20 deletions
diff --git a/src/nvim/lib/kbtree.h b/src/nvim/lib/kbtree.h index 704aa26010..33aeff1d89 100644 --- a/src/nvim/lib/kbtree.h +++ b/src/nvim/lib/kbtree.h @@ -72,7 +72,7 @@ *top++ = (b)->root; \ while (top != stack) { \ x = *--top; \ - if (x->is_internal == 0) { xfree(x); continue; } \ + if (x->is_internal == 0) { XFREE_CLEAR(x); continue; } \ for (i = 0; i <= x->n; ++i) \ if (__KB_PTR(b, x)[i]) { \ if (top - stack == (int)max) { \ @@ -82,10 +82,10 @@ } \ *top++ = __KB_PTR(b, x)[i]; \ } \ - xfree(x); \ + XFREE_CLEAR(x); \ } \ } \ - xfree(stack); \ + XFREE_CLEAR(stack); \ } while (0) #define __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \ @@ -253,7 +253,7 @@ memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, x)[i + 1], (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ memmove(&__KB_PTR(b, x)[i + 1], &__KB_PTR(b, x)[i + 2], (unsigned int)(x->n - i - 1) * sizeof(void*)); \ --x->n; \ - xfree(z); \ + XFREE_CLEAR(z); \ return __kb_delp_aux_##name(b, y, k, s); \ } \ } \ @@ -281,7 +281,7 @@ memmove(&__KB_KEY(key_t, x)[i - 1], &__KB_KEY(key_t, x)[i], (unsigned int)(x->n - i) * sizeof(key_t)); \ memmove(&__KB_PTR(b, x)[i], &__KB_PTR(b, x)[i + 1], (unsigned int)(x->n - i) * sizeof(void*)); \ --x->n; \ - xfree(xp); \ + XFREE_CLEAR(xp); \ xp = y; \ } else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n == T - 1) { \ __KB_KEY(key_t, xp)[xp->n++] = __KB_KEY(key_t, x)[i]; \ @@ -291,7 +291,7 @@ memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, x)[i + 1], (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ memmove(&__KB_PTR(b, x)[i + 1], &__KB_PTR(b, x)[i + 2], (unsigned int)(x->n - i - 1) * sizeof(void*)); \ --x->n; \ - xfree(y); \ + XFREE_CLEAR(y); \ } \ } \ return __kb_delp_aux_##name(b, xp, k, s); \ @@ -306,7 +306,7 @@ --b->n_nodes; \ x = b->root; \ b->root = __KB_PTR(b, x)[0]; \ - xfree(x); \ + XFREE_CLEAR(x); \ } \ return ret; \ } \ diff --git a/src/nvim/lib/khash.h b/src/nvim/lib/khash.h index b2994a3159..c999511543 100644 --- a/src/nvim/lib/khash.h +++ b/src/nvim/lib/khash.h @@ -181,7 +181,7 @@ typedef khint_t khiter_t; #define krealloc(P,Z) xrealloc(P,Z) #endif #ifndef kfree -#define kfree(P) xfree(P) +#define kfree(P) XFREE_CLEAR(P) #endif #define __ac_HASH_UPPER 0.77 diff --git a/src/nvim/lib/klist.h b/src/nvim/lib/klist.h index 7ee100ab8c..b80f4be3c2 100644 --- a/src/nvim/lib/klist.h +++ b/src/nvim/lib/klist.h @@ -46,9 +46,9 @@ static inline void kmp_destroy_##name(kmp_##name##_t *mp) { \ size_t k; \ for (k = 0; k < mp->n; k++) { \ - kmpfree_f(mp->buf[k]); xfree(mp->buf[k]); \ + kmpfree_f(mp->buf[k]); XFREE_CLEAR(mp->buf[k]); \ } \ - xfree(mp->buf); xfree(mp); \ + XFREE_CLEAR(mp->buf); XFREE_CLEAR(mp); \ } \ static inline kmptype_t *kmp_alloc_##name(kmp_##name##_t *mp) { \ mp->cnt++; \ @@ -100,7 +100,7 @@ } \ kmp_free(name, kl->mp, p); \ kmp_destroy(name, kl->mp); \ - xfree(kl); \ + XFREE_CLEAR(kl); \ } \ static inline void kl_push_##name(kl_##name##_t *kl, kltype_t d) { \ kl1_##name *q, *p = kmp_alloc(name, kl->mp); \ diff --git a/src/nvim/lib/kvec.h b/src/nvim/lib/kvec.h index 93b2f053bc..e668b10bb9 100644 --- a/src/nvim/lib/kvec.h +++ b/src/nvim/lib/kvec.h @@ -58,7 +58,7 @@ } #define kv_init(v) ((v).size = (v).capacity = 0, (v).items = 0) -#define kv_destroy(v) xfree((v).items) +#define kv_destroy(v) XFREE_CLEAR((v).items) #define kv_A(v, i) ((v).items[(i)]) #define kv_pop(v) ((v).items[--(v).size]) #define kv_size(v) ((v).size) @@ -138,7 +138,7 @@ static inline void *_memcpy_free(void *const restrict dest, FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_ALWAYS_INLINE { memcpy(dest, src, size); - xfree(src); + XFREE_CLEAR(src); return dest; } @@ -201,7 +201,7 @@ static inline void *_memcpy_free(void *const restrict dest, #define kvi_destroy(v) \ do { \ if ((v).items != (v).init_array) { \ - xfree((v).items); \ + XFREE_CLEAR((v).items); \ } \ } while (0) diff --git a/src/nvim/lib/ringbuf.h b/src/nvim/lib/ringbuf.h index e63eae70b0..cb79eaf742 100644 --- a/src/nvim/lib/ringbuf.h +++ b/src/nvim/lib/ringbuf.h @@ -136,14 +136,14 @@ static inline void funcprefix##_rb_free(TypeName##RingBuffer *const rb) \ RINGBUF_FORALL(rb, RBType, rbitem) { \ rbfree(rbitem); \ } \ - xfree(rb->buf); \ + XFREE_CLEAR(rb->buf); \ } \ \ static inline void funcprefix##_rb_dealloc(TypeName##RingBuffer *const rb) \ REAL_FATTR_UNUSED; \ static inline void funcprefix##_rb_dealloc(TypeName##RingBuffer *const rb) \ { \ - xfree(rb->buf); \ + XFREE_CLEAR(rb->buf); \ } \ \ static inline void funcprefix##_rb_push(TypeName##RingBuffer *const rb, \ diff --git a/src/nvim/memory.c b/src/nvim/memory.c index 4ed816b157..b8a29070ce 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -110,6 +110,8 @@ void *xmalloc(size_t size) } /// free() wrapper that delegates to the backing memory manager +/// +/// @note Use XFREE_CLEAR() instead, if possible. void xfree(void *ptr) { free(ptr); diff --git a/src/nvim/memory.h b/src/nvim/memory.h index 250ac3e08f..5b39d002c9 100644 --- a/src/nvim/memory.h +++ b/src/nvim/memory.h @@ -40,4 +40,15 @@ extern bool entered_free_all_mem; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "memory.h.generated.h" #endif + +#define XFREE_CLEAR(ptr) \ + do { \ + /* Take the address to avoid double evaluation. #1375 */ \ + void **ptr_ = (void **)&(ptr); \ + xfree(*ptr_); \ + /* coverity[dead-store] */ \ + *ptr_ = NULL; \ + (void)(*ptr_); \ + } while (0) + #endif // NVIM_MEMORY_H diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua index 337c5442ef..1eeaa62864 100644 --- a/test/functional/autocmd/autocmd_spec.lua +++ b/test/functional/autocmd/autocmd_spec.lua @@ -148,10 +148,10 @@ describe('autocmd', function() funcs.execute('autocmd Tabnew')) end) - it('window works', function() - -- Nvim uses a special window to execute certain actions for an invisible buffer, - -- internally called autcmd_win and mentioned in the docs at :help E813 - -- Do some safety checks for redrawing and api accesses to this window. + it('internal `aucmd_win` window', function() + -- Nvim uses a special internal window `aucmd_win` to execute certain + -- actions for an invisible buffer (:help E813). + -- Check redrawing and API accesses to this window. local screen = Screen.new(50, 10) screen:attach() |