From d10d1b21f5d4b28ba9d52adb955b87d8208d1197 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 5 Jun 2016 19:17:03 +0300 Subject: [PATCH] net: buf: Don't use recursion for freeing fragment list Freeing the fragment list by recursively calling net_buf_unref() is elegant but dangerous. Since we have fairly small stack sizes it'd be possible to overflow the stack if the user creates a very long list of fragments (empirical tests showed that some 21 fragments is enough to kill a 2k stack). Instead, use a while-loop for freeing up the fragments, thereby guaranteeing a fixed upper bound for net_buf_unref() stack usage. Change-Id: Ibfe794fa717d1cddc84365c7b7b9cff4024edbf6 Signed-off-by: Johan Hedberg --- net/buf.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/net/buf.c b/net/buf.c index 7ea5a863296..b69942fbb91 100644 --- a/net/buf.c +++ b/net/buf.c @@ -129,19 +129,18 @@ void net_buf_unref(struct net_buf *buf) NET_BUF_DBG("buf %p ref %u fifo %p\n", buf, buf->ref, buf->free); NET_BUF_ASSERT(buf->ref > 0); - if (--buf->ref) { - return; - } + while (buf && --buf->ref == 0) { + struct net_buf *frags = buf->frags; - if (buf->frags) { - net_buf_unref(buf->frags); buf->frags = NULL; - } - if (buf->destroy) { - buf->destroy(buf); - } else { - nano_fifo_put(buf->free, buf); + if (buf->destroy) { + buf->destroy(buf); + } else { + nano_fifo_put(buf->free, buf); + } + + buf = frags; } }