diff --git a/libc/src/stdio.cpp b/libc/src/stdio.cpp index bc5cc32e..42c2b1c5 100644 --- a/libc/src/stdio.cpp +++ b/libc/src/stdio.cpp @@ -29,6 +29,22 @@ static int fopen_parse_mode(const char* mode) return result; } +static int fdopen_check_compatible_mode(int fd, int new_flags) +{ + int old_flags = fcntl(fd, F_GETFL); + if (old_flags < 0) return -1; + + int old_mode = old_flags & O_ACCMODE; + int new_mode = new_flags & O_ACCMODE; + if ((old_mode & new_mode) != new_mode) + { + errno = EINVAL; + return -1; + } + + return 0; +} + extern "C" { FILE* fopen(const char* path, const char* mode) @@ -59,9 +75,7 @@ extern "C" if ((flags = fopen_parse_mode(mode)) < 0) return nullptr; - // FIXME: We do verify that fd is valid, but not that the mode is compatible. - long rc = lseek(fd, 0, SEEK_CUR); - if (rc < 0) return nullptr; + if (fdopen_check_compatible_mode(fd, flags) < 0) return nullptr; FILE* f = (FILE*)malloc(sizeof(FILE)); if (!f) { return nullptr; }