From 9e5e0a8a51a0cfc296f6d4284672f515f02cea50 Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Thu, 6 Jul 2017 11:48:02 +0200 Subject: [PATCH] Add string_fget_word function. --- m-string.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/m-string.h b/m-string.h index a9de3ba9..28d27191 100644 --- a/m-string.h +++ b/m-string.h @@ -564,6 +564,40 @@ string_fgets(string_t v, FILE *f, string_fgets_t arg) return retcode; /* Abnormal terminaison */ } +static inline bool +string_fget_word (string_t v, const char separator[], FILE *f) +{ + char buffer[128]; + char c = 0; + assert (1+20+2+strlen(separator)+3 < sizeof buffer); + stringi_fit2size (v, 10); + v->size = 0; + v->ptr[0] = 0; + bool retcode = false; + /* NOTE: We generate a buffer which we give to scanf to parse the string, + that it is to say, we generate the format dynamically! + The format is like " %49[^ \t.\n]%c" + So in this case, we parse up to 49 chars, up to the separators char, + and we read the next char. If the next char is a separator, we successful + read a word, otherwise we have to continue parsing. + The user shall give a constant string as the separator argument, + as a control over this argument may give an attacker + an opportunity for stack overflow */ + while (snprintf(buffer, sizeof buffer -1, " %%%lu[^%s]%%c", (unsigned long) v->alloc-1-v->size, separator) > 0 + && fscanf(f, buffer, &v->ptr[v->size], &c) == 2) { + retcode = true; + v->size += strlen(&v->ptr[v->size]); + if (strchr(separator, c) != NULL) + return retcode; + /* Next char is not a separator: continue parsing */ + v->ptr[v->size++] = c; + v->ptr[v->size] = 0; + stringi_fit2size (v, v->alloc + v->alloc/2); + assert (v->alloc > v->size + 1); + } + return retcode; +} + static inline void string_fputs(FILE *f, const string_t v) {