Bug Summary

File:src/kits/storage/Mime.cpp
Location:line 317, column 2
Description:Attempt to free released memory

Annotated Source Code

1/*
2 * Copyright 2002-2008, Haiku Inc.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Tyler Dauwalder
7 * Ingo Weinhold, bonefish@users.sf.net
8 * Axel Dörfler, axeld@pinc-software.de
9 */
10
11/*!
12 \file Mime.cpp
13 Mime type C functions implementation.
14*/
15
16#include <errno(*(_errnop())).h>
17#include <new>
18#include <stdlib.h>
19#include <string.h>
20#include <sys/ioctl.h>
21#include <unistd.h>
22
23#include <AutoDeleter.h>
24#include <Bitmap.h>
25#include <Drivers.h>
26#include <Entry.h>
27#include <File.h>
28#include <FindDirectory.h>
29#include <fs_attr.h>
30#include <fs_info.h>
31#include <IconUtils.h>
32#include <Mime.h>
33#include <MimeType.h>
34#include <mime/database_access.h>
35#include <Node.h>
36#include <Path.h>
37#include <RegistrarDefs.h>
38#include <Roster.h>
39#include <RosterPrivate.h>
40
41
42using namespace BPrivate;
43
44enum {
45 NOT_IMPLEMENTED = B_ERROR(-1),
46};
47
48
49// Helper function that contacts the registrar for mime update calls
50status_t
51do_mime_update(int32 what, const char *path, int recursive,
52 int synchronous, int force)
53{
54 BEntry root;
55 entry_ref ref;
56
57 status_t err = root.SetTo(path ? path : "/");
58 if (!err)
59 err = root.GetRef(&ref);
60 if (!err) {
61 BMessage msg(what);
62 BMessage reply;
63 status_t result;
64
65 // Build and send the message, read the reply
66 if (!err)
67 err = msg.AddRef("entry", &ref);
68 if (!err)
69 err = msg.AddBool("recursive", recursive);
70 if (!err)
71 err = msg.AddBool("synchronous", synchronous);
72 if (!err)
73 err = msg.AddInt32("force", force);
74 if (!err)
75 err = BRoster::Private().SendTo(&msg, &reply, true);
76 if (!err)
77 err = reply.what == B_REG_RESULT ? B_OK((int)0) : B_BAD_VALUE((-2147483647 - 1) + 5);
78 if (!err)
79 err = reply.FindInt32("result", &result);
80 if (!err)
81 err = result;
82 }
83 return err;
84}
85
86
87// Updates the MIME information (i.e MIME type) for one or more files.
88int
89update_mime_info(const char *path, int recursive, int synchronous, int force)
90{
91 // Force recursion when given a NULL path
92 if (!path)
93 recursive = true;
94
95 return do_mime_update(B_REG_MIME_UPDATE_MIME_INFO, path, recursive,
96 synchronous, force);
97}
98
99
100// Creates a MIME database entry for one or more applications.
101status_t
102create_app_meta_mime(const char *path, int recursive, int synchronous,
103 int force)
104{
105 // Force recursion when given a NULL path
106 if (!path)
107 recursive = true;
108
109 return do_mime_update(B_REG_MIME_CREATE_APP_META_MIME, path, recursive,
110 synchronous, force);
111}
112
113
114// Retrieves an icon associated with a given device.
115status_t
116get_device_icon(const char *device, void *icon, int32 size)
117{
118 if (device == NULL__null || icon == NULL__null
119 || (size != B_LARGE_ICON && size != B_MINI_ICON))
120 return B_BAD_VALUE((-2147483647 - 1) + 5);
121
122 int fd = open(device, O_RDONLY0x0000);
123 if (fd < 0)
124 return errno(*(_errnop()));
125
126 // ToDo: The mounted directories for volumes can also have META:X:STD_ICON
127 // attributes. Should those attributes override the icon returned by
128 // ioctl(,B_GET_ICON,)?
129 device_icon iconData = {size, icon};
130 if (ioctl(fd, B_GET_ICON, &iconData) != 0) {
131 // legacy icon was not available, try vector icon
132 close(fd);
133
134 uint8* data;
135 size_t dataSize;
136 type_code type;
137 status_t status = get_device_icon(device, &data, &dataSize, &type);
138 if (status == B_OK((int)0)) {
139 BBitmap* icon32 = new(std::nothrow) BBitmap(
140 BRect(0, 0, size - 1, size - 1), B_BITMAP_NO_SERVER_LINK,
141 B_RGBA32);
142 BBitmap* icon8 = new(std::nothrow) BBitmap(
143 BRect(0, 0, size - 1, size - 1), B_BITMAP_NO_SERVER_LINK,
144 B_CMAP8);
145
146 ArrayDeleter<uint8> dataDeleter(data);
147 ObjectDeleter<BBitmap> icon32Deleter(icon32);
148 ObjectDeleter<BBitmap> icon8Deleter(icon8);
149
150 if (icon32 == NULL__null || icon32->InitCheck() != B_OK((int)0) || icon8 == NULL__null
151 || icon8->InitCheck() != B_OK((int)0)) {
152 return B_NO_MEMORY((-2147483647 - 1) + 0);
153 }
154
155 status = BIconUtils::GetVectorIcon(data, dataSize, icon32);
156 if (status == B_OK((int)0))
157 status = BIconUtils::ConvertToCMAP8(icon32, icon8);
158 if (status == B_OK((int)0))
159 memcpy(icon, icon8->Bits(), icon8->BitsLength());
160
161 return status;
162 }
163 return errno(*(_errnop()));
164 }
165
166 close(fd);
167 return B_OK((int)0);
168}
169
170
171// Retrieves an icon associated with a given device.
172status_t
173get_device_icon(const char *device, BBitmap *icon, icon_size which)
174{
175 // check parameters
176 if (device == NULL__null || icon == NULL__null)
177 return B_BAD_VALUE((-2147483647 - 1) + 5);
178
179 uint8* data;
180 size_t size;
181 type_code type;
182 status_t status = get_device_icon(device, &data, &size, &type);
183 if (status == B_OK((int)0)) {
184 status = BIconUtils::GetVectorIcon(data, size, icon);
185 delete[] data;
186 return status;
187 }
188
189 // Vector icon was not available, try old one
190
191 BRect rect;
192 if (which == B_MINI_ICON)
193 rect.Set(0, 0, 15, 15);
194 else if (which == B_LARGE_ICON)
195 rect.Set(0, 0, 31, 31);
196
197 BBitmap* bitmap = icon;
198 int32 iconSize = which;
199
200 if (icon->ColorSpace() != B_CMAP8
201 || (which != B_MINI_ICON && which != B_LARGE_ICON)) {
202 if (which < B_LARGE_ICON)
203 iconSize = B_MINI_ICON;
204 else
205 iconSize = B_LARGE_ICON;
206
207 bitmap = new(std::nothrow) BBitmap(
208 BRect(0, 0, iconSize - 1, iconSize -1), B_BITMAP_NO_SERVER_LINK,
209 B_CMAP8);
210 if (bitmap == NULL__null || bitmap->InitCheck() != B_OK((int)0)) {
211 delete bitmap;
212 return B_NO_MEMORY((-2147483647 - 1) + 0);
213 }
214 }
215
216 // get the icon, convert temporary data into bitmap if necessary
217 status = get_device_icon(device, bitmap->Bits(), iconSize);
218 if (status == B_OK((int)0) && icon != bitmap)
219 status = BIconUtils::ConvertFromCMAP8(bitmap, icon);
220
221 if (icon != bitmap)
222 delete bitmap;
223
224 return status;
225}
226
227
228status_t
229get_device_icon(const char *device, uint8** _data, size_t* _size,
230 type_code* _type)
231{
232 if (device == NULL__null || _data == NULL__null || _size == NULL__null || _type == NULL__null)
233 return B_BAD_VALUE((-2147483647 - 1) + 5);
234
235 int fd = open(device, O_RDONLY0x0000);
236 if (fd < 0)
237 return errno(*(_errnop()));
238
239 // Try to get the icon by name first
240
241 char name[B_FILE_NAME_LENGTH(256)];
242 if (ioctl(fd, B_GET_ICON_NAME, name) >= 0) {
243 status_t status = get_named_icon(name, _data, _size, _type);
244 if (status == B_OK((int)0)) {
245 close(fd);
246 return B_OK((int)0);
247 }
248 }
249
250 // Getting the named icon failed, try vector icon next
251
252 // NOTE: The actual icon size is unknown as of yet. After the first call
253 // to B_GET_VECTOR_ICON, the actual size is known and the final buffer
254 // is allocated with the correct size. If the buffer needed to be
255 // larger, then the temporary buffer above will not yet contain the
256 // valid icon data. In that case, a second call to B_GET_VECTOR_ICON
257 // retrieves it into the final buffer.
258 uint8 data[8192];
259 device_icon iconData = {sizeof(data), data};
260 status_t status = ioctl(fd, B_GET_VECTOR_ICON, &iconData,
261 sizeof(device_icon));
262 if (status != 0)
263 status = errno(*(_errnop()));
264
265 if (status == B_OK((int)0)) {
266 *_data = new(std::nothrow) uint8[iconData.icon_size];
267 if (*_data == NULL__null)
268 status = B_NO_MEMORY((-2147483647 - 1) + 0);
269 }
270
271 if (status == B_OK((int)0)) {
272 if (iconData.icon_size > (int32)sizeof(data)) {
273 // the stack buffer does not contain the data, see NOTE above
274 iconData.icon_data = *_data;
275 status = ioctl(fd, B_GET_VECTOR_ICON, &iconData,
276 sizeof(device_icon));
277 if (status != 0)
278 status = errno(*(_errnop()));
279 } else
280 memcpy(*_data, data, iconData.icon_size);
281
282 *_size = iconData.icon_size;
283 *_type = B_VECTOR_ICON_TYPE;
284 }
285
286 // TODO: also support getting the old icon?
287 close(fd);
288 return status;
289}
290
291
292status_t
293get_named_icon(const char* name, BBitmap* icon, icon_size which)
294{
295 // check parameters
296 if (name == NULL__null || icon == NULL__null)
1
Taking false branch
297 return B_BAD_VALUE((-2147483647 - 1) + 5);
298
299 BRect rect;
300 if (which == B_MINI_ICON)
2
Assuming 'which' is not equal to B_MINI_ICON
3
Taking false branch
301 rect.Set(0, 0, 15, 15);
302 else if (which == B_LARGE_ICON)
4
Assuming 'which' is equal to B_LARGE_ICON
5
Taking true branch
303 rect.Set(0, 0, 31, 31);
304 else
305 return B_BAD_VALUE((-2147483647 - 1) + 5);
306
307 if (icon->Bounds() != rect)
6
Taking false branch
308 return B_BAD_VALUE((-2147483647 - 1) + 5);
309
310 uint8* data;
311 size_t size;
312 type_code type;
313 status_t status = get_named_icon(name, &data, &size, &type);
7
Calling 'get_named_icon'
22
Returning; memory was released via 2nd parameter
314 if (status == B_OK((int)0))
23
Taking false branch
315 status = BIconUtils::GetVectorIcon(data, size, icon);
316
317 delete[] data;
24
Attempt to free released memory
318 return status;
319}
320
321
322status_t
323get_named_icon(const char* name, uint8** _data, size_t* _size, type_code* _type)
324{
325 if (name == NULL__null || _data == NULL__null || _size == NULL__null || _type == NULL__null)
8
Taking false branch
326 return B_BAD_VALUE((-2147483647 - 1) + 5);
327
328 directory_which kWhich[] = {
329 B_USER_DATA_DIRECTORY,
330 B_COMMON_DATA_DIRECTORY,
331 B_BEOS_DATA_DIRECTORY,
332 };
333
334 status_t status = B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3);
335 BFile file;
336 off_t size;
337
338 for (uint32 i = 0; i < sizeof(kWhich) / sizeof(kWhich[0]); i++) {
9
Loop condition is true. Entering loop body
339 BPath path;
340 if (find_directory(kWhich[i], &path) != B_OK((int)0))
10
Taking false branch
341 continue;
342
343 path.Append("icons");
344 path.Append(name);
345
346 status = file.SetTo(path.Path(), B_READ_ONLY0x0000);
347 if (status == B_OK((int)0)) {
11
Assuming 'status' is equal to 0
12
Taking true branch
348 status = file.GetSize(&size);
349 if (size > 1024 * 1024)
13
Taking false branch
350 status = B_ERROR(-1);
351 }
352 if (status == B_OK((int)0))
14
Assuming 'status' is equal to 0
15
Taking true branch
353 break;
16
Execution continues on line 356
354 }
355
356 if (status != B_OK((int)0))
17
Taking false branch
357 return status;
358
359 *_data = new(std::nothrow) uint8[size];
18
Memory is allocated
360 if (*_data == NULL__null)
19
Taking false branch
361 return B_NO_MEMORY((-2147483647 - 1) + 0);
362
363 if (file.Read(*_data, size) != size) {
20
Taking true branch
364 delete[] *_data;
21
Memory is released
365 return B_ERROR(-1);
366 }
367
368 *_size = size;
369 *_type = B_VECTOR_ICON_TYPE;
370 // TODO: for now
371
372 return B_OK((int)0);
373}