Bug Summary

File:src/add-ons/translators/psd/PSDLoader.cpp
Location:line 259, column 2
Description:Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete'

Annotated Source Code

1/*
2 * Copyright 2013, Gerasim Troeglazov, 3dEyes@gmail.com. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "PSDLoader.h"
8#include "BaseTranslator.h"
9
10
11PSDLoader::PSDLoader(BPositionIO *src)
12{
13 fLoaded = false;
14 fStream = src;
15
16 fStream->Seek(0, SEEK_END2);
17 fStreamSize = fStream->Position();
18 fStream->Seek(0, SEEK_SET0);
19
20 if (fStreamSize <= 0)
21 return;
22
23 fStream->Seek(0, SEEK_SET0);
24
25 fSignature = _GetInt32FromStream(fStream);
26 if (fSignature != 0x38425053) // 8BPS
27 return;
28
29 fVersion = _GetInt16FromStream(fStream);
30
31 // Skip reserved data
32 _SkipStreamBlock(fStream, 6);
33
34 fChannels = _GetInt16FromStream(fStream);
35 fHeight = _GetInt32FromStream(fStream);
36 fWidth = _GetInt32FromStream(fStream);
37 fDepth = _GetInt16FromStream(fStream);
38 fColorFormat = _GetInt16FromStream(fStream);
39
40 fColorModeDataSize = _GetInt32FromStream(fStream);
41 fColorModeDataPos = fStream->Position();
42 _SkipStreamBlock(fStream, fColorModeDataSize);
43
44 fImageResourceSectionSize = _GetInt32FromStream(fStream);
45 fImageResourceSectionPos = fStream->Position();
46 _SkipStreamBlock(fStream, fImageResourceSectionSize);
47
48 // Skip [layer and mask] block
49 if (fVersion == PSD_FILE)
50 _SkipStreamBlock(fStream, _GetInt32FromStream(fStream));
51 else if (fVersion == PSB_FILE)
52 _SkipStreamBlock(fStream, _GetInt64FromStream(fStream));
53 else
54 return;
55
56 fCompression = _GetInt16FromStream(fStream);
57
58 fStreamPos = fStream->Position();
59
60 fLoaded = true;
61}
62
63
64PSDLoader::~PSDLoader()
65{
66}
67
68
69bool
70PSDLoader::IsLoaded(void)
71{
72 return fLoaded;
73}
74
75
76bool
77PSDLoader::IsSupported(void)
78{
79 if (!fLoaded)
80 return false;
81
82 if (fVersion != PSD_FILE
83 && fVersion != PSB_FILE) {
84 return false;
85 }
86
87 if (fChannels < 0 || fChannels > PSD_MAX_CHANNELS16)
88 return false;
89
90 if (fDepth > 16)
91 return false;
92
93 if (_ColorFormat() == PSD_COLOR_FORMAT_UNSUPPORTED)
94 return false;
95
96 if (fCompression != PSD_COMPRESSED_RAW
97 && fCompression != PSD_COMPRESSED_RLE) {
98 return false;
99 }
100
101 return true;
102}
103
104
105BString
106PSDLoader::ColorFormatName(void)
107{
108 switch (fColorFormat) {
109 case PSD_COLOR_MODE_BITS:
110 return "Bitmap";
111 case PSD_COLOR_MODE_GRAYSCALE:
112 return "Grayscale";
113 case PSD_COLOR_MODE_INDEXED:
114 return "Indexed";
115 case PSD_COLOR_MODE_RGB:
116 return fChannels > 3 ? "RGBA" : "RGB";
117 case PSD_COLOR_MODE_CMYK:
118 return "CMYK";
119 case PSD_COLOR_MODE_MULTICHANNEL:
120 return "Multichannel";
121 case PSD_COLOR_MODE_LAB:
122 return "Lab";
123 case PSD_COLOR_MODE_DUOTONE:
124 return "Duotone";
125 }
126 return "";
127}
128
129
130psd_color_format
131PSDLoader::_ColorFormat(void)
132{
133 psd_color_format format = PSD_COLOR_FORMAT_UNSUPPORTED;
134 if (!fLoaded)
135 return format;
136
137 switch (fColorFormat) {
138 case PSD_COLOR_MODE_BITS:
139 format = PSD_COLOR_FORMAT_BITMAP;
140 break;
141 case PSD_COLOR_MODE_RGB:
142 if (fChannels == 3)
143 format = PSD_COLOR_FORMAT_RGB;
144 else if (fChannels >= 4)
145 format = PSD_COLOR_FORMAT_RGB_A;
146 break;
147 case PSD_COLOR_MODE_GRAYSCALE:
148 if (fChannels == 1)
149 format = PSD_COLOR_FORMAT_GRAY;
150 else if (fChannels == 2)
151 format = PSD_COLOR_FORMAT_GRAY_A;
152 break;
153 case PSD_COLOR_MODE_MULTICHANNEL:
154 if (fChannels == 3)
155 format = PSD_COLOR_FORMAT_MULTICHANNEL;
156 break;
157 case PSD_COLOR_MODE_CMYK:
158 if (fChannels == 3)
159 format = PSD_COLOR_FORMAT_MULTICHANNEL;
160 else if (fChannels == 4)
161 format = PSD_COLOR_FORMAT_CMYK;
162 else if (fChannels > 4)
163 format = PSD_COLOR_FORMAT_CMYK_A;
164 break;
165 case PSD_COLOR_MODE_LAB:
166 if (fChannels == 3)
167 format = PSD_COLOR_FORMAT_LAB;
168 else if (fChannels > 3)
169 format = PSD_COLOR_FORMAT_LAB_A;
170 break;
171 case PSD_COLOR_MODE_DUOTONE:
172 if (fChannels >= 1)
173 format = PSD_COLOR_FORMAT_DUOTONE;
174 break;
175 case PSD_COLOR_MODE_INDEXED:
176 if (fChannels >= 1 && fColorModeDataSize >= 3)
177 format = PSD_COLOR_FORMAT_INDEXED;
178 break;
179 default:
180 break;
181 };
182
183 return format;
184}
185
186
187status_t
188PSDLoader::Decode(BPositionIO *target)
189{
190 if (!IsSupported())
1
Taking false branch
191 return B_NO_TRANSLATOR(((-2147483647 - 1) + 0x4800) + 1);
192
193 fStreamBuffer = new uint8[fStreamSize];
2
Memory is allocated
194 fStream->Seek(0, SEEK_SET0);
195 fStream->Read(fStreamBuffer, fStreamSize);
196
197 int32 depthBytes = fDepth / 8;
198 int32 rowBytes = (fWidth * fDepth) / 8;
199 int32 channelBytes = rowBytes * fHeight;
200
201 uint8 *imageData[PSD_MAX_CHANNELS16];
202 for (int i = 0; i < fChannels; i++)
3
Loop condition is true. Entering loop body
4
Loop condition is false. Execution continues on line 206
203 imageData[i] = new uint8[channelBytes];
204
205
206 switch (fCompression) {
5
Control jumps to 'case PSD_COMPRESSED_RAW:' at line 207
207 case PSD_COMPRESSED_RAW:
208 {
209 for (int channelIdx = 0; channelIdx < fChannels; channelIdx++) {
6
Loop condition is true. Entering loop body
9
Loop condition is false. Execution continues on line 214
210 uint8 *ptr = imageData[channelIdx];
211 for (int i = 0; i < channelBytes; i++, ptr++)
7
Assuming 'i' is >= 'channelBytes'
8
Loop condition is false. Execution continues on line 209
212 *ptr = (uint8)fStreamBuffer[fStreamPos++];
213 }
214 break;
10
Execution continues on line 259
215 }
216 case PSD_COMPRESSED_RLE:
217 {
218 if (fVersion == PSD_FILE)
219 fStreamPos += fHeight * fChannels * 2;
220 else if (fVersion == PSB_FILE)
221 fStreamPos += fHeight * fChannels * 4;
222
223 for (int channelIdx = 0; channelIdx < fChannels; channelIdx++) {
224 uint8 *ptr = imageData[channelIdx];
225 // Read the RLE data.
226 int count = 0;
227 while (count < channelBytes) {
228 uint8 len = (uint8)fStreamBuffer[fStreamPos++];
229 if (len == 128) {
230 continue;
231 } else if (len < 128) {
232 len++;
233 count += len;
234 while (len) {
235 *ptr++ = (int8)fStreamBuffer[fStreamPos++];
236 len--;
237 }
238 } else if (len > 128) {
239 int8 val = (int8)fStreamBuffer[fStreamPos++];
240 len ^= 255;
241 len += 2;
242 count += len;
243 while (len) {
244 *ptr++ = val;
245 len--;
246 }
247 }
248 }
249 }
250 break;
251 }
252 default:
253 delete fStreamBuffer;
254 for (int i = 0; i < fChannels; i++)
255 delete imageData[i];
256 return B_NO_TRANSLATOR(((-2147483647 - 1) + 0x4800) + 1);
257 }
258
259 delete fStreamBuffer;
11
Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete'
260
261 TranslatorBitmap bitsHeader;
262 bitsHeader.magic = B_TRANSLATOR_BITMAP;
263 bitsHeader.bounds.left = 0;
264 bitsHeader.bounds.top = 0;
265 bitsHeader.bounds.right = fWidth - 1;
266 bitsHeader.bounds.bottom = fHeight - 1;
267
268 psd_color_format colorFormat = _ColorFormat();
269
270 if (colorFormat == PSD_COLOR_FORMAT_BITMAP) {
271 bitsHeader.rowBytes = rowBytes;
272 bitsHeader.dataSize = channelBytes;
273 bitsHeader.colors = B_GRAY1;
274 } else {
275 bitsHeader.rowBytes = sizeof(uint32) * fWidth;
276 bitsHeader.colors = B_RGBA32;
277 bitsHeader.dataSize = bitsHeader.rowBytes * fHeight;
278 }
279
280 if (swap_data(B_UINT32_TYPE, &bitsHeader,
281 sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN) != B_OK((int)0)) {
282 return B_NO_TRANSLATOR(((-2147483647 - 1) + 0x4800) + 1);
283 }
284
285 target->Write(&bitsHeader, sizeof(TranslatorBitmap));
286
287 uint8 *lineData = new uint8[fWidth * sizeof(uint32)];
288
289 switch (colorFormat) {
290 case PSD_COLOR_FORMAT_BITMAP:
291 {
292 int32 rowBytes = (fWidth / 8 ) * fHeight;
293 for (int32 i = 0; i < rowBytes; i++)
294 imageData[0][i]^=255;
295 target->Write(imageData[0], rowBytes);
296 break;
297 }
298 case PSD_COLOR_FORMAT_INDEXED:
299 {
300 int32 paletteSize = fColorModeDataSize / 3;
301
302 uint8 *colorData = new uint8[fColorModeDataSize];
303 fStream->Seek(fColorModeDataPos, SEEK_SET0);
304 fStream->Read(colorData, fColorModeDataSize);
305
306 if (_ParseImageResources() != B_OK((int)0))
307 fTransparentIndex = 256;
308
309 uint8 *redPalette = colorData;
310 uint8 *greenPalette = colorData + paletteSize;
311 uint8 *bluePalette = colorData + paletteSize * 2;
312 int32 index = 0;
313 for (int h = 0; h < fHeight; h++) {
314 uint8 *ptr = lineData;
315 for (int w = 0; w < fWidth; w++) {
316 uint8 colorIndex = imageData[0][index];
317 ptr[0] = bluePalette[colorIndex];
318 ptr[1] = greenPalette[colorIndex];
319 ptr[2] = redPalette[colorIndex];
320 ptr[3] = colorIndex == fTransparentIndex ? 0 : 255;
321
322 ptr += sizeof(uint32);
323 index++;
324 }
325 target->Write(lineData, fWidth * sizeof(uint32));
326 }
327 delete colorData;
328 break;
329 }
330 case PSD_COLOR_FORMAT_DUOTONE:
331 case PSD_COLOR_FORMAT_GRAY:
332 case PSD_COLOR_FORMAT_GRAY_A:
333 {
334 bool isAlpha = colorFormat == PSD_COLOR_FORMAT_GRAY_A;
335 int32 index = 0;
336 for (int h = 0; h < fHeight; h++) {
337 uint8 *ptr = lineData;
338 for (int w = 0; w < fWidth; w++) {
339 ptr[0] = imageData[0][index];
340 ptr[1] = imageData[0][index];
341 ptr[2] = imageData[0][index];
342 ptr[3] = isAlpha ? imageData[1][index] : 255;
343
344 ptr += sizeof(uint32);
345 index += depthBytes;
346 }
347 target->Write(lineData, fWidth * sizeof(uint32));
348 }
349 break;
350 }
351 case PSD_COLOR_FORMAT_MULTICHANNEL:
352 case PSD_COLOR_FORMAT_RGB:
353 case PSD_COLOR_FORMAT_RGB_A:
354 {
355 bool isAlpha = colorFormat == PSD_COLOR_FORMAT_RGB_A;
356 int32 index = 0;
357 for (int h = 0; h < fHeight; h++) {
358 uint8 *ptr = lineData;
359 for (int w = 0; w < fWidth; w++) {
360 ptr[0] = imageData[2][index];
361 ptr[1] = imageData[1][index];
362 ptr[2] = imageData[0][index];
363 ptr[3] = isAlpha ? imageData[3][index] : 255;
364
365 ptr += sizeof(uint32);
366 index += depthBytes;
367 }
368 target->Write(lineData, fWidth * sizeof(uint32));
369 }
370 break;
371 }
372 case PSD_COLOR_FORMAT_CMYK:
373 case PSD_COLOR_FORMAT_CMYK_A:
374 {
375 bool isAlpha = colorFormat == PSD_COLOR_FORMAT_CMYK_A;
376 int32 index = 0;
377 for (int h = 0; h < fHeight; h++) {
378 uint8 *ptr = lineData;
379 for (int w = 0; w < fWidth; w++) {
380 double c = 1.0 - imageData[0][index] / 255.0;
381 double m = 1.0 - imageData[1][index] / 255.0;
382 double y = 1.0 - imageData[2][index] / 255.0;
383 double k = 1.0 - imageData[3][index] / 255.0;
384 ptr[0] = (uint8)((1.0 - (y * (1.0 - k) + k)) * 255.0);
385 ptr[1] = (uint8)((1.0 - (m * (1.0 - k) + k)) * 255.0);
386 ptr[2] = (uint8)((1.0 - (c * (1.0 - k) + k)) * 255.0);
387 ptr[3] = isAlpha ? imageData[4][index] : 255;
388
389 ptr += sizeof(uint32);
390 index += depthBytes;
391 }
392 target->Write(lineData, fWidth * sizeof(uint32));
393 }
394 break;
395 }
396 case PSD_COLOR_FORMAT_LAB:
397 case PSD_COLOR_FORMAT_LAB_A:
398 {
399 bool isAlpha = colorFormat == PSD_COLOR_FORMAT_LAB_A;
400 int32 index = 0;
401 for (int h = 0; h < fHeight; h++) {
402 uint8 *ptr = lineData;
403 for (int w = 0; w < fWidth; w++) {
404 double L = imageData[0][index] / 255.0 * 100.0;
405 double a = imageData[1][index] - 128.0;
406 double b = imageData[2][index] - 128.0;
407
408 double Y = L * (1.0 / 116.0) + 16.0 / 116.0;
409 double X = a * (1.0 / 500.0) + Y;
410 double Z = b * (-1.0 / 200.0) + Y;
411
412 X = X > 6.0 / 29.0 ? X * X * X : X * (108.0 / 841.0)
413 - (432.0 / 24389.0);
414 Y = L > 8.0 ? Y * Y * Y : L * (27.0 / 24389.0);
415 Z = Z > 6.0 / 29.0 ? Z * Z * Z : Z * (108.0 / 841.0)
416 - (432.0 / 24389.0);
417
418 double R = X * (1219569.0 / 395920.0)
419 + Y * (-608687.0 / 395920.0)
420 + Z * (-107481.0 / 197960.0);
421 double G = X * (-80960619.0 / 87888100.0)
422 + Y * (82435961.0 / 43944050.0)
423 + Z * (3976797.0 / 87888100.0);
424 double B = X * (93813.0 / 1774030.0)
425 + Y * (-180961.0 / 887015.0)
426 + Z * (107481.0 / 93370.0);
427
428 R = R > 0.0031308 ? pow(R, 1.0 / 2.4) * 1.055 - 0.055
429 : R * 12.92;
430 G = G > 0.0031308 ? pow(G, 1.0 / 2.4) * 1.055 - 0.055
431 : G * 12.92;
432 B = B > 0.0031308 ? pow(B, 1.0 / 2.4) * 1.055 - 0.055
433 : B * 12.92;
434
435 R = (R < 0) ? 0 : ((R > 1) ? 1 : R);
436 G = (G < 0) ? 0 : ((G > 1) ? 1 : G);
437 B = (B < 0) ? 0 : ((B > 1) ? 1 : B);
438
439 ptr[0] = (uint8)(B * 255.0);
440 ptr[1] = (uint8)(G * 255.0);
441 ptr[2] = (uint8)(R * 255.0);
442 ptr[3] = isAlpha ? imageData[3][index] : 255;
443
444 ptr += sizeof(uint32);
445 index += depthBytes;
446 }
447 target->Write(lineData, fWidth * sizeof(uint32));
448 }
449 break;
450 }
451 default:
452 break;
453 };
454
455 delete lineData;
456 for (int i = 0; i < fChannels; i++)
457 delete imageData[i];
458
459 return B_OK((int)0);
460}
461
462
463int64
464PSDLoader::_GetInt64FromStream(BPositionIO *in)
465{
466 int64 ret;
467 in->Read(&ret, sizeof(int64));
468 return B_BENDIAN_TO_HOST_INT64(ret)__swap_int64(ret);
469}
470
471
472int32
473PSDLoader::_GetInt32FromStream(BPositionIO *in)
474{
475 int32 ret;
476 in->Read(&ret, sizeof(int32));
477 return B_BENDIAN_TO_HOST_INT32(ret)__swap_int32(ret);
478}
479
480
481int16
482PSDLoader::_GetInt16FromStream(BPositionIO *in)
483{
484 int16 ret;
485 in->Read(&ret, sizeof(int16));
486 return B_BENDIAN_TO_HOST_INT16(ret)__swap_int16(ret);
487}
488
489
490int8
491PSDLoader::_GetInt8FromStream(BPositionIO *in)
492{
493 int8 ret;
494 in->Read(&ret, sizeof(int8));
495 return ret;
496}
497
498
499uint8
500PSDLoader::_GetUInt8FromStream(BPositionIO *in)
501{
502 uint8 ret;
503 in->Read(&ret, sizeof(uint8));
504 return ret;
505}
506
507
508void
509PSDLoader::_SkipStreamBlock(BPositionIO *in, size_t count)
510{
511 in->Seek(count, SEEK_CUR1);
512}
513
514
515status_t
516PSDLoader::_ParseImageResources(void)
517{
518 if (!fLoaded && fImageResourceSectionSize == 0)
519 return B_ERROR(-1);
520
521 size_t currentPos = fStream->Position();
522 fStream->Seek(fImageResourceSectionPos, SEEK_SET0);
523
524 while (fStream->Position() < currentPos + fImageResourceSectionSize) {
525 int32 resBlockSignature = _GetInt32FromStream(fStream);
526 if (resBlockSignature != 0x3842494D) // 8BIM
527 return B_ERROR(-1);
528
529 uint16 resID = _GetInt16FromStream(fStream);
530
531 BString resName, name;
532 int nameLength = 0;
533 while (true) {
534 int charData = _GetUInt8FromStream(fStream);
535 nameLength++;
536 if (charData == 0) {
537 if (nameLength % 2 == 1) {
538 _GetUInt8FromStream(fStream);
539 nameLength++;
540 }
541 break;
542 } else
543 name += charData;
544 resName = name;
545 }
546
547 uint32 resSize = _GetInt32FromStream(fStream);
548
549 if (resSize % 2 == 1)
550 resSize++;
551
552 switch (resID) {
553 case 0x0417:
554 fTransparentIndex = _GetInt16FromStream(fStream);
555 break;
556 default:
557 _SkipStreamBlock(fStream, resSize);
558 }
559 }
560
561 fStream->Seek(currentPos, SEEK_SET0);
562
563 return B_OK((int)0);
564}