From a02cb16190bd901962fb7bcd18bf8b5a5b4492a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 18 Nov 2020 08:55:27 +0100 Subject: [PATCH] mesh: Fix model tree walk procedure `bt_mesh_model_tree_walk()` was too simplistic and did not track visited nodes which caused it to fall into infinite loop. Moreover the double next jump could skip a level causing depth value to be invalid. this is port of 3908638bab5966ac2e989a099a64141dff1116e1 --- nimble/host/mesh/src/access.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index 952ab0183..7ac52e18d 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -804,23 +804,31 @@ void bt_mesh_model_tree_walk(struct bt_mesh_model *root, { struct bt_mesh_model *m = root; uint32_t depth = 0; + /* 'skip' is set to true when we ascend from child to parent node. + * In that case, we want to skip calling the callback on the parent + * node and we don't want to descend onto a child node as those + * nodes have already been visited. + */ + bool skip = false; do { - if (cb(m, depth, user_data) == BT_MESH_WALK_STOP) { + if (!skip && cb(m, depth, user_data) == BT_MESH_WALK_STOP) { return; } #if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS) - if (m->extends) { + if (!skip && m->extends) { m = m->extends; depth++; } else if (m->flags & BT_MESH_MOD_NEXT_IS_PARENT) { - m = m->next->next; + m = m->next; depth--; + skip = true; } else { m = m->next; + skip = false; } #endif - } while (m && m != root); + } while (m); } #if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS)