Previously key=value on the command line allowed the key to be pretty
much anything that didn't contain an '=' character. Even empty
strings were permitted.
This tightens up the permitted keys so they must contain only ASCII
alphanumeric, period, underscore or dash characters, and must not be
an empty string.
---
docs/nbdkit-plugin.pod | 18 ++++++++++--------
src/main.c | 32 +++++++++++++++++++++++++++++++-
2 files changed, 41 insertions(+), 9 deletions(-)
diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod
index 570a142..b37cac1 100644
--- a/docs/nbdkit-plugin.pod
+++ b/docs/nbdkit-plugin.pod
@@ -376,15 +376,17 @@ optional list of C<key=value> arguments. These are passed to
the
plugin through this callback when the plugin is first loaded and
before any connections are accepted.
-This callback may be called zero or more times. Both C<key> and
-C<value> parameters will be non-NULL, but it is possible for either to
-be empty strings. The strings are owned by nbdkit but will remain
-valid for the lifetime of the plugin, so the plugin does not need to
-copy them.
+This callback may be called zero or more times.
-The format of the C<key> accepted by plugins is up to the plugin, but
-you should probably look at other plugins and follow the same
-conventions.
+Both C<key> and C<value> parameters will be non-NULL. They key will
+be a non-empty string containing only ASCII alphanumeric plus period,
+underscore or dash characters (C<A-Z> C<a-z> C<0-9> C<.>
C<_> C<->).
+The value may be an arbitrary string, including an empty string. The
+strings are owned by nbdkit but will remain valid for the lifetime of
+the plugin, so the plugin does not need to copy them.
+
+The names of C<key>s accepted by plugins is up to the plugin, but you
+should probably look at other plugins and follow the same conventions.
If the value is a relative path, then note that the server changes
directory when it starts up. See L</FILENAMES AND PATHS> above.
diff --git a/src/main.c b/src/main.c
index 9c18d6f..c523854 100644
--- a/src/main.c
+++ b/src/main.c
@@ -72,6 +72,7 @@ static void fork_into_background (void);
static uid_t parseuser (const char *);
static gid_t parsegroup (const char *);
static unsigned int get_socket_activation (void);
+static int is_config_key (const char *key, size_t len);
struct debug_flag *debug_flags; /* -D */
int exit_with_parent; /* --exit-with-parent */
@@ -694,7 +695,7 @@ main (int argc, char *argv[])
magic_config_key = backend->magic_config_key (backend);
for (i = 0; optind < argc; ++i, ++optind) {
p = strchr (argv[optind], '=');
- if (p) { /* key=value */
+ if (p && is_config_key (argv[optind], p - argv[optind])) { /* key=value */
*p = '\0';
backend->config (backend, argv[optind], p+1);
}
@@ -1281,3 +1282,32 @@ get_socket_activation (void)
return nr_fds;
}
+
+/* When parsing plugin and filter config key=value from the command
+ * line, check that the key is a simple alphanumeric with period,
+ * underscore or dash.
+ *
+ * Note this doesn't return an error. If the key is not valid then we
+ * return false and the parsing code will assume that this is a bare
+ * value instead.
+ */
+static int
+is_config_key (const char *key, size_t len)
+{
+ const char allowed[] =
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789"
+ "._-";
+ size_t i;
+
+ if (key[0] == '\0')
+ return 0;
+
+ for (i = 0; i < len; ++i) {
+ if (strchr (allowed, key[i]) == NULL)
+ return 0;
+ }
+
+ return 1;
+}
--
2.18.0