From b251117ddd460bb2209f565d71121b17b4385881 Mon Sep 17 00:00:00 2001 From: Patrick McDermott Date: Wed, 10 May 2023 06:11:03 -0400 Subject: dirent: Fix separators and length limits --- diff --git a/src/dirent.c b/src/dirent.c index b918a0d..7f361da 100644 --- a/src/dirent.c +++ b/src/dirent.c @@ -30,30 +30,43 @@ _opkg_opk_dirent_name_prefix(struct opkg_opk_dirent *dirent, char **name_buf, { size_t len; char **buf; + int sep; len = strlen(dirent->name); - if (*name_len + len <= *name_buf_len) { + if (*name_len > 0 && *name_len + len + 1 <= *name_buf_len) { + /* Space available in name buffer. Not last node, so append + * separator. */ buf = name_buf; - if (*buf == NULL) { - return OPKG_OPK_ERROR; - } - if (**buf != '\0') { - ++len; - } - *name_buf_len -= len; - } else if (*pref_len + len <= *pref_buf_len) { + *name_len += len + 1; + sep = 1; + } else if (*name_len == 0 && *name_len + len <= *name_buf_len) { + /* Space available in name buffer. Last node (first in + * recursion), so don't append separator. */ + buf = name_buf; + *name_len += len; + sep = 0; + } else if (*pref_len > 0 && *pref_len + len + 1 <= *pref_buf_len) { + /* Space available in prefix buffer. Not last node, so append + * separator. */ + buf = pref_buf; + *pref_len += len + 1; + sep = 1; + } else if (*pref_len == 0 && *pref_len + len <= *pref_buf_len) { + /* Space available in prefix buffer. Last node (first in + * recursion), so don't append separator. */ buf = pref_buf; - if (*buf == NULL) { - return OPKG_OPK_ERROR; - } - if (**buf != '\0') { - ++len; - } - *pref_buf_len -= len; + *pref_len += len; + sep = 0; } else { + /* Both buffers full. */ + return OPKG_OPK_ERROR; + } + if (*buf == NULL) { + /* Caller provided a NULL buffer pointer. */ return OPKG_OPK_ERROR; } + /* Recurse. */ if (dirent->parent != NULL && _opkg_opk_dirent_name_prefix(dirent->parent, name_buf, name_buf_len, pref_buf, pref_buf_len, @@ -61,13 +74,13 @@ _opkg_opk_dirent_name_prefix(struct opkg_opk_dirent *dirent, char **name_buf, return OPKG_OPK_ERROR; } - if (**buf != '\0') { + /* Copy node name and possibly separator suffix. */ + memcpy(*buf, dirent->name, len); + *buf += len; + if (sep == 1) { **buf = '/'; *buf += 1; - --len; } - memcpy(*buf, dirent->name, len); - *buf += len; return OPKG_OPK_OK; } @@ -76,18 +89,24 @@ int opkg_opk_dirent_name_prefix(struct opkg_opk_dirent *dirent, char *name_buf, size_t name_buf_len, char *pref_buf, size_t pref_buf_len) { - size_t name_len = 0; - size_t pref_len = 0; + size_t name_len = 0; + size_t pref_len = 0; + char *name = name_buf; + char *pref = pref_buf; + + /* NUL bytes */ + --name_buf_len; + --pref_buf_len; - name_buf[0] = '\0'; - pref_buf[0] = '\0'; if (_opkg_opk_dirent_name_prefix(dirent, &name_buf, &name_buf_len, &pref_buf, &pref_buf_len, &name_len, &pref_len) == OPKG_OPK_ERROR) { return OPKG_OPK_ERROR; } - name_buf[name_len] = '\0'; - pref_buf[pref_len] = '\0'; + + name[name_len] = '\0'; + pref[pref_len] = '\0'; + return OPKG_OPK_OK; } @@ -107,10 +126,10 @@ main() .parent = &bar, }; char name[8]; - char pref[5]; + char pref[4]; - if (opkg_opk_dirent_name_prefix(&baz, name, 8, pref, 5) != OPKG_OPK_OK) - { + if (opkg_opk_dirent_name_prefix(&baz, name, sizeof(name), + pref, sizeof(pref)) != OPKG_OPK_OK) { puts("Error building name parts"); return EXIT_FAILURE; } -- cgit v0.9.1