From f3e4be0d83022d9613417f0ca7d8b30cf6ce5b14 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Mon, 11 May 2015 15:49:54 +0200 Subject: [PATCH] Fix getdelim(3). --- init/init.c++ | 3 ++ libc/stdio/getdelim.cpp | 71 ++++++++++++++++++++--------------------- tix/util.h | 5 +++ utils/colormake.cpp | 2 ++ utils/column.cpp | 3 +- utils/sort.cpp | 1 + utils/tail.cpp | 1 + utils/uniq.cpp | 1 + 8 files changed, 48 insertions(+), 39 deletions(-) diff --git a/init/init.c++ b/init/init.c++ index d616dfae..d30f5f3f 100644 --- a/init/init.c++ +++ b/init/init.c++ @@ -53,7 +53,10 @@ char* read_single_line(FILE* fp) size_t ret_size = 0; ssize_t ret_length = getline(&ret, &ret_size, fp); if ( ret_length < 0 ) + { + free(ret); return NULL; + } if ( ret_length && ret[ret_length-1] == '\n' ) ret[--ret_length] = '\0'; return ret; diff --git a/libc/stdio/getdelim.cpp b/libc/stdio/getdelim.cpp index f6d9cf94..1dfe5d88 100644 --- a/libc/stdio/getdelim.cpp +++ b/libc/stdio/getdelim.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014, 2015. This file is part of the Sortix C Library. @@ -22,58 +22,55 @@ *******************************************************************************/ +#include + #include +#include #include #include +static const size_t DEFAULT_BUFSIZE = 32UL; + extern "C" ssize_t getdelim(char** lineptr, size_t* n, int delim, FILE* fp) { - if ( !lineptr || (*lineptr && !n) || !fp ) - return errno = EINVAL, -1; - const size_t DEFAULT_BUFSIZE = 32UL; - bool malloced = !*lineptr; - if ( malloced ) - *lineptr = (char*) malloc(DEFAULT_BUFSIZE); - if ( !*lineptr ) - return -1; - size_t bufsize = malloced ? DEFAULT_BUFSIZE : *n; - if ( n ) - *n = bufsize; - ssize_t written = 0; - int c; + int err = EINVAL; flockfile(fp); + if ( !lineptr || !n ) + { + failure: + fp->flags |= _FILE_STATUS_ERROR; + funlockfile(fp); + return errno = err, -1; + } + err = ENOMEM; + if ( !*lineptr ) + *n = 0; + size_t written = 0; + int c; do { - if ( (c = getc_unlocked(fp)) == EOF ) + if ( written == (size_t) SSIZE_MAX ) + goto failure; + if ( *n <= (size_t) written + 1UL ) { - if ( written ) - break; - else - goto cleanup; - } - if ( bufsize <= (size_t) written + 1UL ) - { - size_t newbufsize = 2UL * bufsize; + size_t newbufsize = *n ? 2UL * *n : DEFAULT_BUFSIZE; char* newbuf = (char*) realloc(*lineptr, newbufsize); if ( !newbuf ) - goto cleanup; - bufsize = newbufsize; - if ( n ) - *n = bufsize; + goto failure; *lineptr = newbuf; + *n = newbufsize; + } + if ( (c = getc_unlocked(fp)) == EOF ) + { + if ( !written || feof_unlocked(fp) ) + { + funlockfile(fp); + return -1; + } } (*lineptr)[written++] = c; } while ( c != delim ); funlockfile(fp); (*lineptr)[written] = 0; - return written; - -cleanup: - funlockfile(fp); - if ( malloced ) - { - free(*lineptr); - *lineptr = NULL; - } - return -1; + return (ssize_t) written; } diff --git a/tix/util.h b/tix/util.h index 843cbacf..e9f0551f 100644 --- a/tix/util.h +++ b/tix/util.h @@ -270,6 +270,7 @@ void string_array_append_file(string_array_t* sa, FILE* fp) entry[entry_length-1] = '\0'; string_array_append(sa, entry); } + free(entry); } bool string_array_append_file_path(string_array_t* sa, const char* path) @@ -355,6 +356,7 @@ void dictionary_append_file(string_array_t* sa, FILE* fp) continue; string_array_append(sa, entry); } + free(entry); } bool dictionary_append_file_path(string_array_t* sa, const char* path) @@ -384,7 +386,10 @@ char* read_single_line(FILE* fp) size_t ret_size = 0; ssize_t ret_len = getline(&ret, &ret_size, fp); if ( ret_len < 0 ) + { + free(ret); return NULL; + } if ( ret_len && ret[ret_len-1] == '\n' ) ret[ret_len-1] = '\0'; return ret; diff --git a/utils/colormake.cpp b/utils/colormake.cpp index fb362a77..a41348c2 100644 --- a/utils/colormake.cpp +++ b/utils/colormake.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -96,6 +97,7 @@ int main(int /*argc*/, char* argv[]) fflush(stdout); mode = next_mode; } + free(line); int status; waitpid(child_pid, &status, 0); return WEXITSTATUS(status); diff --git a/utils/column.cpp b/utils/column.cpp index 000a6f29..ec847f55 100644 --- a/utils/column.cpp +++ b/utils/column.cpp @@ -100,10 +100,9 @@ bool append_lines_from_file(FILE* fp, ssize_t string_length = getline(&string, &string_size, fp); if ( string_length < 0 ) { + free(string); if ( feof(stdin) ) return true; - // TODO: HACK: Unfortunately feof(stdin) isn't always true in the - // normal EOF case due to a getline/getdelim bug. if ( errno == 0 ) return true; error(0, errno, "getline: `%s'", fpname); diff --git a/utils/sort.cpp b/utils/sort.cpp index 5c9cf412..8450c089 100644 --- a/utils/sort.cpp +++ b/utils/sort.cpp @@ -102,6 +102,7 @@ char* read_line(FILE* fp, const char* fpname, int delim) ssize_t amount = getdelim(&line, &line_size, delim, fp); if ( amount < 0 ) { + free(line); if ( ferror(fp) ) error(0, errno, "read: `%s'", fpname); return NULL; diff --git a/utils/tail.cpp b/utils/tail.cpp index dbbe52a1..71ace30b 100644 --- a/utils/tail.cpp +++ b/utils/tail.cpp @@ -67,6 +67,7 @@ bool processfp(const char* inputname, FILE* fp) ssize_t linelen = getline(&line, &linesize, fp); if ( linelen < 0 ) { + free(line); if ( feof(fp) ) { break; } error(1, errno, "error reading line: %s", inputname); } diff --git a/utils/uniq.cpp b/utils/uniq.cpp index ac570529..82ccd65c 100644 --- a/utils/uniq.cpp +++ b/utils/uniq.cpp @@ -38,6 +38,7 @@ char* read_line(FILE* fp, const char* fpname, int delim) ssize_t amount = getdelim(&line, &line_size, delim, fp); if ( amount < 0 ) { + free(line); if ( ferror(fp) ) error(0, errno, "read: `%s'", fpname); return NULL;