Fix getdelim(3).

This commit is contained in:
Jonas 'Sortie' Termansen 2015-05-11 15:49:54 +02:00
parent 86c5bc52b3
commit f3e4be0d83
8 changed files with 48 additions and 39 deletions

View File

@ -53,7 +53,10 @@ char* read_single_line(FILE* fp)
size_t ret_size = 0; size_t ret_size = 0;
ssize_t ret_length = getline(&ret, &ret_size, fp); ssize_t ret_length = getline(&ret, &ret_size, fp);
if ( ret_length < 0 ) if ( ret_length < 0 )
{
free(ret);
return NULL; return NULL;
}
if ( ret_length && ret[ret_length-1] == '\n' ) if ( ret_length && ret[ret_length-1] == '\n' )
ret[--ret_length] = '\0'; ret[--ret_length] = '\0';
return ret; return ret;

View File

@ -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. This file is part of the Sortix C Library.
@ -22,58 +22,55 @@
*******************************************************************************/ *******************************************************************************/
#include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <limits.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
static const size_t DEFAULT_BUFSIZE = 32UL;
extern "C" ssize_t getdelim(char** lineptr, size_t* n, int delim, FILE* fp) extern "C" ssize_t getdelim(char** lineptr, size_t* n, int delim, FILE* fp)
{ {
if ( !lineptr || (*lineptr && !n) || !fp ) int err = EINVAL;
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;
flockfile(fp); 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 do
{ {
if ( (c = getc_unlocked(fp)) == EOF ) if ( written == (size_t) SSIZE_MAX )
goto failure;
if ( *n <= (size_t) written + 1UL )
{ {
if ( written ) size_t newbufsize = *n ? 2UL * *n : DEFAULT_BUFSIZE;
break;
else
goto cleanup;
}
if ( bufsize <= (size_t) written + 1UL )
{
size_t newbufsize = 2UL * bufsize;
char* newbuf = (char*) realloc(*lineptr, newbufsize); char* newbuf = (char*) realloc(*lineptr, newbufsize);
if ( !newbuf ) if ( !newbuf )
goto cleanup; goto failure;
bufsize = newbufsize;
if ( n )
*n = bufsize;
*lineptr = newbuf; *lineptr = newbuf;
*n = newbufsize;
}
if ( (c = getc_unlocked(fp)) == EOF )
{
if ( !written || feof_unlocked(fp) )
{
funlockfile(fp);
return -1;
}
} }
(*lineptr)[written++] = c; (*lineptr)[written++] = c;
} while ( c != delim ); } while ( c != delim );
funlockfile(fp); funlockfile(fp);
(*lineptr)[written] = 0; (*lineptr)[written] = 0;
return written; return (ssize_t) written;
cleanup:
funlockfile(fp);
if ( malloced )
{
free(*lineptr);
*lineptr = NULL;
}
return -1;
} }

View File

@ -270,6 +270,7 @@ void string_array_append_file(string_array_t* sa, FILE* fp)
entry[entry_length-1] = '\0'; entry[entry_length-1] = '\0';
string_array_append(sa, entry); string_array_append(sa, entry);
} }
free(entry);
} }
bool string_array_append_file_path(string_array_t* sa, const char* path) 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; continue;
string_array_append(sa, entry); string_array_append(sa, entry);
} }
free(entry);
} }
bool dictionary_append_file_path(string_array_t* sa, const char* path) 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; size_t ret_size = 0;
ssize_t ret_len = getline(&ret, &ret_size, fp); ssize_t ret_len = getline(&ret, &ret_size, fp);
if ( ret_len < 0 ) if ( ret_len < 0 )
{
free(ret);
return NULL; return NULL;
}
if ( ret_len && ret[ret_len-1] == '\n' ) if ( ret_len && ret[ret_len-1] == '\n' )
ret[ret_len-1] = '\0'; ret[ret_len-1] = '\0';
return ret; return ret;

View File

@ -26,6 +26,7 @@
#include <errno.h> #include <errno.h>
#include <error.h> #include <error.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@ -96,6 +97,7 @@ int main(int /*argc*/, char* argv[])
fflush(stdout); fflush(stdout);
mode = next_mode; mode = next_mode;
} }
free(line);
int status; int status;
waitpid(child_pid, &status, 0); waitpid(child_pid, &status, 0);
return WEXITSTATUS(status); return WEXITSTATUS(status);

View File

@ -100,10 +100,9 @@ bool append_lines_from_file(FILE* fp,
ssize_t string_length = getline(&string, &string_size, fp); ssize_t string_length = getline(&string, &string_size, fp);
if ( string_length < 0 ) if ( string_length < 0 )
{ {
free(string);
if ( feof(stdin) ) if ( feof(stdin) )
return true; 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 ) if ( errno == 0 )
return true; return true;
error(0, errno, "getline: `%s'", fpname); error(0, errno, "getline: `%s'", fpname);

View File

@ -102,6 +102,7 @@ char* read_line(FILE* fp, const char* fpname, int delim)
ssize_t amount = getdelim(&line, &line_size, delim, fp); ssize_t amount = getdelim(&line, &line_size, delim, fp);
if ( amount < 0 ) if ( amount < 0 )
{ {
free(line);
if ( ferror(fp) ) if ( ferror(fp) )
error(0, errno, "read: `%s'", fpname); error(0, errno, "read: `%s'", fpname);
return NULL; return NULL;

View File

@ -67,6 +67,7 @@ bool processfp(const char* inputname, FILE* fp)
ssize_t linelen = getline(&line, &linesize, fp); ssize_t linelen = getline(&line, &linesize, fp);
if ( linelen < 0 ) if ( linelen < 0 )
{ {
free(line);
if ( feof(fp) ) { break; } if ( feof(fp) ) { break; }
error(1, errno, "error reading line: %s", inputname); error(1, errno, "error reading line: %s", inputname);
} }

View File

@ -38,6 +38,7 @@ char* read_line(FILE* fp, const char* fpname, int delim)
ssize_t amount = getdelim(&line, &line_size, delim, fp); ssize_t amount = getdelim(&line, &line_size, delim, fp);
if ( amount < 0 ) if ( amount < 0 )
{ {
free(line);
if ( ferror(fp) ) if ( ferror(fp) )
error(0, errno, "read: `%s'", fpname); error(0, errno, "read: `%s'", fpname);
return NULL; return NULL;