Fix elf loader range checking
[qemu] / qemu-option.c
1 /*
2  * Commandline option parsing functions
3  *
4  * Copyright (c) 2003-2008 Fabrice Bellard
5  * Copyright (c) 2009 Kevin Wolf <kwolf@redhat.com>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25
26 #include <stdio.h>
27 #include <string.h>
28
29 #include "qemu-common.h"
30 #include "qemu-option.h"
31
32 /*
33  * Extracts the name of an option from the parameter string (p points at the
34  * first byte of the option name)
35  *
36  * The option name is delimited by delim (usually , or =) or the string end
37  * and is copied into buf. If the option name is longer than buf_size, it is
38  * truncated. buf is always zero terminated.
39  *
40  * The return value is the position of the delimiter/zero byte after the option
41  * name in p.
42  */
43 const char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
44 {
45     char *q;
46
47     q = buf;
48     while (*p != '\0' && *p != delim) {
49         if (q && (q - buf) < buf_size - 1)
50             *q++ = *p;
51         p++;
52     }
53     if (q)
54         *q = '\0';
55
56     return p;
57 }
58
59 /*
60  * Extracts the value of an option from the parameter string p (p points at the
61  * first byte of the option value)
62  *
63  * This function is comparable to get_opt_name with the difference that the
64  * delimiter is fixed to be comma which starts a new option. To specify an
65  * option value that contains commas, double each comma.
66  */
67 const char *get_opt_value(char *buf, int buf_size, const char *p)
68 {
69     char *q;
70
71     q = buf;
72     while (*p != '\0') {
73         if (*p == ',') {
74             if (*(p + 1) != ',')
75                 break;
76             p++;
77         }
78         if (q && (q - buf) < buf_size - 1)
79             *q++ = *p;
80         p++;
81     }
82     if (q)
83         *q = '\0';
84
85     return p;
86 }
87
88 /*
89  * Searches an option list for an option with the given name
90  */
91 QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list,
92     const char *name)
93 {
94     while (list && list->name) {
95         if (!strcmp(list->name, name)) {
96             return list;
97         }
98         list++;
99     }
100
101     return NULL;
102 }
103
104 /*
105  * Sets the value of a parameter in a given option list. The parsing of the
106  * value depends on the type of option:
107  *
108  * OPT_FLAG (uses value.n):
109  *      If no value is given, the flag is set to 1.
110  *      Otherwise the value must be "on" (set to 1) or "off" (set to 0)
111  *
112  * OPT_STRING (uses value.s):
113  *      value is strdup()ed and assigned as option value
114  *
115  * OPT_SIZE (uses value.n):
116  *      The value is converted to an integer. Suffixes for kilobytes etc. are
117  *      allowed (powers of 1024).
118  *
119  * Returns 0 on succes, -1 in error cases
120  */
121 int set_option_parameter(QEMUOptionParameter *list, const char *name,
122     const char *value)
123 {
124     // Find a matching parameter
125     list = get_option_parameter(list, name);
126     if (list == NULL) {
127         fprintf(stderr, "Unknown option '%s'\n", name);
128         return -1;
129     }
130
131     // Process parameter
132     switch (list->type) {
133     case OPT_FLAG:
134         if (value != NULL) {
135             if (!strcmp(value, "on")) {
136                 list->value.n = 1;
137             } else if (!strcmp(value, "off")) {
138                 list->value.n = 0;
139             } else {
140                 fprintf(stderr, "Option '%s': Use 'on' or 'off'\n", name);
141                 return -1;
142             }
143         } else {
144             list->value.n = 1;
145         }
146         break;
147
148     case OPT_STRING:
149         if (value != NULL) {
150             list->value.s = strdup(value);
151         } else {
152             fprintf(stderr, "Option '%s' needs a parameter\n", name);
153             return -1;
154         }
155         break;
156
157     case OPT_SIZE:
158         if (value != NULL) {
159             double sizef = strtod(value, (char**) &value);
160
161             switch (*value) {
162             case 'T':
163                 sizef *= 1024;
164             case 'G':
165                 sizef *= 1024;
166             case 'M':
167                 sizef *= 1024;
168             case 'K':
169             case 'k':
170                 sizef *= 1024;
171             case 'b':
172             case '\0':
173                 list->value.n = (uint64_t) sizef;
174                 break;
175             default:
176                 fprintf(stderr, "Option '%s' needs size as parameter\n", name);
177                 fprintf(stderr, "You may use k, M, G or T suffixes for "
178                     "kilobytes, megabytes, gigabytes and terabytes.\n");
179                 return -1;
180             }
181         } else {
182             fprintf(stderr, "Option '%s' needs a parameter\n", name);
183             return -1;
184         }
185         break;
186     default:
187         fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name);
188         return -1;
189     }
190
191     return 0;
192 }
193
194 /*
195  * Sets the given parameter to an integer instead of a string.
196  * This function cannot be used to set string options.
197  *
198  * Returns 0 on success, -1 in error cases
199  */
200 int set_option_parameter_int(QEMUOptionParameter *list, const char *name,
201     uint64_t value)
202 {
203     // Find a matching parameter
204     list = get_option_parameter(list, name);
205     if (list == NULL) {
206         fprintf(stderr, "Unknown option '%s'\n", name);
207         return -1;
208     }
209
210     // Process parameter
211     switch (list->type) {
212     case OPT_FLAG:
213     case OPT_NUMBER:
214     case OPT_SIZE:
215         list->value.n = value;
216         break;
217
218     default:
219         return -1;
220     }
221
222     return 0;
223 }
224
225 /*
226  * Frees a option list. If it contains strings, the strings are freed as well.
227  */
228 void free_option_parameters(QEMUOptionParameter *list)
229 {
230     QEMUOptionParameter *cur = list;
231
232     while (cur && cur->name) {
233         if (cur->type == OPT_STRING) {
234             free(cur->value.s);
235         }
236         cur++;
237     }
238
239     free(list);
240 }
241
242 /*
243  * Parses a parameter string (param) into an option list (dest).
244  *
245  * list is the templace is. If dest is NULL, a new copy of list is created for
246  * it. If list is NULL, this function fails.
247  *
248  * A parameter string consists of one or more parameters, separated by commas.
249  * Each parameter consists of its name and possibly of a value. In the latter
250  * case, the value is delimited by an = character. To specify a value which
251  * contains commas, double each comma so it won't be recognized as the end of
252  * the parameter.
253  *
254  * For more details of the parsing see above.
255  *
256  * Returns a pointer to the first element of dest (or the newly allocated copy)
257  * or NULL in error cases
258  */
259 QEMUOptionParameter *parse_option_parameters(const char *param,
260     QEMUOptionParameter *list, QEMUOptionParameter *dest)
261 {
262     QEMUOptionParameter *cur;
263     QEMUOptionParameter *allocated = NULL;
264     char name[256];
265     char value[256];
266     char *param_delim, *value_delim;
267     char next_delim;
268     size_t num_options;
269
270     if (list == NULL) {
271         return NULL;
272     }
273
274     if (dest == NULL) {
275         // Count valid options
276         num_options = 0;
277         cur = list;
278         while (cur->name) {
279             num_options++;
280             cur++;
281         }
282
283         // Create a copy of the option list to fill in values
284         dest = qemu_mallocz((num_options + 1) * sizeof(QEMUOptionParameter));
285         allocated = dest;
286         memcpy(dest, list, (num_options + 1) * sizeof(QEMUOptionParameter));
287     }
288
289     while (*param) {
290
291         // Find parameter name and value in the string
292         param_delim = strchr(param, ',');
293         value_delim = strchr(param, '=');
294
295         if (value_delim && (value_delim < param_delim || !param_delim)) {
296             next_delim = '=';
297         } else {
298             next_delim = ',';
299             value_delim = NULL;
300         }
301
302         param = get_opt_name(name, sizeof(name), param, next_delim);
303         if (value_delim) {
304             param = get_opt_value(value, sizeof(value), param + 1);
305         }
306         if (*param != '\0') {
307             param++;
308         }
309
310         // Set the parameter
311         if (set_option_parameter(dest, name, value_delim ? value : NULL)) {
312             goto fail;
313         }
314     }
315
316     return dest;
317
318 fail:
319     // Only free the list if it was newly allocated
320     free_option_parameters(allocated);
321     return NULL;
322 }
323
324 /*
325  * Prints all options of a list that have a value to stdout
326  */
327 void print_option_parameters(QEMUOptionParameter *list)
328 {
329     while (list && list->name) {
330         switch (list->type) {
331             case OPT_STRING:
332                  if (list->value.s != NULL) {
333                      printf("%s='%s' ", list->name, list->value.s);
334                  }
335                 break;
336             case OPT_FLAG:
337                 printf("%s=%s ", list->name, list->value.n ? "on" : "off");
338                 break;
339             case OPT_SIZE:
340             case OPT_NUMBER:
341                 printf("%s=%" PRId64 " ", list->name, list->value.n);
342                 break;
343             default:
344                 printf("%s=(unkown type) ", list->name);
345                 break;
346         }
347         list++;
348     }
349 }