From cbfba4b3756d389eec103c88939d699bd95567b8 Mon Sep 17 00:00:00 2001 From: zerico <71151164+ZERICO2005@users.noreply.github.com> Date: Mon, 8 Jun 2026 13:26:16 -0600 Subject: [PATCH] Fixed file and dereferencing bugs --- src/libc/clearerr.c | 8 +++--- src/libc/fclose.c | 13 +++++++--- src/libc/feof.c | 4 +++ src/libc/ferror.c | 4 +++ src/libc/fgetc.c | 19 ++++----------- src/libc/fopen.c | 3 +-- src/libc/fputc.c | 27 ++++++--------------- src/libc/fread.c | 17 +++++++------ src/libc/fseek.c | 5 ++-- src/libc/ftell.c | 4 +-- src/libc/fwrite.c | 21 ++++++++-------- src/libc/include/stdio.h | 4 +-- src/libc/rewind.c | 5 ++++ test/standalone/asprintf_fprintf/src/main.c | 21 +++++++++------- 14 files changed, 81 insertions(+), 74 deletions(-) diff --git a/src/libc/clearerr.c b/src/libc/clearerr.c index 7f0847a60..dc788a0f6 100644 --- a/src/libc/clearerr.c +++ b/src/libc/clearerr.c @@ -1,5 +1,7 @@ #include "__fileioc_stdio.h" +#include + void __attribute__((weak)) clearerr(FILE *stream) { if (stream == NULL || @@ -9,7 +11,7 @@ void __attribute__((weak)) clearerr(FILE *stream) { return; } - - _file_streams[stream->slot].eof = 0; - _file_streams[stream->slot].err = 0; + uint8_t index = stream->slot - 1; + _file_streams[index].eof = 0; + _file_streams[index].err = 0; } diff --git a/src/libc/fclose.c b/src/libc/fclose.c index f513a9c41..205593f46 100644 --- a/src/libc/fclose.c +++ b/src/libc/fclose.c @@ -1,5 +1,7 @@ #include "__fileioc_stdio.h" +#include + int __attribute__((weak)) fclose(FILE *stream) { ti_var_t slot; @@ -14,8 +16,13 @@ int __attribute__((weak)) fclose(FILE *stream) slot = stream->slot; - _file_streams[slot - 1].slot = 0; - int status = ti_Close(slot); - return (status == 0) ? EOF : 0; + if (status == 0) + { + // failed to close file + return EOF; + } + uint8_t index = slot - 1; + _file_streams[index].slot = 0; + return 0; } diff --git a/src/libc/feof.c b/src/libc/feof.c index 51b385126..33bb85304 100644 --- a/src/libc/feof.c +++ b/src/libc/feof.c @@ -2,5 +2,9 @@ int __attribute__((weak)) feof(FILE *stream) { + if (stream == NULL || stream == stdin || stream == stdout || stream == stderr) + { + return 0; + } return stream->eof; } diff --git a/src/libc/ferror.c b/src/libc/ferror.c index 8b97b3620..6cd51f4b0 100644 --- a/src/libc/ferror.c +++ b/src/libc/ferror.c @@ -2,5 +2,9 @@ int __attribute__((weak)) ferror(FILE *stream) { + if (stream == NULL || stream == stdin || stream == stdout || stream == stderr) + { + return 0; + } return stream->err; } diff --git a/src/libc/fgetc.c b/src/libc/fgetc.c index a744f97ab..7a681819b 100644 --- a/src/libc/fgetc.c +++ b/src/libc/fgetc.c @@ -2,26 +2,17 @@ int __attribute__((weak)) fgetc(FILE *stream) { - int c; - - if (stream == NULL) + if (stream == NULL || stream == stdout || stream == stderr) { return EOF; } - - if (stream == stdout || stream == stderr) - { - c = EOF; - } - else if (stream == stdin) + if (stream == stdin) { - c = getchar(); - } - else - { - c = ti_GetC(stream->slot); + return getchar(); } + int c = ti_GetC(stream->slot); + if (c == EOF) { stream->eof = 1; diff --git a/src/libc/fopen.c b/src/libc/fopen.c index 91c66333c..40088650a 100644 --- a/src/libc/fopen.c +++ b/src/libc/fopen.c @@ -5,7 +5,6 @@ FILE* __attribute__((weak)) fopen(const char *__restrict filename, const char *__restrict mode) { ti_var_t slot; - uint8_t index; slot = ti_Open(filename, mode); if (slot == 0) @@ -13,7 +12,7 @@ FILE* __attribute__((weak)) fopen(const char *__restrict filename, const char *_ return NULL; } - index = slot - 1; + uint8_t index = slot - 1; _file_streams[index].slot = slot; _file_streams[index].eof = 0; _file_streams[index].err = 0; diff --git a/src/libc/fputc.c b/src/libc/fputc.c index c9deaa1b6..4c6591dd2 100644 --- a/src/libc/fputc.c +++ b/src/libc/fputc.c @@ -2,32 +2,21 @@ int __attribute__((weak)) fputc(int c, FILE *stream) { - int ret; - - if (stream == NULL) + if (stream == NULL || stream == stdin) { return EOF; } - - if (stream == stdin) + if (stream == stdout || stream == stderr) { - ret = EOF; - } - else if (stream == stdout || stream == stderr) - { - ret = putchar(c); - } - else - { - ret = ti_PutC((char)c, stream->slot); + return putchar(c); } + int ret = ti_PutC((char)c, stream->slot); + /* + * `ti_PutC` returns `(unsigned char)c` or `EOF` so we can skip testing for + * the case of `ret != (unsigned char)c` + */ if (ret == EOF) - { - stream->eof = 1; - } - - if (ret != c) { stream->err = 1; } diff --git a/src/libc/fread.c b/src/libc/fread.c index ca8abaf78..1d0ac6c6f 100644 --- a/src/libc/fread.c +++ b/src/libc/fread.c @@ -2,11 +2,12 @@ size_t __attribute__((weak)) fread(void *ptr, size_t size, size_t count, FILE *__restrict stream) { - size_t ncount; - - if (stream == NULL || - stream == stdout || - stream == stderr) + if (stream == NULL || stream == stdout || stream == stderr) + { + return 0; + } + // If size or count is zero, fread returns zero and performs no other action. + if (size == 0 || count == 0) { return 0; } @@ -16,6 +17,7 @@ size_t __attribute__((weak)) fread(void *ptr, size_t size, size_t count, FILE *_ int c; char *p = ptr; size_t len = size * count; + size_t bytes_read = 0; for (; len > 0; len--) { @@ -24,12 +26,13 @@ size_t __attribute__((weak)) fread(void *ptr, size_t size, size_t count, FILE *_ break; } *p++ = (char)c; + bytes_read++; } - return count; + return bytes_read / size; } - ncount = ti_Read(ptr, size, count, stream->slot); + size_t ncount = ti_Read(ptr, size, count, stream->slot); if (ncount != count) { stream->err = 1; diff --git a/src/libc/fseek.c b/src/libc/fseek.c index 1b205e3d7..df1010333 100644 --- a/src/libc/fseek.c +++ b/src/libc/fseek.c @@ -1,6 +1,6 @@ #include "__fileioc_stdio.h" -int __attribute__((weak)) fseek(FILE *stream, long int offset, int origin) +int __attribute__((weak)) fseek(FILE *stream, long offset, int origin) { if (stream == NULL || stream == stdin || @@ -9,6 +9,5 @@ int __attribute__((weak)) fseek(FILE *stream, long int offset, int origin) { return -1; } - - return ti_Seek((int)offset, origin, stream->slot); + return (ti_Seek((int)offset, origin, stream->slot) == EOF) ? -1 : 0; } diff --git a/src/libc/ftell.c b/src/libc/ftell.c index 1e19ed4a4..fd09dbe2d 100644 --- a/src/libc/ftell.c +++ b/src/libc/ftell.c @@ -1,7 +1,7 @@ #include "__fileioc_stdio.h" #include -long int __attribute__((weak)) ftell(FILE *stream) +long __attribute__((weak)) ftell(FILE *stream) { if (stream == NULL || stream == stdin || @@ -14,5 +14,5 @@ long int __attribute__((weak)) ftell(FILE *stream) // ti_Tell shouldn't return a value greater than OS_VAR_MAX_SIZE (65512) unless an error occurs uint16_t ret = ti_Tell(stream->slot); // Convert a result of UINT16_MAX to -1L, leaving other results the same - return ((uint16_t)ret + 1) - 1L; + return (uint16_t)(ret + 1) - 1L; } diff --git a/src/libc/fwrite.c b/src/libc/fwrite.c index ad02a7b74..08827a7d4 100644 --- a/src/libc/fwrite.c +++ b/src/libc/fwrite.c @@ -2,20 +2,21 @@ size_t __attribute__((weak)) fwrite(const void *__restrict ptr, size_t size, size_t count, FILE *__restrict stream) { - size_t ncount; - - if (stream == NULL || - stream == stdin) + if (stream == NULL || stream == stdin) + { + return 0; + } + // If size or count is zero, fwrite returns zero and performs no other action. + if (size == 0 || count == 0) { return 0; } - if (stream == stdout || - stream == stderr) + if (stream == stdout || stream == stderr) { char *p = (char *)ptr; size_t len = size * count; - size_t num = 0; + size_t bytes_written = 0; for (; len > 0; len--) { @@ -23,13 +24,13 @@ size_t __attribute__((weak)) fwrite(const void *__restrict ptr, size_t size, siz { break; } - num++; + bytes_written++; } - return num / size; + return bytes_written / size; } - ncount = ti_Write(ptr, size, count, stream->slot); + size_t ncount = ti_Write(ptr, size, count, stream->slot); if (ncount != count) { stream->err = 1; diff --git a/src/libc/include/stdio.h b/src/libc/include/stdio.h index 3ff03fe76..c877fca39 100644 --- a/src/libc/include/stdio.h +++ b/src/libc/include/stdio.h @@ -61,9 +61,9 @@ size_t fread(void *__restrict ptr, size_t size, size_t count, FILE *__restrict s size_t fwrite(const void *__restrict ptr, size_t size, size_t count, FILE *__restrict stream); -long int ftell(FILE *stream) __attribute__((__warn_unused_result__)); +long ftell(FILE *stream) __attribute__((__warn_unused_result__)); -int fseek(FILE *stream, long int offset, int origin); +int fseek(FILE *stream, long offset, int origin); void rewind(FILE *stream); diff --git a/src/libc/rewind.c b/src/libc/rewind.c index ab42d43c7..bea5389e2 100644 --- a/src/libc/rewind.c +++ b/src/libc/rewind.c @@ -2,6 +2,11 @@ void __attribute__((weak)) rewind(FILE *stream) { + if (stream == NULL || stream == stdin || stream == stdout || stream == stderr) + { + return; + } + stream->eof = 0; (void)fseek(stream, 0L, SEEK_SET); diff --git a/test/standalone/asprintf_fprintf/src/main.c b/test/standalone/asprintf_fprintf/src/main.c index 0150eaed3..074aeaeda 100644 --- a/test/standalone/asprintf_fprintf/src/main.c +++ b/test/standalone/asprintf_fprintf/src/main.c @@ -536,19 +536,20 @@ int memccpy_tests(void) { for (size_t i = 0; i != sizeof terminal; ++i) { void* to = T_memccpy(dest, src, terminal[i], sizeof dest); - fprintf(file, "Terminal '%c' (%s):\t\"", terminal[i], to ? "found" : "absent"); + C(fprintf(file, "Terminal '%c' (%s):\t\"", terminal[i], to ? "found" : "absent") > 0); // if `terminal` character was not found - print the whole `dest` to = to ? to : dest + sizeof dest; for (char* from = dest; from != to; ++from) { - fputc(isprint(*from) ? *from : alt, file); + unsigned char ch = (unsigned char)(isprint(*from) ? *from : alt); + C(fputc((int)ch, file) == (int)ch); } - fputs("\"\n", file); + C(fputs("\"\n", file) >= 0); } - fprintf(file, "%c%s", '\n', "Separate star names from distances (ly):\n"); + C(fprintf(file, "%c%s", '\n', "Separate star names from distances (ly):\n") > 0); const char *star_distance[] = { "Arcturus : 37", "Vega : 25", "Capella : 43", "Rigel : 860", "Procyon : 11" }; @@ -566,14 +567,14 @@ int memccpy_tests(void) { if (first) { *first = '\0'; - fprintf(file, "%s%c", names_only, '\n'); + C(fprintf(file, "%s%c", names_only, '\n') > 0); } else { printf("Error Buffer is too small.\n"); } - fseek(file, 0, SEEK_END); + C(fseek(file, 0, SEEK_END) == 0); int file_size = ftell(file); - fseek(file, 0, SEEK_SET); + C(fseek(file, 0, SEEK_SET) == 0); if (file_size <= 0) { perror("file_size <= 0"); @@ -1687,9 +1688,11 @@ int run_tests(void) { /* nano_fprintf memccpy */ ret = memccpy_tests(); free(buf); buf = NULL; - fclose(file); + if (fclose(file) != 0) { + perror("Could not close file"); + } if (remove(file_name) != 0) { - perror("Couldn't delete file"); + perror("Could not delete file"); } if (ret != 0) { return ret; }