This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit e2c9aa65883780747ca00625a1452dddc6f8a138 Author: Zhe Weng <[email protected]> AuthorDate: Thu Aug 17 15:55:32 2023 +0800 mm/iob: Fix IOB length in `iob_reserve` If we apply `iob_reserve` on an IOB with `io_offset != 0`, the `head->io_pktlen` and `iob->io_len` will become wrong value, because we only need to trim `offset - iob->io_offset`. Signed-off-by: Zhe Weng <[email protected]> --- mm/iob/iob_reserve.c | 32 +++++++++++++------------------- mm/iob/iob_test.c | 20 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/mm/iob/iob_reserve.c b/mm/iob/iob_reserve.c index 2f459de3aa..e1964d5d14 100644 --- a/mm/iob/iob_reserve.c +++ b/mm/iob/iob_reserve.c @@ -41,20 +41,11 @@ void iob_reserve(FAR struct iob_s *iob, unsigned int reserved) { + FAR struct iob_s *head = iob; unsigned int offset; + int trimlen; - /* Empty iob buffer is allowed, update packet length. */ - - if (iob->io_pktlen > reserved) - { - iob->io_pktlen -= reserved; - } - else - { - iob->io_pktlen = 0; - } - - /* Update offset and reducing the tail room */ + /* Update offset and adjust packet length. */ while (iob != NULL && reserved > 0) { @@ -67,16 +58,19 @@ void iob_reserve(FAR struct iob_s *iob, unsigned int reserved) offset = reserved; } - if (iob->io_len > offset) - { - iob->io_len -= offset; - } - else + trimlen = offset - iob->io_offset; + + /* At most trim iob->io_len to 0. */ + + if ((int)(iob->io_len - trimlen) < 0) { - iob->io_len = 0; + trimlen = iob->io_len; } - iob->io_offset = offset; + head->io_pktlen -= trimlen; + iob->io_len -= trimlen; + iob->io_offset = offset; + iob = iob->io_flink; reserved -= offset; } diff --git a/mm/iob/iob_test.c b/mm/iob/iob_test.c index 78122c0768..f865326385 100644 --- a/mm/iob/iob_test.c +++ b/mm/iob/iob_test.c @@ -161,6 +161,26 @@ int main(int argc, char **argv) fprintf(stderr, "Buffer1 does not match buffer2\n"); } + nbytes = iob->io_pktlen; + + iob_reserve(iob, 55); + printf("Reserve: adjust offset to 55\n"); + dump_chain(iob); + + if (iob->io_offset != 55 || iob->io_pktlen + 55 != nbytes) + { + fprintf(stderr, "Offset or packet length wrong\n"); + } + + iob_reserve(iob, 28); + printf("Reserve: adjust offset to 28\n"); + dump_chain(iob); + + if (iob->io_offset != 28 || iob->io_pktlen + 28 != nbytes) + { + fprintf(stderr, "Offset or packet length wrong\n"); + } + while (iob) iob = iob_free(iob); return EXIT_SUCCESS; }
