From 4ed7de537b0ee60821f65324208216fcc32d5016 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 13 Sep 2024 15:18:14 -0400 Subject: [PATCH] Stat file first to check directory --- include/prism/util/pm_string.h | 3 +++ src/util/pm_string.c | 37 ++++++++++++++++++++-------------- test/prism/api/parse_test.rb | 1 - 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/include/prism/util/pm_string.h b/include/prism/util/pm_string.h index 6ba327b247..f99f1abdf3 100644 --- a/include/prism/util/pm_string.h +++ b/include/prism/util/pm_string.h @@ -22,6 +22,9 @@ #include #include #include +#elif defined(PRISM_HAS_FILESYSTEM) +#include +#include #endif /** diff --git a/src/util/pm_string.c b/src/util/pm_string.c index 99a27ede4d..7e56dec9f7 100644 --- a/src/util/pm_string.c +++ b/src/util/pm_string.c @@ -254,38 +254,45 @@ pm_string_file_init(pm_string_t *string, const char *filepath) { *string = (pm_string_t) { .type = PM_STRING_OWNED, .source = source, .length = (size_t) file_size }; return PM_STRING_INIT_SUCCESS; #elif defined(PRISM_HAS_FILESYSTEM) - FILE *file = fopen(filepath, "rb"); - if (file == NULL) { + // Open the file for reading + int fd = open(filepath, O_RDONLY); + if (fd == -1) { return PM_STRING_INIT_ERROR_GENERIC; } - fseek(file, 0, SEEK_END); - long file_size = ftell(file); - - if (file_size == -1) { - fclose(file); + // Stat the file to get the file size + struct stat sb; + if (fstat(fd, &sb) == -1) { + close(fd); return PM_STRING_INIT_ERROR_GENERIC; } - if (file_size == 0) { - fclose(file); + // Ensure it is a file and not a directory + if (S_ISDIR(sb.st_mode)) { + close(fd); + return PM_STRING_INIT_ERROR_DIRECTORY; + } + + // Check the size to see if it's empty + size_t size = (size_t) sb.st_size; + if (size == 0) { + close(fd); const uint8_t source[] = ""; *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 }; return PM_STRING_INIT_SUCCESS; } - size_t length = (size_t) file_size; + size_t length = (size_t) size; uint8_t *source = xmalloc(length); if (source == NULL) { - fclose(file); + close(fd); return PM_STRING_INIT_ERROR_GENERIC; } - fseek(file, 0, SEEK_SET); - size_t bytes_read = fread(source, length, 1, file); - fclose(file); + long bytes_read = (long) read(fd, source, length); + close(fd); - if (bytes_read != 1) { + if (bytes_read == -1) { xfree(source); return PM_STRING_INIT_ERROR_GENERIC; } diff --git a/test/prism/api/parse_test.rb b/test/prism/api/parse_test.rb index 49a2b2bfb9..19c1feabb1 100644 --- a/test/prism/api/parse_test.rb +++ b/test/prism/api/parse_test.rb @@ -87,7 +87,6 @@ def test_parse_directory rescue SystemCallError => error end - return if error.nil? || error.is_a?(Errno::ENOMEM) assert_kind_of Errno::EISDIR, error end