aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Pilling <robpilling@gmail.com>2019-10-22 19:55:55 +0100
committerRob Pilling <robpilling@gmail.com>2019-10-22 19:55:55 +0100
commite284b7233fb459a7a6d4ce0f98371b34b3639d2b (patch)
tree1c0a52228f22cd913b6a92556649355ab8b1897c
parentdd49a130ff0cd7a51cec3a7bae1ecda3708f8eb2 (diff)
downloadrneovim-e284b7233fb459a7a6d4ce0f98371b34b3639d2b.tar.gz
rneovim-e284b7233fb459a7a6d4ce0f98371b34b3639d2b.tar.bz2
rneovim-e284b7233fb459a7a6d4ce0f98371b34b3639d2b.zip
Perform HASHTAB_ITER bookkeeping before user-code
The `HASHTAB_ITER` logic keeps track of how many entries in the hash table are left to visit, decrementing this on each iteration of the loop. This was previously decremented at the end of the loop body: ```c size_t hi##todo_ = hi##ht_->ht_used; for (hashitem_T *hi = hi##ht_->ht_array; hi##todo_; hi++) { if (!HASHITEM_EMPTY(hi)) { { <user code, macro-inserted> } hi##todo_--; // <--- important decrement here } } ``` This meant that if the body of the loop (substituted in via macro expansion) contained a `continue` statement, we'd skip decrementing our counter, meaning we'd iterate too many times over the hash table, usually leading to an out of bounds read beyond the hash table's memory, or uninitialised/null pointers from unused hash table slots. Decrementing `hi##todo` before the arbitrary loop body protects us from this, and has no adverse side-effects since only the macro code can (or should) use this variable. Before this commit, no code within `HASHTAB_ITER()` contained a `continue`, meaning this bug was left dormant and the fix has a very minimal chance of introducing any bugs.
-rw-r--r--src/nvim/hashtab.h2
1 files changed, 1 insertions, 1 deletions
diff --git a/src/nvim/hashtab.h b/src/nvim/hashtab.h
index a70a8bea63..19633d455f 100644
--- a/src/nvim/hashtab.h
+++ b/src/nvim/hashtab.h
@@ -81,10 +81,10 @@ typedef struct hashtable_S {
size_t hi##todo_ = hi##ht_->ht_used; \
for (hashitem_T *hi = hi##ht_->ht_array; hi##todo_; hi++) { \
if (!HASHITEM_EMPTY(hi)) { \
+ hi##todo_--; \
{ \
code \
} \
- hi##todo_--; \
} \
} \
} while (0)