summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2020-06-27 23:24:59 +0100
committerVincent Sanders <vince@kyllikki.org>2020-06-27 23:24:59 +0100
commit1dab82d655b8f54e344f21f062495d5cb35c8c4c (patch)
treeda808c38af9a07e53602c745f7be4c2b1dba705e /utils
parent402ad02ff58d5e755e4cee60bd65e29745d5295a (diff)
downloadnetsurf-1dab82d655b8f54e344f21f062495d5cb35c8c4c.tar.gz
netsurf-1dab82d655b8f54e344f21f062495d5cb35c8c4c.tar.bz2
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
Diffstat (limited to 'utils')
-rw-r--r--utils/nsoption.c115
1 files changed, 88 insertions, 27 deletions
diff --git a/utils/nsoption.c b/utils/nsoption.c
index 6985b3cb8..a8a29b3bf 100644
--- a/utils/nsoption.c
+++ b/utils/nsoption.c
@@ -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);