SDL: SDL_RWFromFile, stdio: reject if the file is not a regular file. (3bf60)

From 3bf60755cbbfe7d8990f766a70821dfbe0b4f060 Mon Sep 17 00:00:00 2001
From: Ozkan Sezer <[EMAIL REDACTED]>
Date: Sun, 28 Jan 2024 01:44:50 +0300
Subject: [PATCH] SDL_RWFromFile, stdio: reject if the file is not a regular
 file.

Fixes https://github.com/libsdl-org/SDL/issues/8935
(cherry picked from commit 230ae797a7406358b7fcf74701d39b5f342f9807)
---
 src/file/SDL_rwops.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/src/file/SDL_rwops.c b/src/file/SDL_rwops.c
index a691a5ce071a..d46089e7b03c 100644
--- a/src/file/SDL_rwops.c
+++ b/src/file/SDL_rwops.c
@@ -36,6 +36,7 @@
 
 #ifdef HAVE_STDIO_H
 #include <stdio.h>
+#include <sys/stat.h>
 #endif
 
 #ifdef HAVE_LIMITS_H
@@ -523,6 +524,24 @@ static int SDLCALL mem_close(SDL_RWops *context)
 
 /* Functions to create SDL_RWops structures from various data sources */
 
+#if defined(HAVE_STDIO_H) && !(defined(__WIN32__) || defined(__GDK__))
+static SDL_bool SDL_IsRegularFile(FILE *f)
+{
+    #ifdef __WINRT__
+    struct __stat64 st;
+    if (_fstat64(_fileno(f), &st) < 0 || !S_ISREG(st.st_mode)) {
+        return SDL_FALSE;
+    }
+    #else
+    struct stat st;
+    if (fstat(fileno(f), &st) < 0 || !S_ISREG(st.st_mode)) {
+        return SDL_FALSE;
+    }
+    #endif
+    return SDL_TRUE;
+}
+#endif
+
 SDL_RWops *SDL_RWFromFile(const char *file, const char *mode)
 {
     SDL_RWops *rwops = NULL;
@@ -536,6 +555,11 @@ SDL_RWops *SDL_RWFromFile(const char *file, const char *mode)
     if (*file == '/') {
         FILE *fp = fopen(file, mode);
         if (fp) {
+            if (!SDL_IsRegularFile(fp)) {
+                fclose(fp);
+                SDL_SetError("%s is not a regular file", file);
+                return NULL;
+            }
             return SDL_RWFromFP(fp, 1);
         }
     } else {
@@ -551,6 +575,11 @@ SDL_RWops *SDL_RWFromFile(const char *file, const char *mode)
             fp = fopen(path, mode);
             SDL_stack_free(path);
             if (fp) {
+                if (!SDL_IsRegularFile(fp)) {
+                    fclose(fp);
+                    SDL_SetError("%s is not a regular file", path);
+                    return NULL;
+                }
                 return SDL_RWFromFP(fp, 1);
             }
         }
@@ -604,6 +633,10 @@ SDL_RWops *SDL_RWFromFile(const char *file, const char *mode)
 #endif
         if (!fp) {
             SDL_SetError("Couldn't open %s", file);
+        } else if (!SDL_IsRegularFile(fp)) {
+            fclose(fp);
+            fp = NULL;
+            SDL_SetError("%s is not a regular file", file);
         } else {
             rwops = SDL_RWFromFP(fp, SDL_TRUE);
         }