fix(platform): correct filename buffer handling and prevent overflows
- Replace undefined 'len' variable references with 'name_len' - Add explicit null terminators after memcpy operations - Move name_len declaration to Windows-specific scope to eliminate unused variable warning on BSD - Standardize string copy pattern across all platforms: strlen -> clamp -> memcpy -> null terminate - Fix increment operator placement for clarity (i++ moved outside array indexing) - Remove duplicate name_len declaration in platform_directory_watch_check This ensures proper bounds checking and null termination for filenames on both Windows and BSD systems, preventing potential buffer overflows when handling long filenames (approaching STK_PATH_MAX).
This commit is contained in:
+129
-113
@@ -286,126 +286,128 @@ void *platform_get_symbol(void *h, const char *s)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
char (*platform_directory_init_scan(const char *dir_path, size_t *out_count))
|
char (*platform_directory_init_scan(const char *dir_path,
|
||||||
[STK_PATH_MAX] {
|
size_t *out_count))[STK_PATH_MAX]
|
||||||
size_t count = 0, i = 0, name_len;
|
{
|
||||||
char (*list)[STK_PATH_MAX] = NULL;
|
size_t count = 0, i = 0, name_len;
|
||||||
|
char(*list)[STK_PATH_MAX] = NULL;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WIN32_FIND_DATAA fd;
|
WIN32_FIND_DATAA fd;
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
char s[STK_PATH_MAX_OS];
|
char s[STK_PATH_MAX_OS];
|
||||||
|
|
||||||
sprintf(s, "%s\\*", dir_path);
|
sprintf(s, "%s\\*", dir_path);
|
||||||
h = FindFirstFileA(s, &fd);
|
h = FindFirstFileA(s, &fd);
|
||||||
if (h == INVALID_HANDLE_VALUE)
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
goto create_and_exit;
|
goto create_and_exit;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||||
continue;
|
continue;
|
||||||
if (is_valid_module_file(fd.cFileName))
|
if (is_valid_module_file(fd.cFileName))
|
||||||
count++;
|
count++;
|
||||||
} while (FindNextFileA(h, &fd));
|
} while (FindNextFileA(h, &fd));
|
||||||
|
|
||||||
FindClose(h);
|
FindClose(h);
|
||||||
|
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
list = malloc(count * sizeof(*list));
|
list = malloc(count * sizeof(*list));
|
||||||
if (!list)
|
if (!list)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
h = FindFirstFileA(s, &fd);
|
h = FindFirstFileA(s, &fd);
|
||||||
if (h == INVALID_HANDLE_VALUE)
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||||
continue;
|
continue;
|
||||||
if (is_valid_module_file(fd.cFileName) && i < count) {
|
if (is_valid_module_file(fd.cFileName) && i < count) {
|
||||||
name_len = strlen(fd.cFileName);
|
name_len = strlen(fd.cFileName);
|
||||||
if (name_len >= STK_PATH_MAX)
|
if (name_len >= STK_PATH_MAX)
|
||||||
len = STK_PATH_MAX - 1;
|
name_len = STK_PATH_MAX - 1;
|
||||||
|
|
||||||
memcpy(list[i], fd.cFileName, name_len);
|
memcpy(list[i], fd.cFileName, name_len);
|
||||||
list[i++][len] = '\0';
|
list[i][name_len] = '\0';
|
||||||
}
|
i++;
|
||||||
} while (FindNextFileA(h, &fd));
|
}
|
||||||
|
} while (FindNextFileA(h, &fd));
|
||||||
|
|
||||||
FindClose(h);
|
FindClose(h);
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
create_and_exit:
|
create_and_exit:
|
||||||
platform_mkdir(dir_path);
|
platform_mkdir(dir_path);
|
||||||
exit:
|
exit:
|
||||||
*out_count = i;
|
*out_count = i;
|
||||||
return list;
|
return list;
|
||||||
#else
|
#else
|
||||||
DIR *d;
|
DIR *d;
|
||||||
struct dirent *e;
|
struct dirent *e;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char f[STK_PATH_MAX_OS];
|
char f[STK_PATH_MAX_OS];
|
||||||
|
|
||||||
d = opendir(dir_path);
|
d = opendir(dir_path);
|
||||||
if (!d)
|
if (!d)
|
||||||
goto create_and_exit;
|
goto create_and_exit;
|
||||||
|
|
||||||
count_loop:
|
count_loop:
|
||||||
e = readdir(d);
|
e = readdir(d);
|
||||||
if (!e)
|
if (!e)
|
||||||
goto count_done;
|
goto count_done;
|
||||||
|
|
||||||
sprintf(f, "%s/%s", dir_path, e->d_name);
|
sprintf(f, "%s/%s", dir_path, e->d_name);
|
||||||
if (!is_valid_module_file(e->d_name))
|
if (!is_valid_module_file(e->d_name))
|
||||||
goto count_loop;
|
goto count_loop;
|
||||||
|
|
||||||
if (stat(f, &st) != 0 || !S_ISREG(st.st_mode))
|
if (stat(f, &st) != 0 || !S_ISREG(st.st_mode))
|
||||||
goto count_loop;
|
goto count_loop;
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
goto count_loop;
|
goto count_loop;
|
||||||
|
|
||||||
count_done:
|
count_done:
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
goto close_and_exit;
|
goto close_and_exit;
|
||||||
|
|
||||||
rewinddir(d);
|
rewinddir(d);
|
||||||
list = malloc(count * sizeof(*list));
|
list = malloc(count * sizeof(*list));
|
||||||
if (!list)
|
if (!list)
|
||||||
goto close_and_exit;
|
goto close_and_exit;
|
||||||
|
|
||||||
fill_loop:
|
fill_loop:
|
||||||
e = readdir(d);
|
e = readdir(d);
|
||||||
if (!e || i >= count)
|
if (!e || i >= count)
|
||||||
goto close_and_exit;
|
goto close_and_exit;
|
||||||
|
|
||||||
sprintf(f, "%s/%s", dir_path, e->d_name);
|
sprintf(f, "%s/%s", dir_path, e->d_name);
|
||||||
if (!is_valid_module_file(e->d_name))
|
if (!is_valid_module_file(e->d_name))
|
||||||
goto fill_loop;
|
goto fill_loop;
|
||||||
|
|
||||||
if (stat(f, &st) != 0 || !S_ISREG(st.st_mode))
|
if (stat(f, &st) != 0 || !S_ISREG(st.st_mode))
|
||||||
goto fill_loop;
|
goto fill_loop;
|
||||||
|
|
||||||
name_len = strlen(e->d_name);
|
name_len = strlen(e->d_name);
|
||||||
if (name_len >= STK_PATH_MAX) {
|
if (name_len >= STK_PATH_MAX) {
|
||||||
name_len = STK_PATH_MAX - 1;
|
name_len = STK_PATH_MAX - 1;
|
||||||
}
|
}
|
||||||
memcpy(list[i++], e->d_name, name_len);
|
memcpy(list[i++], e->d_name, name_len);
|
||||||
list[i - 1][name_len] = '\0';
|
list[i - 1][name_len] = '\0';
|
||||||
goto fill_loop;
|
goto fill_loop;
|
||||||
|
|
||||||
create_and_exit:
|
create_and_exit:
|
||||||
platform_mkdir(dir_path);
|
platform_mkdir(dir_path);
|
||||||
*out_count = 0;
|
*out_count = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
close_and_exit:
|
close_and_exit:
|
||||||
closedir(d);
|
closedir(d);
|
||||||
*out_count = i;
|
*out_count = i;
|
||||||
return list;
|
return list;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(__linux__) && !defined(_WIN32)
|
#if !defined(__linux__) && !defined(_WIN32)
|
||||||
static void update_watches(platform_watch_context_t *ctx)
|
static void update_watches(platform_watch_context_t *ctx)
|
||||||
@@ -489,12 +491,11 @@ void *platform_directory_watch_start(const char *path)
|
|||||||
fd, path, IN_CLOSE_WRITE | IN_DELETE | IN_MOVED_TO | IN_MOVED_FROM);
|
fd, path, IN_CLOSE_WRITE | IN_DELETE | IN_MOVED_TO | IN_MOVED_FROM);
|
||||||
return (void *)(long)fd;
|
return (void *)(long)fd;
|
||||||
#else
|
#else
|
||||||
size_t name_len;
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WIN32_FIND_DATAA fd;
|
WIN32_FIND_DATAA fd;
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
char s[STK_PATH_MAX_OS];
|
char s[STK_PATH_MAX_OS];
|
||||||
size_t count = 0, i = 0;
|
size_t count = 0, i = 0, name_len;
|
||||||
#else
|
#else
|
||||||
DIR *d;
|
DIR *d;
|
||||||
struct dirent *e;
|
struct dirent *e;
|
||||||
@@ -545,10 +546,12 @@ void *platform_directory_watch_start(const char *path)
|
|||||||
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||||
is_valid_module_file(fd.cFileName) && i < count) {
|
is_valid_module_file(fd.cFileName) && i < count) {
|
||||||
name_len = strlen(fd.cFileName);
|
name_len = strlen(fd.cFileName);
|
||||||
if (len >= STK_PATH_MAX)
|
if (name_len >= STK_PATH_MAX)
|
||||||
len = STK_PATH_MAX - 1;
|
name_len = STK_PATH_MAX - 1;
|
||||||
memcpy(ctx->snaps[i].filename, fd.cFileName, len);
|
memcpy(ctx->snaps[i].filename, fd.cFileName, name_len);
|
||||||
ctx->snaps[i++].mtime = fd.ftLastWriteTime;
|
ctx->snaps[i].filename[name_len] = '\0';
|
||||||
|
ctx->snaps[i].mtime = fd.ftLastWriteTime;
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
} while (FindNextFileA(h, &fd));
|
} while (FindNextFileA(h, &fd));
|
||||||
|
|
||||||
@@ -773,7 +776,7 @@ stk_module_event_t *platform_directory_watch_check(
|
|||||||
WIN32_FIND_DATAA fd;
|
WIN32_FIND_DATAA fd;
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
char s[STK_PATH_MAX_OS];
|
char s[STK_PATH_MAX_OS];
|
||||||
size_t count = 0, name_len;
|
size_t count = 0;
|
||||||
|
|
||||||
sprintf(s, "%s\\*", ctx->path);
|
sprintf(s, "%s\\*", ctx->path);
|
||||||
h = FindFirstFileA(s, &fd);
|
h = FindFirstFileA(s, &fd);
|
||||||
@@ -805,12 +808,12 @@ stk_module_event_t *platform_directory_watch_check(
|
|||||||
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||||
is_valid_module_file(fd.cFileName) && new_count < count) {
|
is_valid_module_file(fd.cFileName) && new_count < count) {
|
||||||
name_len = strlen(fd.cFileName);
|
name_len = strlen(fd.cFileName);
|
||||||
if (len >= STK_PATH_MAX)
|
if (name_len >= STK_PATH_MAX)
|
||||||
len = STK_PATH_MAX - 1;
|
name_len = STK_PATH_MAX - 1;
|
||||||
|
|
||||||
memcpy(new_snaps[new_count].filename, fd.cFileName,
|
memcpy(new_snaps[new_count].filename, fd.cFileName,
|
||||||
len);
|
name_len);
|
||||||
new_snaps[new_count].filename[len] = '\0';
|
new_snaps[new_count].filename[name_len] = '\0';
|
||||||
new_snaps[new_count].mtime = fd.ftLastWriteTime;
|
new_snaps[new_count].mtime = fd.ftLastWriteTime;
|
||||||
new_count++;
|
new_count++;
|
||||||
}
|
}
|
||||||
@@ -904,9 +907,13 @@ build_diff:
|
|||||||
&new_snaps[j].mtime) != 0) {
|
&new_snaps[j].mtime) != 0) {
|
||||||
if (is_file_ready(ctx->path,
|
if (is_file_ready(ctx->path,
|
||||||
new_snaps[j].filename)) {
|
new_snaps[j].filename)) {
|
||||||
strncpy((*file_list)[ev_index],
|
name_len =
|
||||||
new_snaps[j].filename,
|
strlen(new_snaps[j].filename);
|
||||||
STK_PATH_MAX - 1);
|
if (name_len >= STK_PATH_MAX)
|
||||||
|
name_len = STK_PATH_MAX - 1;
|
||||||
|
memcpy((*file_list)[ev_index],
|
||||||
|
new_snaps[j].filename, name_len);
|
||||||
|
(*file_list)[ev_index][name_len] = '\0';
|
||||||
evs[ev_index++] = STK_MOD_RELOAD;
|
evs[ev_index++] = STK_MOD_RELOAD;
|
||||||
} else {
|
} else {
|
||||||
new_snaps[j].mtime =
|
new_snaps[j].mtime =
|
||||||
@@ -920,10 +927,11 @@ build_diff:
|
|||||||
name_len =
|
name_len =
|
||||||
strlen(ctx->snaps[i].filename);
|
strlen(ctx->snaps[i].filename);
|
||||||
if (name_len >= STK_PATH_MAX)
|
if (name_len >= STK_PATH_MAX)
|
||||||
len = STK_PATH_MAX;
|
name_len = STK_PATH_MAX - 1;
|
||||||
memcpy((*file_list)[ev_index],
|
memcpy((*file_list)[ev_index],
|
||||||
ctx->snaps[i].filename,
|
ctx->snaps[i].filename,
|
||||||
name_len);
|
name_len);
|
||||||
|
(*file_list)[ev_index][name_len] = '\0';
|
||||||
evs[ev_index++] = STK_MOD_RELOAD;
|
evs[ev_index++] = STK_MOD_RELOAD;
|
||||||
} else {
|
} else {
|
||||||
new_snaps[j].mtime =
|
new_snaps[j].mtime =
|
||||||
@@ -935,8 +943,12 @@ build_diff:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
strncpy((*file_list)[ev_index], ctx->snaps[i].filename,
|
name_len = strlen(ctx->snaps[i].filename);
|
||||||
STK_PATH_MAX - 1);
|
if (name_len >= STK_PATH_MAX)
|
||||||
|
name_len = STK_PATH_MAX - 1;
|
||||||
|
memcpy((*file_list)[ev_index], ctx->snaps[i].filename,
|
||||||
|
name_len);
|
||||||
|
(*file_list)[ev_index][name_len] = '\0';
|
||||||
evs[ev_index++] = STK_MOD_UNLOAD;
|
evs[ev_index++] = STK_MOD_UNLOAD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -952,8 +964,12 @@ build_diff:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
strncpy((*file_list)[ev_index], new_snaps[j].filename,
|
name_len = strlen(new_snaps[j].filename);
|
||||||
STK_PATH_MAX - 1);
|
if (name_len >= STK_PATH_MAX)
|
||||||
|
name_len = STK_PATH_MAX - 1;
|
||||||
|
memcpy((*file_list)[ev_index], new_snaps[j].filename,
|
||||||
|
name_len);
|
||||||
|
(*file_list)[ev_index][name_len] = '\0';
|
||||||
evs[ev_index++] = STK_MOD_LOAD;
|
evs[ev_index++] = STK_MOD_LOAD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user