Page 1 of 1

[PATCH] Fix off-by-one error in readdir and some minor inconsistencies

Posted: Wed Apr 19, 2023 2:45 am
by Extrems

Code: Select all

From 7571ec2b7b47f38f95f47909025f9753e4b9c055 Mon Sep 17 00:00:00 2001
From: Extrems <[email protected]>
Date: Tue, 18 Apr 2023 21:31:48 -0400
Subject: [PATCH 1/2] Fix off-by-one error in readdir and some minor
 inconsistencies

---
 libgloss/libsysbase/dirent.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/libgloss/libsysbase/dirent.c b/libgloss/libsysbase/dirent.c
index bed699102..482d2f814 100644
--- a/libgloss/libsysbase/dirent.c
+++ b/libgloss/libsysbase/dirent.c
@@ -117,6 +117,7 @@ DIR* opendir (const char *dirname) {
 
 	dirp->position = 0;	// 0th position means no file name has been returned yet
 	dirp->fileData.d_ino = -1;
+	dirp->fileData.d_type = DT_UNKNOWN;
 	dirp->fileData.d_name[0] = '\0';
 
 	return dirp;
@@ -139,7 +140,7 @@ int closedir (DIR *dirp) {
 
 struct dirent* readdir (DIR *dirp) {
 	struct stat st;
-	char filename[NAME_MAX];
+	char filename[NAME_MAX+1];
 	int res;
 	int olderrno = errno;
 
@@ -162,7 +163,7 @@ struct dirent* readdir (DIR *dirp) {
 	// We've moved forward in the directory
 	dirp->position += 1;
 
-	if (strnlen(filename, NAME_MAX) >= sizeof(dirp->fileData.d_name)) {
+	if (strnlen(filename, sizeof(filename)) >= sizeof(dirp->fileData.d_name)) {
 		errno = EOVERFLOW;
 		return NULL;
 	}
@@ -177,7 +178,7 @@ struct dirent* readdir (DIR *dirp) {
 
 int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) {
 	struct stat st;
-	char filename[NAME_MAX];
+	char filename[NAME_MAX+1];
 	int res;
 
 	if (!dirp) {
@@ -200,13 +201,14 @@ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) {
 	// We've moved forward in the directory
 	dirp->position += 1;
 
-	if (strnlen(filename, NAME_MAX) >= sizeof(entry->d_name)) {
+	if (strnlen(filename, sizeof(filename)) >= sizeof(entry->d_name)) {
 		errno = EOVERFLOW;
 		return EOVERFLOW;
 	}
 
 	strncpy (entry->d_name, filename, sizeof(entry->d_name));
 	entry->d_ino = st.st_ino;
+	entry->d_type = IFTODT(st.st_mode);
 
 	*result = entry;
 	return 0;
@@ -224,7 +226,7 @@ void rewinddir (DIR *dirp) {
 
 
 void seekdir(DIR *dirp, long int loc) {
-	char filename[NAME_MAX];
+	char filename[NAME_MAX+1];
 
 	if (!dirp || loc < 0) {
 		return;
-- 
2.39.1.windows.1

This is necessary to ensure a working overflow check for VFAT and NTFS file names, which may occupy up to 766 UTF-8 bytes, and for a NUL to be present when a file name is exactly 255 characters.

Re: [PATCH] Fix off-by-one error in readdir and some minor inconsistencies

Posted: Thu Apr 20, 2023 7:20 pm
by WinterMute
Also thanks for this. I split the changes into two commits though rather than bundle multiple changes in one go.