qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

qemu-img: Move is_valid_option_list() to qemu-img.c and rewrite

is_valid_option_list()'s purpose is ensuring qemu-img.c's can safely
join multiple parameter strings separated by ',' like this:

g_strdup_printf("%s,%s", params1, params2);

How it does that is anything but obvious. A close reading of the code
reveals that it fails exactly when its argument starts with ',' or
ends with an odd number of ','. Makes sense, actually, because when
the argument starts with ',', a separating ',' preceding it would get
escaped, and when it ends with an odd number of ',', a separating ','
following it would get escaped.

Move it to qemu-img.c and rewrite it the obvious way.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20200415074927.19897-9-armbru@redhat.com>

+26 -23
-1
include/qemu/option.h
··· 33 33 void parse_option_size(const char *name, const char *value, 34 34 uint64_t *ret, Error **errp); 35 35 bool has_help_option(const char *param); 36 - bool is_valid_option_list(const char *param); 37 36 38 37 enum QemuOptType { 39 38 QEMU_OPT_STRING = 0, /* no parsing (use string as-is) */
+26
qemu-img.c
··· 223 223 return true; 224 224 } 225 225 226 + /* 227 + * Is @optarg safe for accumulate_options()? 228 + * It is when multiple of them can be joined together separated by ','. 229 + * To make that work, @optarg must not start with ',' (or else a 230 + * separating ',' preceding it gets escaped), and it must not end with 231 + * an odd number of ',' (or else a separating ',' following it gets 232 + * escaped). 233 + */ 234 + static bool is_valid_option_list(const char *optarg) 235 + { 236 + size_t len = strlen(optarg); 237 + size_t i; 238 + 239 + if (optarg[0] == ',') { 240 + return false; 241 + } 242 + 243 + for (i = len; i > 0 && optarg[i - 1] == ','; i--) { 244 + } 245 + if ((len - i) % 2) { 246 + return false; 247 + } 248 + 249 + return true; 250 + } 251 + 226 252 static int accumulate_options(char **options, char *optarg) 227 253 { 228 254 char *new_options;
-22
util/qemu-option.c
··· 165 165 *ret = size; 166 166 } 167 167 168 - bool is_valid_option_list(const char *p) 169 - { 170 - char *value = NULL; 171 - bool result = false; 172 - 173 - while (*p) { 174 - p = get_opt_value(p, &value); 175 - if ((*p && !*++p) || 176 - (!*value || *value == ',')) { 177 - goto out; 178 - } 179 - 180 - g_free(value); 181 - value = NULL; 182 - } 183 - 184 - result = true; 185 - out: 186 - g_free(value); 187 - return result; 188 - } 189 - 190 168 static const char *opt_type_to_string(enum QemuOptType type) 191 169 { 192 170 switch (type) {