Improve user choices file processing

Improve the key/value processing in choices file.

Fixes several oddities discovered including:
 removing the last character of the last value.
 possible buffer overflow with certian values
This commit is contained in:
Vincent Sanders 2020-06-27 23:24:59 +01:00
parent 402ad02ff5
commit 1dab82d655
1 changed files with 88 additions and 27 deletions

View File

@ -540,6 +540,89 @@ nsoption_free(struct nsoption_s *opts)
}
/**
* extract key/value from a line of input
*
* \retun NSERROR_OK and key_out and value_out updated
* NSERROR_NOT_FOUND if not a key/value input line
* NSERROR_INVALID if the line is and invalid format (missing colon)
*/
static nserror
get_key_value(char *line, int linelen, char **key_out, char **value_out)
{
char *key;
char *value;
/* skip leading whitespace for start of key */
for (key = line; *key != 0; key++) {
if ((*key != ' ') && (*key != '\t') && (*key != '\n')) {
break;
}
}
/* empty line or only whitespace */
if (*key == 0) {
return NSERROR_NOT_FOUND;
}
/* comment */
if (*key == '#') {
return NSERROR_NOT_FOUND;
}
/* get start of value */
for (value = key; *value != 0; value++) {
if (*value == ':') {
*value = 0;
value++;
break;
}
}
/* missing colon separator */
if (*value == 0) {
return NSERROR_INVALID;
}
/* remove delimiter from value */
if (line[linelen - 1] == '\n') {
linelen--;
line[linelen] = 0;
}
*key_out = key;
*value_out = value;
return NSERROR_OK;
}
/**
* Process a line from a user option file
*/
static nserror optionline(struct nsoption_s *opts, char *line, int linelen)
{
nserror res;
char *key;
char *value;
int idx;
res = get_key_value(line, linelen, &key, &value);
if (res != NSERROR_OK) {
/* skip line as no valid key value pair found */
return res;
}
for (idx = 0; opts[idx].key != NULL; idx++) {
if (strcasecmp(key, opts[idx].key) == 0) {
strtooption(value, &opts[idx]);
break;
}
}
return res;
}
/* exported interface documented in utils/nsoption.h */
nserror
nsoption_init(nsoption_set_default_t *set_defaults,
@ -645,7 +728,9 @@ nsoption_read(const char *path, struct nsoption_s *opts)
opts = nsoptions;
}
/** @todo is this and API bug not being a parameter */
/**
* @todo is this an API bug not being a parameter
*/
defs = nsoptions_default;
if ((opts == NULL) || (defs == NULL)) {
@ -658,34 +743,10 @@ nsoption_read(const char *path, struct nsoption_s *opts)
return NSERROR_NOT_FOUND;
}
NSLOG(netsurf, INFO, "Successfully opened '%s' for Options file",
path);
NSLOG(netsurf, INFO, "Successfully opened '%s' for Options file", path);
while (fgets(s, NSOPTION_MAX_LINE_LEN, fp)) {
char *colon, *value;
unsigned int idx;
if ((s[0] == 0) || (s[0] == '#')) {
continue;
}
colon = strchr(s, ':');
if (colon == 0) {
continue;
}
s[strlen(s) - 1] = 0; /* remove \n at end */
*colon = 0; /* terminate key */
value = colon + 1;
for (idx = 0; opts[idx].key != NULL; idx++) {
if (strcasecmp(s, opts[idx].key) != 0) {
continue;
}
strtooption(value, &opts[idx]);
break;
}
optionline(opts, s, strlen(s));
}
fclose(fp);