debuggers.hg

view tools/libxl/libxlu_cfg.c @ 21968:756d770ef599

libxl: free values in XLU_ConfigSetting.

Fixes these valgrind reported leaks, found with "valgrind xl create -n ..."

==21170== 8 bytes in 3 blocks are definitely lost in loss record 1 of 3
==21170== at 0x4022F0A: malloc (vg_replace_malloc.c:236)
==21170== by 0x411B22F: strdup (in /lib/i686/cmov/libc-2.7.so)
==21170== by 0x4030085: xlu__cfgl_strdup (libxlu_cfg.c:290)
==21170== by 0x402F3C4: xlu__cfg_yylex (libxlu_cfg_l.l:37)
==21170== by 0x402DD86: xlu__cfg_yyparse (libxlu_cfg_y.c:1338)
==21170== by 0x40308AE: xlu_cfg_readdata (libxlu_cfg.c:85)
==21170== by 0x804DBE4: parse_config_data (xl_cmdimpl.c:591)
==21170== by 0x8056EE4: create_domain (xl_cmdimpl.c:1381)
==21170== by 0x80582AE: main_create (xl_cmdimpl.c:3178)
==21170== by 0x804B54B: main (xl.c:76)
==21170==
==21170== 57 bytes in 2 blocks are definitely lost in loss record 2 of 3
==21170== at 0x4022F0A: malloc (vg_replace_malloc.c:236)
==21170== by 0x402FE22: xlu__cfgl_dequote (libxlu_cfg.c:307)
==21170== by 0x402F4B4: xlu__cfg_yylex (libxlu_cfg_l.l:52)
==21170== by 0x402DD86: xlu__cfg_yyparse (libxlu_cfg_y.c:1338)
==21170== by 0x40308AE: xlu_cfg_readdata (libxlu_cfg.c:85)
==21170== by 0x804DBE4: parse_config_data (xl_cmdimpl.c:591)
==21170== by 0x8056EE4: create_domain (xl_cmdimpl.c:1381)
==21170== by 0x80582AE: main_create (xl_cmdimpl.c:3178)
==21170== by 0x804B54B: main (xl.c:76)
==21170==
==21170== 111 bytes in 6 blocks are definitely lost in loss record 3 of 3
==21170== at 0x4022F0A: malloc (vg_replace_malloc.c:236)
==21170== by 0x402FE22: xlu__cfgl_dequote (libxlu_cfg.c:307)
==21170== by 0x402F4ED: xlu__cfg_yylex (libxlu_cfg_l.l:56)
==21170== by 0x402DD86: xlu__cfg_yyparse (libxlu_cfg_y.c:1338)
==21170== by 0x40308AE: xlu_cfg_readdata (libxlu_cfg.c:85)
==21170== by 0x804DBE4: parse_config_data (xl_cmdimpl.c:591)
==21170== by 0x8056EE4: create_domain (xl_cmdimpl.c:1381)
==21170== by 0x80582AE: main_create (xl_cmdimpl.c:3178)
==21170== by 0x804B54B: main (xl.c:76)

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
author Ian Campbell <ian.campbell@citrix.com>
date Wed Aug 04 16:00:13 2010 +0100 (2010-08-04)
parents 4405b50cb183
children e9d95f7e75ab
line source
2 #include "libxlu_internal.h"
3 #include "libxlu_cfg_y.h"
4 #include "libxlu_cfg_l.h"
5 #include "libxlu_cfg_i.h"
7 XLU_Config *xlu_cfg_init(FILE *report, const char *report_filename) {
8 XLU_Config *cfg;
10 cfg= malloc(sizeof(*cfg));
11 if (!cfg) return 0;
13 cfg->report= report;
14 cfg->filename= strdup(report_filename);
15 if (!cfg->filename) { free(cfg); return 0; }
17 cfg->settings= 0;
18 return cfg;
19 }
21 int xlu_cfg_readfile(XLU_Config *cfg, const char *real_filename) {
22 CfgParseContext ctx;
23 FILE *f;
24 int e, r;
26 ctx.cfg= cfg;
27 ctx.err= 0;
28 ctx.lexerrlineno= -1;
30 f= fopen(real_filename, "r");
31 if (!f) {
32 e= errno;
33 fprintf(cfg->report,"%s: unable to open configuration file: %s\n",
34 real_filename, strerror(e));
35 return e;
36 }
38 e= xlu__cfg_yylex_init_extra(&ctx, &ctx.scanner);
39 if (e) {
40 fprintf(cfg->report,"%s: unable to create scanner: %s\n",
41 cfg->filename, strerror(e));
42 return e;
43 }
45 xlu__cfg_yyrestart(f, ctx.scanner);
47 r= xlu__cfg_yyparse(&ctx);
48 if (r) assert(ctx.err);
50 xlu__cfg_yylex_destroy(ctx.scanner);
51 fclose(f);
53 return ctx.err;
54 }
56 int xlu_cfg_readdata(XLU_Config *cfg, const char *data, int length) {
57 CfgParseContext ctx;
58 int e, r;
59 YY_BUFFER_STATE buf= 0;
61 ctx.scanner= 0;
62 ctx.cfg= cfg;
63 ctx.err= 0;
64 ctx.lexerrlineno= -1;
66 e= xlu__cfg_yylex_init_extra(&ctx, &ctx.scanner);
67 if (e) {
68 fprintf(cfg->report,"%s: unable to create scanner: %s\n",
69 cfg->filename, strerror(e));
70 ctx.err= e;
71 ctx.scanner= 0;
72 goto xe;
73 }
75 buf = xlu__cfg_yy_scan_bytes(data, length, ctx.scanner);
76 if (!buf) {
77 fprintf(cfg->report,"%s: unable to allocate scanner buffer\n",
78 cfg->filename);
79 ctx.err= ENOMEM;
80 goto xe;
81 }
83 r= xlu__cfg_yyparse(&ctx);
84 if (r) assert(ctx.err);
86 xe:
87 if (buf) xlu__cfg_yy_delete_buffer(buf, ctx.scanner);
88 if (ctx.scanner) xlu__cfg_yylex_destroy(ctx.scanner);
90 return ctx.err;
91 }
93 void xlu__cfg_set_free(XLU_ConfigSetting *set) {
94 int i;
96 free(set->name);
97 for (i=0; i<set->nvalues; i++)
98 free(set->values[i]);
99 free(set->values);
100 free(set);
101 }
103 void xlu_cfg_destroy(XLU_Config *cfg) {
104 XLU_ConfigSetting *set, *set_next;
106 for (set= cfg->settings;
107 set;
108 set= set_next) {
109 set_next= set->next;
110 xlu__cfg_set_free(set);
111 }
112 free(cfg->filename);
113 free(cfg);
114 }
116 static XLU_ConfigSetting *find(const XLU_Config *cfg, const char *n) {
117 XLU_ConfigSetting *set;
119 for (set= cfg->settings;
120 set;
121 set= set->next)
122 if (!strcmp(set->name, n))
123 return set;
124 return 0;
125 }
127 static int find_atom(const XLU_Config *cfg, const char *n,
128 XLU_ConfigSetting **set_r) {
129 XLU_ConfigSetting *set;
131 set= find(cfg,n);
132 if (!set) return ESRCH;
134 if (set->avalues!=1) {
135 fprintf(cfg->report,
136 "%s:%d: warning: parameter `%s' is"
137 " a list but should be a single value\n",
138 cfg->filename, set->lineno, n);
139 return EINVAL;
140 }
141 *set_r= set;
142 return 0;
143 }
145 int xlu_cfg_get_string(const XLU_Config *cfg, const char *n,
146 const char **value_r) {
147 XLU_ConfigSetting *set;
148 int e;
150 e= find_atom(cfg,n,&set); if (e) return e;
151 *value_r= set->values[0];
152 return 0;
153 }
155 int xlu_cfg_get_long(const XLU_Config *cfg, const char *n,
156 long *value_r) {
157 long l;
158 XLU_ConfigSetting *set;
159 int e;
160 char *ep;
162 e= find_atom(cfg,n,&set); if (e) return e;
163 errno= 0; l= strtol(set->values[0], &ep, 0);
164 e= errno;
165 if (errno) {
166 e= errno;
167 assert(e==EINVAL || e==ERANGE);
168 fprintf(cfg->report,
169 "%s:%d: warning: parameter `%s' could not be parsed"
170 " as a number: %s\n",
171 cfg->filename, set->lineno, n, strerror(e));
172 return e;
173 }
174 if (*ep || ep==set->values[0]) {
175 fprintf(cfg->report,
176 "%s:%d: warning: parameter `%s' is not a valid number\n",
177 cfg->filename, set->lineno, n);
178 return EINVAL;
179 }
180 *value_r= l;
181 return 0;
182 }
185 int xlu_cfg_get_list(const XLU_Config *cfg, const char *n,
186 XLU_ConfigList **list_r, int *entries_r) {
187 XLU_ConfigSetting *set;
188 set= find(cfg,n); if (!set) return ESRCH;
189 if (set->avalues==1) {
190 fprintf(cfg->report,
191 "%s:%d: warning: parameter `%s' is a single value"
192 " but should be a list\n",
193 cfg->filename, set->lineno, n);
194 return EINVAL;
195 }
196 if (list_r) *list_r= set;
197 if (entries_r) *entries_r= set->nvalues;
198 return 0;
199 }
201 const char *xlu_cfg_get_listitem(const XLU_ConfigList *set, int entry) {
202 if (entry < 0 || entry >= set->nvalues) return 0;
203 return set->values[entry];
204 }
207 XLU_ConfigSetting *xlu__cfg_set_mk(CfgParseContext *ctx,
208 int alloc, char *atom) {
209 XLU_ConfigSetting *set= 0;
211 if (ctx->err) goto x;
212 assert(!!alloc == !!atom);
214 set= malloc(sizeof(*set));
215 if (!set) goto xe;
217 set->name= 0; /* tbd */
218 set->avalues= alloc;
220 if (!alloc) {
221 set->nvalues= 0;
222 set->values= 0;
223 } else {
224 set->values= malloc(sizeof(*set->values) * alloc);
225 if (!set->values) goto xe;
227 set->nvalues= 1;
228 set->values[0]= atom;
229 }
230 return set;
232 xe:
233 ctx->err= errno;
234 x:
235 free(set);
236 free(atom);
237 return 0;
238 }
240 void xlu__cfg_set_add(CfgParseContext *ctx, XLU_ConfigSetting *set,
241 char *atom) {
242 if (ctx->err) return;
244 assert(atom);
246 if (set->nvalues >= set->avalues) {
247 int new_avalues;
248 char **new_values;
250 if (set->avalues > INT_MAX / 100) { ctx->err= ERANGE; return; }
251 new_avalues= set->avalues * 4;
252 new_values= realloc(set->values,
253 sizeof(*new_values) * new_avalues);
254 if (!new_values) { ctx->err= errno; free(atom); return; }
255 set->values= new_values;
256 set->avalues= new_avalues;
257 }
258 set->values[set->nvalues++]= atom;
259 }
261 void xlu__cfg_set_store(CfgParseContext *ctx, char *name,
262 XLU_ConfigSetting *set, int lineno) {
263 if (ctx->err) return;
265 assert(name);
266 set->name= name;
267 set->lineno= lineno;
268 set->next= ctx->cfg->settings;
269 ctx->cfg->settings= set;
270 }
272 char *xlu__cfgl_strdup(CfgParseContext *ctx, const char *src) {
273 char *result;
275 if (ctx->err) return 0;
276 result= strdup(src);
277 if (!result) ctx->err= errno;
278 return result;
279 }
281 char *xlu__cfgl_dequote(CfgParseContext *ctx, const char *src) {
282 char *result;
283 const char *p;
284 char *q;
285 int len, c, nc;
287 if (ctx->err) return 0;
289 len= strlen(src);
290 assert(len>=2 && src[0]==src[len-1]);
292 result= malloc(len-1);
293 if (!result) { ctx->err= errno; return 0; }
295 q= result;
297 for (p= src+1;
298 p < src+len-1;
299 ) {
300 c= *p++;
301 if (c=='\\') {
302 assert(p < src+len-1);
303 nc= *p++;
304 if (nc=='"' || nc=='\'' || nc=='\\') {
305 *q++= nc;
306 } else if (nc=='a') { *q++= '\007';
307 } else if (nc=='b') { *q++= '\010';
308 } else if (nc=='f') { *q++= '\014';
309 } else if (nc=='n') { *q++= '\n';
310 } else if (nc=='r') { *q++= '\r';
311 } else if (nc=='t') { *q++= '\t';
312 } else if (nc=='v') { *q++= '\013';
313 } else if (nc=='x') {
315 #define NUMERIC_CHAR(minlen,maxlen,base,basetext) do{ \
316 char numbuf[(maxlen)+1], *ep; \
317 unsigned long val; \
318 \
319 strncpy(numbuf,p,(maxlen)); \
320 numbuf[(maxlen)]= 0; \
321 val= strtoul(numbuf, &ep, (base)); \
322 if (ep <= numbuf+(minlen)) { \
323 xlu__cfgl_lexicalerror(ctx,"invalid digit after" \
324 " backslash " basetext "numerical character escape" \
325 " in quoted string"); \
326 ctx->err= EINVAL; \
327 goto x; \
328 } \
329 p += (ep - numbuf); \
330 }while(0)
332 p++;
333 NUMERIC_CHAR(2,2,16,"hex");
334 } else if (nc>='0' && nc<='7') {
335 NUMERIC_CHAR(1,3,10,"octal");
336 }
337 assert(p <= src+len-1);
338 } else {
339 *q++= c;
340 }
341 }
343 x:
344 *q++= 0;
345 return result;
346 }
348 void xlu__cfgl_lexicalerror(CfgParseContext *ctx, char const *msg) {
349 YYLTYPE loc;
350 loc.first_line= xlu__cfg_yyget_lineno(ctx->scanner);
351 xlu__cfg_yyerror(&loc, ctx, msg);
352 ctx->lexerrlineno= loc.first_line;
353 }
355 void xlu__cfg_yyerror(YYLTYPE *loc, CfgParseContext *ctx, char const *msg) {
356 const char *text, *newline;
357 int len, lineno;
359 lineno= loc->first_line;
360 if (lineno <= ctx->lexerrlineno) return;
362 text= xlu__cfg_yyget_text(ctx->scanner);
363 len= xlu__cfg_yyget_leng(ctx->scanner);
364 newline= "";
365 if (len>0 && text[len-1]=='\n') {
366 len--;
367 lineno--;
368 if (!len) {
369 newline= "<newline>";
370 }
371 }
372 while (len>0 && (text[len-1]=='\t' || text[len-1]==' ')) {
373 len--;
374 }
376 fprintf(ctx->cfg->report,
377 "%s:%d: config parsing error near %s%.*s%s%s: %s\n",
378 ctx->cfg->filename, lineno,
379 len?"`":"", len, text, len?"'":"", newline,
380 msg);
381 if (!ctx->err) ctx->err= EINVAL;
382 }