Bug Summary

File:obj-scan-build/libstore/../../libstore/kids.c
Location:line 204, column 17
Description:Call to 'malloc' has an allocation size of 0 bytes

Annotated Source Code

1/* Managing sub-stores
2
3 Copyright (C) 1995,96,97,2001,02 Free Software Foundation, Inc.
4 Written by Miles Bader <miles@gnu.org>
5
6 This file is part of the GNU Hurd.
7
8 The GNU Hurd is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
12
13 The GNU Hurd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
21
22#include <stdlib.h>
23#include <string.h>
24#include <stdio.h>
25#include <ctype.h>
26
27#include "store.h"
28
29/* Set STORE's current children list to (a copy of) CHILDREN and NUM_CHILDREN. */
30error_t
31store_set_children (struct store *store,
32 struct store *const *children, size_t num_children)
33{
34 unsigned size = num_children * sizeof (struct store *);
35 struct store **copy = malloc (size);
36
37 if (!copy)
38 return ENOMEM((0x10 << 26) | ((12) & 0x3fff));
39
40 if (store->children)
41 free (store->children);
42
43 memcpy (copy, children, size);
44 store->children = copy;
45 store->num_children = num_children;
46
47 return 0;
48}
49
50/* Calls the allocate_encoding method in each child store of STORE,
51 propagating any errors. If any child does not hae such a method,
52 EOPNOTSUPP is returned. */
53error_t
54store_allocate_child_encodings (const struct store *store,
55 struct store_enc *enc)
56{
57 int i;
58 error_t err = 0;
59 for (i = 0; i < store->num_children && !err; i++)
60 {
61 struct store *k = store->children[i];
62 if (k->class->allocate_encoding)
63 (*k->class->allocate_encoding) (k, enc);
64 else
65 err = EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
66 }
67 return err;
68}
69
70/* Calls the encode method in each child store of STORE, propagating any
71 errors. If any child does not hae such a method, EOPNOTSUPP is returned. */
72error_t
73store_encode_children (const struct store *store, struct store_enc *enc)
74{
75 int i;
76 error_t err = 0;
77 for (i = 0; i < store->num_children && !err; i++)
78 {
79 struct store *k = store->children[i];
80 if (k->class->encode)
81 (*k->class->encode) (k, enc);
82 else
83 err = EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff));
84 }
85 return err;
86}
87
88/* Decodes NUM_CHILDREN from ENC, storing the results into successive
89 positions in CHILDREN. */
90error_t
91store_decode_children (struct store_enc *enc, int num_children,
92 const struct store_class *const *classes,
93 struct store **children)
94{
95 int i;
96 error_t err = 0;
97 for (i = 0; i < num_children && !err; i++)
98 err = store_decode (enc, classes, &children[i]);
99 if (err)
100 /* Deallocate anything we've already created. */
101 while (--i >= 0)
102 store_free (children[i]);
103 return err;
104}
105
106/* Set FLAGS in all children of STORE, and if successful, add FLAGS to
107 STORE's flags. */
108error_t
109store_set_child_flags (struct store *store, int flags)
110{
111 int i;
112 error_t err = 0;
113 int old_child_flags[store->num_children];
114
115 for (i = 0; i < store->num_children && !err; i++)
116 {
117 old_child_flags[i] = store->children[i]->flags;
118 err = store_set_flags (store->children[i], flags);
119 }
120
121 if (err)
122 while (i-- > 0)
123 store_clear_flags (store->children[i], flags & ~old_child_flags[i]);
124 else
125 store->flags |= flags;
126
127 return err;
128}
129
130/* Clear FLAGS in all children of STORE, and if successful, remove FLAGS from
131 STORE's flags. */
132error_t
133store_clear_child_flags (struct store *store, int flags)
134{
135 int i;
136 error_t err = 0;
137 int old_child_flags[store->num_children];
138
139 for (i = 0; i < store->num_children && !err; i++)
140 {
141 old_child_flags[i] = store->children[i]->flags;
142 err = store_clear_flags (store->children[i], flags);
143 }
144
145 if (err)
146 while (i-- > 0)
147 store_set_flags (store->children[i], flags & ~old_child_flags[i]);
148 else
149 store->flags &= ~flags;
150
151 return err;
152}
153
154/* Parse multiple store names in NAME, and open each individually, returning
155 all in the vector STORES, and the number in NUM_STORES. The syntax of
156 NAME is a single non-alpha-numeric separator character, followed by each
157 child store name separated by the same separator; each child name is
158 TYPE:NAME notation as parsed by store_typed_open. If every child uses the
159 same TYPE: prefix, then it may be factored out and put before the child
160 list instead (the two types of notation are differentiated by whether the
161 first character of name is alpha-numeric or not). */
162error_t
163store_open_children (const char *name, int flags,
164 const struct store_class *const *classes,
165 struct store ***stores, size_t *num_stores)
166{
167 char *pfx = 0; /* Prefix applied to each part name. */
168 size_t pfx_len = 0; /* Space PFX + separator takes up. */
169 char sep = *name; /* Character separating individual names. */
170
171 if (sep && isalnum (sep)((*__ctype_b_loc ())[(int) ((sep))] & (unsigned short int
) _ISalnum)
)
1
Taking false branch
172 /* If the first character is a `name' character, it's likely to be either
173 a type prefix (e.g, TYPE:@NAME1@NAME2@), so we distribute the type
174 prefix among the elements (@TYPE:NAME1@TYPE:NAME2@). */
175 {
176 const char *pfx_end = name;
177
178 while (isalnum (*pfx_end)((*__ctype_b_loc ())[(int) ((*pfx_end))] & (unsigned short
int) _ISalnum)
)
179 pfx_end++;
180
181 if (*pfx_end++ != ':')
182 return EINVAL((0x10 << 26) | ((22) & 0x3fff));
183
184 /* Make a copy of the prefix. */
185 pfx = strndupa (name, pfx_end - name)(__extension__ ({ const char *__old = (name); size_t __len = strnlen
(__old, (pfx_end - name)); char *__new = (char *) __builtin_alloca
(__len + 1); __new[__len] = '\0'; (char *) memcpy (__new, __old
, __len); }))
;
186 pfx_len = pfx_end - name;
187
188 sep = *pfx_end;
189 }
190
191 if (sep)
2
Taking true branch
192 /* Parse a list of store specs separated by SEP. */
193 {
194 int k;
195 const char *p, *end;
196 error_t err = 0;
197 size_t count = 0;
198
199 /* First, see how many there are. */
200 for (p = name; p && p[1]; p = strchr (p + 1, sep))
3
Loop condition is false. Execution continues on line 204
201 count++;
202
203 /* Make a vector to hold them. */
204 *stores = malloc (count * sizeof (struct store *));
4
Call to 'malloc' has an allocation size of 0 bytes
205 *num_stores = count;
206 if (! *stores)
207 return ENOMEM((0x10 << 26) | ((12) & 0x3fff));
208
209 memset (*stores, 0, count * sizeof(struct store *));
210
211 /* Open each child store. */
212 for (p = name, k = 0; !err && p && p[1]; p = end, k++)
213 {
214 size_t kname_len;
215
216 end = strchr (p + 1, sep);
217 kname_len = (end ? end - p - 1 : strlen (p + 1));
218
219 {
220 /* Allocate temporary child name on the stack. */
221 char kname[pfx_len + kname_len + 1];
222
223 if (pfx)
224 /* Add type prefix to child name. */
225 memcpy (kname, pfx, pfx_len);
226
227 memcpy (kname + pfx_len, p + 1, kname_len);
228 kname[pfx_len + kname_len] = '\0';
229
230 err = store_typed_open (kname, flags, classes, &(*stores)[k]);
231 }
232 }
233
234 if (err)
235 /* Failure opening some child, deallocate what we've done so far. */
236 {
237 while (--k >= 0)
238 store_free ((*stores)[k]);
239 free (*stores);
240 }
241
242 return err;
243 }
244 else
245 /* Empty list. */
246 {
247 *stores = 0;
248 *num_stores = 0;
249 return 0;
250 }
251}
252
253/* Try to come up with a name for the children in STORE, combining the names
254 of each child in a way that could be used to parse them with
255 store_open_children. This is done heuristically, and so may not succeed.
256 If a child doesn't have a name, EINVAL is returned. */
257error_t
258store_children_name (const struct store *store, char **name)
259{
260 static char try_seps[] = "@+=,._%|;^!~'&";
261 struct store **kids = store->children;
262 size_t num_kids = store->num_children;
263
264 if (num_kids == 0)
265 {
266 *name = strdup ("");
267 return *name ? 0 : ENOMEM((0x10 << 26) | ((12) & 0x3fff));
268 }
269 else
270 {
271 int k;
272 char *s; /* Current separator in search for one. */
273 int fail; /* If we couldn't use *S as as sep. */
274 size_t total_len = 0; /* Length of name we will return. */
275
276 /* Detect children without names, and calculate the total length of the
277 name we will return (which is the sum of the lengths of the child
278 names plus room for the types and separator characters. */
279 for (k = 0; k < num_kids; k++)
280 if (!kids[k] || !kids[k]->name)
281 return EINVAL((0x10 << 26) | ((22) & 0x3fff));
282 else
283 total_len +=
284 /* separator + type name + type separator + child name */
285 1 + strlen (kids[k]->class->name) + 1 + strlen (kids[k]->name);
286
287 /* Look for a separator character from those in TRY_SEPS that doesn't
288 occur in any of the the child names. */
289 for (s = try_seps, fail = 1; *s && fail; s++)
290 for (k = 0, fail = 0; k < num_kids && !fail; k++)
291 if (strchr (kids[k]->name, *s))
292 fail = 1;
293
294 if (*s)
295 /* We found a usable separator! */
296 {
297 char *p = malloc (total_len + 1);
298
299 if (! p)
300 return ENOMEM((0x10 << 26) | ((12) & 0x3fff));
301 *name = p;
302
303 for (k = 0; k < num_kids; k++)
304 p +=
305 sprintf (p, "%c%s:%s", *s, kids[k]->class->name, kids[k]->name);
306
307 return 0;
308 }
309 else
310 return EGRATUITOUS((0x10 << 26) | ((105) & 0x3fff));
311 }
312}