libuv
libuv copied to clipboard
uv_fs_scandir memory leak
In some case of breaking the loop uv_fs_scandir_next() before the end , there seems to be a memory leak of the last entry
uv_fs_t scandir_req{}
uv_dirent_t entry{}
res = uv_fs_scandir(NULL, &scandir_req, path, 0, NULL);
...
while (UV_EOF != uv_fs_scandir_next(&scandir_req, &entry))
{
...
goto exit;
}
exit:
uv_fs_req_cleanup(&scandir_req)
my test directory includes only one file. if I am waiting until the end of the loop (one more iteration) there is no memory leak.
from my short research , I saw difference between the two cleanup cases (breaking the rule before UV_EOF and after)
Breaking the loop (my case)
uv_fs_req_cleanup calls uv__fs_scandir_cleanup(req)
void uv__fs_scandir_cleanup(uv_fs_t* req) {
uv__dirent_t** dents;
unsigned int* nbufs = uv__get_nbufs(req);
dents = req->ptr;
if (*nbufs > 0 && nbufs != (unsigned int) req->result) // **the previous entity is not released**
(*nbufs)--;
for (; *nbufs < (unsigned int) req->result; (*nbufs)++)
uv__fs_scandir_free(dents[*nbufs]);
uv__fs_scandir_free(req->ptr);
req->ptr = NULL;
}
Running until UV_EOF case (one more time):
the last uv_fs_scandir_next call releases the previous entity
int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) {
uv__dirent_t** dents;
uv__dirent_t* dent;
unsigned int* nbufs;
/* Check to see if req passed */
if (req->result < 0)
return req->result;
/* Ptr will be null if req was canceled or no files found */
if (!req->ptr)
return UV_EOF;
nbufs = uv__get_nbufs(req);
assert(nbufs);
dents = req->ptr;
/* Free previous entity */
if (*nbufs > 0)
uv__fs_scandir_free(dents[*nbufs - 1]); // **the previous entity is released**
/* End was already reached */
if (*nbufs == (unsigned int) req->result) {
uv__fs_scandir_free(dents);
req->ptr = NULL;
return UV_EOF;
}
....
}
Is the uv__fs_scandir_cleanup's condition wrong? (nbufs != (unsigned int) req->result )
- Version: v1.39.0
- Platform: Linux ubuntu 5.4.0-113-generic