From 9f19cffc787a715e6bf33fe0c5b6f9644bf563e6 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Thu, 12 Mar 2026 11:36:42 -0400
Subject: [PATCH] io: With stdio, only forbid opening directories as files.
This allows opening Unix device nodes, etc.
Fixes #15188.
---
src/io/SDL_iostream.c | 25 +++++++++++--------------
1 file changed, 11 insertions(+), 14 deletions(-)
diff --git a/src/io/SDL_iostream.c b/src/io/SDL_iostream.c
index 5fa7f194d47c8..4f3b0606add5a 100644
--- a/src/io/SDL_iostream.c
+++ b/src/io/SDL_iostream.c
@@ -970,16 +970,13 @@ static bool SDLCALL mem_close(void *userdata)
#endif
#if defined(HAVE_STDIO_H) && !defined(SKIP_STDIO_DIR_TEST)
-static bool IsRegularFileOrPipe(FILE *f)
+static bool IsStdioFileADirectory(FILE *f)
{
struct stat st;
- if (fstat(fileno(f), &st) < 0 || !(S_ISREG(st.st_mode) || S_ISFIFO(st.st_mode))) {
- return false;
- }
- return true;
+ return ((fstat(fileno(f), &st) == 0) && (S_ISDIR(st.st_mode)));
}
#else
-#define IsRegularFileOrPipe(f) false
+#define IsStdioFileADirectory(f) false
#endif
SDL_IOStream *SDL_IOFromFile(const char *file, const char *mode)
@@ -1001,9 +998,9 @@ SDL_IOStream *SDL_IOFromFile(const char *file, const char *mode)
if (*file == '/') {
FILE *fp = fopen(file, mode);
if (fp) {
- if (!IsRegularFileOrPipe(fp)) {
+ if (IsStdioFileADirectory(fp)) {
fclose(fp);
- SDL_SetError("%s is not a regular file or pipe", file);
+ SDL_SetError("%s is a directory", file);
return NULL;
}
return SDL_IOFromFP(fp, true);
@@ -1032,9 +1029,9 @@ SDL_IOStream *SDL_IOFromFile(const char *file, const char *mode)
FILE *fp = fopen(path, mode);
SDL_free(path);
if (fp) {
- if (!IsRegularFileOrPipe(fp)) {
+ if (IsStdioFileADirectory(fp)) {
fclose(fp);
- SDL_SetError("%s is not a regular file or pipe", path);
+ SDL_SetError("%s is a directory", path);
return NULL;
}
return SDL_IOFromFP(fp, true);
@@ -1098,9 +1095,9 @@ SDL_IOStream *SDL_IOFromFile(const char *file, const char *mode)
if (!fp) {
SDL_SetError("Couldn't open %s: %s", file, strerror(errno));
- } else if (!IsRegularFileOrPipe(fp)) {
+ } else if (IsStdioFileADirectory(fp)) {
fclose(fp);
- SDL_SetError("%s is not a regular file or pipe", file);
+ SDL_SetError("%s is a directory", file);
} else {
iostr = SDL_IOFromFP(fp, true);
}
@@ -1121,9 +1118,9 @@ SDL_IOStream *SDL_IOFromFile(const char *file, const char *mode)
if (!fp) {
SDL_SetError("Couldn't open %s: %s", file, strerror(errno));
- } else if (!IsRegularFileOrPipe(fp)) {
+ } else if (IsStdioFileADirectory(fp)) {
fclose(fp);
- SDL_SetError("%s is not a regular file or pipe", file);
+ SDL_SetError("%s is a directory", file);
} else {
iostr = SDL_IOFromFP(fp, true);
}