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

Got something cool to help make the toolchains better? Post it here.
Post Reply
Extrems
Posts: 3
Joined: Sat Dec 26, 2020 11:26 pm
Location: Québec, Canada
Contact:

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

Post by Extrems » Wed Apr 19, 2023 2:45 am

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.

WinterMute
Site Admin
Posts: 1845
Joined: Tue Aug 09, 2005 3:21 am
Location: UK
Contact:

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

Post by WinterMute » Thu Apr 20, 2023 7:20 pm

Also thanks for this. I split the changes into two commits though rather than bundle multiple changes in one go.
Help keep devkitPro toolchains free, Donate today

Personal Blog

Post Reply

Who is online

Users browsing this forum: No registered users and 10 guests