File: | libs/libsndfile/src/sd2.c |
Location: | line 166, column 2 |
Description: | Use of memory after it is freed |
1 | /* | |||
2 | ** Copyright (C) 2001-2013 Erik de Castro Lopo <erikd@mega-nerd.com> | |||
3 | ** Copyright (C) 2004 Paavo Jumppanen | |||
4 | ** | |||
5 | ** This program is free software; you can redistribute it and/or modify | |||
6 | ** it under the terms of the GNU Lesser General Public License as published by | |||
7 | ** the Free Software Foundation; either version 2.1 of the License, or | |||
8 | ** (at your option) any later version. | |||
9 | ** | |||
10 | ** This program is distributed in the hope that it will be useful, | |||
11 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
12 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
13 | ** GNU Lesser General Public License for more details. | |||
14 | ** | |||
15 | ** You should have received a copy of the GNU Lesser General Public License | |||
16 | ** along with this program; if not, write to the Free Software | |||
17 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
18 | */ | |||
19 | ||||
20 | /* | |||
21 | ** The sd2 support implemented in this file was partially sponsored | |||
22 | ** (financially) by Paavo Jumppanen. | |||
23 | */ | |||
24 | ||||
25 | /* | |||
26 | ** Documentation on the Mac resource fork was obtained here : | |||
27 | ** http://developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html | |||
28 | */ | |||
29 | ||||
30 | #include "sfconfig.h" | |||
31 | ||||
32 | #include <stdio.h> | |||
33 | #include <stdlib.h> | |||
34 | #include <string.h> | |||
35 | #include <ctype.h> | |||
36 | ||||
37 | #include "sndfile.h" | |||
38 | #include "sfendian.h" | |||
39 | #include "common.h" | |||
40 | ||||
41 | /*------------------------------------------------------------------------------ | |||
42 | * Markers. | |||
43 | */ | |||
44 | ||||
45 | #define Sd2f_MARKER((uint32_t) (('S') | (('d') << 8) | (('2') << 16) | (((uint32_t) ('f')) << 24))) MAKE_MARKER ('S', 'd', '2', 'f')((uint32_t) (('S') | (('d') << 8) | (('2') << 16) | (((uint32_t) ('f')) << 24))) | |||
46 | #define Sd2a_MARKER((uint32_t) (('S') | (('d') << 8) | (('2') << 16) | (((uint32_t) ('a')) << 24))) MAKE_MARKER ('S', 'd', '2', 'a')((uint32_t) (('S') | (('d') << 8) | (('2') << 16) | (((uint32_t) ('a')) << 24))) | |||
47 | #define ALCH_MARKER((uint32_t) (('A') | (('L') << 8) | (('C') << 16) | (((uint32_t) ('H')) << 24))) MAKE_MARKER ('A', 'L', 'C', 'H')((uint32_t) (('A') | (('L') << 8) | (('C') << 16) | (((uint32_t) ('H')) << 24))) | |||
48 | #define lsf1_MARKER((uint32_t) (('l') | (('s') << 8) | (('f') << 16) | (((uint32_t) ('1')) << 24))) MAKE_MARKER ('l', 's', 'f', '1')((uint32_t) (('l') | (('s') << 8) | (('f') << 16) | (((uint32_t) ('1')) << 24))) | |||
49 | ||||
50 | #define STR_MARKER((uint32_t) (('S') | (('T') << 8) | (('R') << 16) | (((uint32_t) (' ')) << 24))) MAKE_MARKER ('S', 'T', 'R', ' ')((uint32_t) (('S') | (('T') << 8) | (('R') << 16) | (((uint32_t) (' ')) << 24))) | |||
51 | #define sdML_MARKER((uint32_t) (('s') | (('d') << 8) | (('M') << 16) | (((uint32_t) ('L')) << 24))) MAKE_MARKER ('s', 'd', 'M', 'L')((uint32_t) (('s') | (('d') << 8) | (('M') << 16) | (((uint32_t) ('L')) << 24))) | |||
52 | ||||
53 | enum | |||
54 | { RSRC_STR = 111, | |||
55 | RSRC_BIN | |||
56 | } ; | |||
57 | ||||
58 | typedef struct | |||
59 | { unsigned char * rsrc_data ; | |||
60 | int rsrc_len ; | |||
61 | int need_to_free_rsrc_data ; | |||
62 | ||||
63 | int data_offset, data_length ; | |||
64 | int map_offset, map_length ; | |||
65 | ||||
66 | int type_count, type_offset ; | |||
67 | int item_offset ; | |||
68 | ||||
69 | int str_index, str_count ; | |||
70 | ||||
71 | int string_offset ; | |||
72 | ||||
73 | /* All the above just to get these three. */ | |||
74 | int sample_size, sample_rate, channels ; | |||
75 | } SD2_RSRC ; | |||
76 | ||||
77 | typedef struct | |||
78 | { int type ; | |||
79 | int id ; | |||
80 | char name [32] ; | |||
81 | char value [32] ; | |||
82 | int value_len ; | |||
83 | } STR_RSRC ; | |||
84 | ||||
85 | /*------------------------------------------------------------------------------ | |||
86 | * Private static functions. | |||
87 | */ | |||
88 | ||||
89 | static int sd2_close (SF_PRIVATE *psf) ; | |||
90 | ||||
91 | static int sd2_parse_rsrc_fork (SF_PRIVATE *psf) ; | |||
92 | static int parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc) ; | |||
93 | ||||
94 | static int sd2_write_rsrc_fork (SF_PRIVATE *psf, int calc_length) ; | |||
95 | ||||
96 | /*------------------------------------------------------------------------------ | |||
97 | ** Public functions. | |||
98 | */ | |||
99 | ||||
100 | int | |||
101 | sd2_open (SF_PRIVATE *psf) | |||
102 | { int subformat, error = 0, valid ; | |||
103 | ||||
104 | /* SD2 is always big endian. */ | |||
105 | psf->endian = SF_ENDIAN_BIG ; | |||
106 | ||||
107 | if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->rsrclength > 0)) | |||
| ||||
108 | { psf_use_rsrc (psf, SF_TRUE) ; | |||
109 | valid = psf_file_valid (psf) ; | |||
110 | psf_use_rsrc (psf, SF_FALSE) ; | |||
111 | if (! valid) | |||
112 | { psf_log_printf (psf, "sd2_open : psf->rsrc.filedes < 0\n") ; | |||
113 | return SFE_SD2_BAD_RSRC ; | |||
114 | } ; | |||
115 | ||||
116 | error = sd2_parse_rsrc_fork (psf) ; | |||
117 | ||||
118 | if (error) | |||
119 | goto error_cleanup ; | |||
120 | } ; | |||
121 | ||||
122 | if ((SF_CONTAINER (psf->sf.format)((psf->sf.format) & SF_FORMAT_TYPEMASK)) != SF_FORMAT_SD2) | |||
123 | { error = SFE_BAD_OPEN_FORMAT ; | |||
124 | goto error_cleanup ; | |||
125 | } ; | |||
126 | ||||
127 | subformat = SF_CODEC (psf->sf.format)((psf->sf.format) & SF_FORMAT_SUBMASK) ; | |||
128 | psf->dataoffset = 0 ; | |||
129 | ||||
130 | /* Only open and write the resource in RDWR mode is its current length is zero. */ | |||
131 | if (psf->file.mode == SFM_WRITE || (psf->file.mode == SFM_RDWR && psf->rsrclength == 0)) | |||
132 | { psf->rsrc.mode = psf->file.mode ; | |||
133 | psf_open_rsrc (psf) ; | |||
134 | ||||
135 | error = sd2_write_rsrc_fork (psf, SF_FALSE) ; | |||
136 | ||||
137 | if (error) | |||
138 | goto error_cleanup ; | |||
139 | ||||
140 | /* Not needed. */ | |||
141 | psf->write_header = NULL((void*)0) ; | |||
142 | } ; | |||
143 | ||||
144 | psf->container_close = sd2_close ; | |||
145 | ||||
146 | psf->blockwidth = psf->bytewidth * psf->sf.channels ; | |||
147 | ||||
148 | switch (subformat) | |||
149 | { case SF_FORMAT_PCM_S8 : /* 8-bit linear PCM. */ | |||
150 | case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */ | |||
151 | case SF_FORMAT_PCM_24 : /* 24-bit linear PCM */ | |||
152 | case SF_FORMAT_PCM_32 : /* 32-bit linear PCM */ | |||
153 | error = pcm_init (psf) ; | |||
154 | break ; | |||
155 | ||||
156 | default : | |||
157 | error = SFE_UNIMPLEMENTED ; | |||
158 | break ; | |||
159 | } ; | |||
160 | ||||
161 | psf_fseek (psf, psf->dataoffset, SEEK_SET0) ; | |||
162 | ||||
163 | error_cleanup: | |||
164 | ||||
165 | /* Close the resource fork regardless. We won't need it again. */ | |||
166 | psf_close_rsrc (psf) ; | |||
| ||||
167 | ||||
168 | return error ; | |||
169 | } /* sd2_open */ | |||
170 | ||||
171 | /*------------------------------------------------------------------------------ | |||
172 | */ | |||
173 | ||||
174 | static int | |||
175 | sd2_close (SF_PRIVATE *psf) | |||
176 | { | |||
177 | if (psf->file.mode == SFM_WRITE) | |||
178 | { /* Now we know for certain the audio_length of the file we can re-write | |||
179 | ** correct values for the FORM, 8SVX and BODY chunks. | |||
180 | */ | |||
181 | ||||
182 | } ; | |||
183 | ||||
184 | return 0 ; | |||
185 | } /* sd2_close */ | |||
186 | ||||
187 | /*------------------------------------------------------------------------------ | |||
188 | */ | |||
189 | ||||
190 | static inline void | |||
191 | write_char (unsigned char * data, int offset, char value) | |||
192 | { data [offset] = value ; | |||
193 | } /* write_char */ | |||
194 | ||||
195 | static inline void | |||
196 | write_short (unsigned char * data, int offset, short value) | |||
197 | { data [offset] = value >> 8 ; | |||
198 | data [offset + 1] = value ; | |||
199 | } /* write_char */ | |||
200 | ||||
201 | static inline void | |||
202 | write_int (unsigned char * data, int offset, int value) | |||
203 | { data [offset] = value >> 24 ; | |||
204 | data [offset + 1] = value >> 16 ; | |||
205 | data [offset + 2] = value >> 8 ; | |||
206 | data [offset + 3] = value ; | |||
207 | } /* write_int */ | |||
208 | ||||
209 | static inline void | |||
210 | write_marker (unsigned char * data, int offset, int value) | |||
211 | { | |||
212 | if (CPU_IS_BIG_ENDIAN0) | |||
213 | { data [offset] = value >> 24 ; | |||
214 | data [offset + 1] = value >> 16 ; | |||
215 | data [offset + 2] = value >> 8 ; | |||
216 | data [offset + 3] = value ; | |||
217 | } | |||
218 | else | |||
219 | { data [offset] = value ; | |||
220 | data [offset + 1] = value >> 8 ; | |||
221 | data [offset + 2] = value >> 16 ; | |||
222 | data [offset + 3] = value >> 24 ; | |||
223 | } ; | |||
224 | } /* write_marker */ | |||
225 | ||||
226 | static void | |||
227 | write_str (unsigned char * data, int offset, const char * buffer, int buffer_len) | |||
228 | { memcpy (data + offset, buffer, buffer_len) ; | |||
229 | } /* write_str */ | |||
230 | ||||
231 | static int | |||
232 | sd2_write_rsrc_fork (SF_PRIVATE *psf, int UNUSED (calc_length)UNUSED_calc_length __attribute__ ((unused))) | |||
233 | { SD2_RSRC rsrc ; | |||
234 | STR_RSRC str_rsrc [] = | |||
235 | { { RSRC_STR, 1000, "_sample-size", "", 0 }, | |||
236 | { RSRC_STR, 1001, "_sample-rate", "", 0 }, | |||
237 | { RSRC_STR, 1002, "_channels", "", 0 }, | |||
238 | { RSRC_BIN, 1000, "_Markers", "", 8 } | |||
239 | } ; | |||
240 | ||||
241 | int k, str_offset, data_offset, next_str ; | |||
242 | ||||
243 | psf_use_rsrc (psf, SF_TRUE) ; | |||
244 | ||||
245 | memset (&rsrc, 0, sizeof (rsrc)) ; | |||
246 | ||||
247 | rsrc.sample_rate = psf->sf.samplerate ; | |||
248 | rsrc.sample_size = psf->bytewidth ; | |||
249 | rsrc.channels = psf->sf.channels ; | |||
250 | ||||
251 | rsrc.rsrc_data = psf->header ; | |||
252 | rsrc.rsrc_len = sizeof (psf->header) ; | |||
253 | memset (rsrc.rsrc_data, 0xea, rsrc.rsrc_len) ; | |||
254 | ||||
255 | snprintf (str_rsrc [0].value, sizeof (str_rsrc [0].value), "_%d", rsrc.sample_size)__builtin___snprintf_chk (str_rsrc [0].value, sizeof (str_rsrc [0].value), 2 - 1, __builtin_object_size (str_rsrc [0].value , 2 > 1), "_%d", rsrc.sample_size) ; | |||
256 | snprintf (str_rsrc [1].value, sizeof (str_rsrc [1].value), "_%d.000000", rsrc.sample_rate)__builtin___snprintf_chk (str_rsrc [1].value, sizeof (str_rsrc [1].value), 2 - 1, __builtin_object_size (str_rsrc [1].value , 2 > 1), "_%d.000000", rsrc.sample_rate) ; | |||
257 | snprintf (str_rsrc [2].value, sizeof (str_rsrc [2].value), "_%d", rsrc.channels)__builtin___snprintf_chk (str_rsrc [2].value, sizeof (str_rsrc [2].value), 2 - 1, __builtin_object_size (str_rsrc [2].value , 2 > 1), "_%d", rsrc.channels) ; | |||
258 | ||||
259 | for (k = 0 ; k < ARRAY_LEN (str_rsrc)((int) (sizeof (str_rsrc) / sizeof ((str_rsrc) [0]))) ; k++) | |||
260 | { if (str_rsrc [k].value_len == 0) | |||
261 | { str_rsrc [k].value_len = strlen (str_rsrc [k].value) ; | |||
262 | str_rsrc [k].value [0] = str_rsrc [k].value_len - 1 ; | |||
263 | } ; | |||
264 | ||||
265 | /* Turn name string into a pascal string. */ | |||
266 | str_rsrc [k].name [0] = strlen (str_rsrc [k].name) - 1 ; | |||
267 | } ; | |||
268 | ||||
269 | rsrc.data_offset = 0x100 ; | |||
270 | ||||
271 | /* | |||
272 | ** Calculate data length : | |||
273 | ** length of strings, plus the length of the sdML chunk. | |||
274 | */ | |||
275 | rsrc.data_length = 0 ; | |||
276 | for (k = 0 ; k < ARRAY_LEN (str_rsrc)((int) (sizeof (str_rsrc) / sizeof ((str_rsrc) [0]))) ; k++) | |||
277 | rsrc.data_length += str_rsrc [k].value_len + 4 ; | |||
278 | ||||
279 | rsrc.map_offset = rsrc.data_offset + rsrc.data_length ; | |||
280 | ||||
281 | /* Very start of resource fork. */ | |||
282 | write_int (rsrc.rsrc_data, 0, rsrc.data_offset) ; | |||
283 | write_int (rsrc.rsrc_data, 4, rsrc.map_offset) ; | |||
284 | write_int (rsrc.rsrc_data, 8, rsrc.data_length) ; | |||
285 | ||||
286 | write_char (rsrc.rsrc_data, 0x30, strlen (psf->file.name.c)) ; | |||
287 | write_str (rsrc.rsrc_data, 0x31, psf->file.name.c, strlen (psf->file.name.c)) ; | |||
288 | ||||
289 | write_short (rsrc.rsrc_data, 0x50, 0) ; | |||
290 | write_marker (rsrc.rsrc_data, 0x52, Sd2f_MARKER((uint32_t) (('S') | (('d') << 8) | (('2') << 16) | (((uint32_t) ('f')) << 24)))) ; | |||
291 | write_marker (rsrc.rsrc_data, 0x56, lsf1_MARKER((uint32_t) (('l') | (('s') << 8) | (('f') << 16) | (((uint32_t) ('1')) << 24)))) ; | |||
292 | ||||
293 | /* Very start of resource map. */ | |||
294 | write_int (rsrc.rsrc_data, rsrc.map_offset + 0, rsrc.data_offset) ; | |||
295 | write_int (rsrc.rsrc_data, rsrc.map_offset + 4, rsrc.map_offset) ; | |||
296 | write_int (rsrc.rsrc_data, rsrc.map_offset + 8, rsrc.data_length) ; | |||
297 | ||||
298 | /* These I don't currently understand. */ | |||
299 | if (1) | |||
300 | { write_char (rsrc.rsrc_data, rsrc.map_offset+ 16, 1) ; | |||
301 | /* Next resource map. */ | |||
302 | write_int (rsrc.rsrc_data, rsrc.map_offset + 17, 0x12345678) ; | |||
303 | /* File ref number. */ | |||
304 | write_short (rsrc.rsrc_data, rsrc.map_offset + 21, 0xabcd) ; | |||
305 | /* Fork attributes. */ | |||
306 | write_short (rsrc.rsrc_data, rsrc.map_offset + 23, 0) ; | |||
307 | } ; | |||
308 | ||||
309 | /* Resource type offset. */ | |||
310 | rsrc.type_offset = rsrc.map_offset + 30 ; | |||
311 | write_short (rsrc.rsrc_data, rsrc.map_offset + 24, rsrc.type_offset - rsrc.map_offset - 2) ; | |||
312 | ||||
313 | /* Type index max. */ | |||
314 | rsrc.type_count = 2 ; | |||
315 | write_short (rsrc.rsrc_data, rsrc.map_offset + 28, rsrc.type_count - 1) ; | |||
316 | ||||
317 | rsrc.item_offset = rsrc.type_offset + rsrc.type_count * 8 ; | |||
318 | ||||
319 | rsrc.str_count = ARRAY_LEN (str_rsrc)((int) (sizeof (str_rsrc) / sizeof ((str_rsrc) [0]))) ; | |||
320 | rsrc.string_offset = rsrc.item_offset + (rsrc.str_count + 1) * 12 - rsrc.map_offset ; | |||
321 | write_short (rsrc.rsrc_data, rsrc.map_offset + 26, rsrc.string_offset) ; | |||
322 | ||||
323 | /* Write 'STR ' resource type. */ | |||
324 | rsrc.str_count = 3 ; | |||
325 | write_marker (rsrc.rsrc_data, rsrc.type_offset, STR_MARKER((uint32_t) (('S') | (('T') << 8) | (('R') << 16) | (((uint32_t) (' ')) << 24)))) ; | |||
326 | write_short (rsrc.rsrc_data, rsrc.type_offset + 4, rsrc.str_count - 1) ; | |||
327 | write_short (rsrc.rsrc_data, rsrc.type_offset + 6, 0x12) ; | |||
328 | ||||
329 | /* Write 'sdML' resource type. */ | |||
330 | write_marker (rsrc.rsrc_data, rsrc.type_offset + 8, sdML_MARKER((uint32_t) (('s') | (('d') << 8) | (('M') << 16) | (((uint32_t) ('L')) << 24)))) ; | |||
331 | write_short (rsrc.rsrc_data, rsrc.type_offset + 12, 0) ; | |||
332 | write_short (rsrc.rsrc_data, rsrc.type_offset + 14, 0x36) ; | |||
333 | ||||
334 | str_offset = rsrc.map_offset + rsrc.string_offset ; | |||
335 | next_str = 0 ; | |||
336 | data_offset = rsrc.data_offset ; | |||
337 | for (k = 0 ; k < ARRAY_LEN (str_rsrc)((int) (sizeof (str_rsrc) / sizeof ((str_rsrc) [0]))) ; k++) | |||
338 | { write_str (rsrc.rsrc_data, str_offset, str_rsrc [k].name, strlen (str_rsrc [k].name)) ; | |||
339 | ||||
340 | write_short (rsrc.rsrc_data, rsrc.item_offset + k * 12, str_rsrc [k].id) ; | |||
341 | write_short (rsrc.rsrc_data, rsrc.item_offset + k * 12 + 2, next_str) ; | |||
342 | ||||
343 | str_offset += strlen (str_rsrc [k].name) ; | |||
344 | next_str += strlen (str_rsrc [k].name) ; | |||
345 | ||||
346 | write_int (rsrc.rsrc_data, rsrc.item_offset + k * 12 + 4, data_offset - rsrc.data_offset) ; | |||
347 | ||||
348 | write_int (rsrc.rsrc_data, data_offset, str_rsrc [k].value_len) ; | |||
349 | write_str (rsrc.rsrc_data, data_offset + 4, str_rsrc [k].value, str_rsrc [k].value_len) ; | |||
350 | data_offset += 4 + str_rsrc [k].value_len ; | |||
351 | } ; | |||
352 | ||||
353 | /* Finally, calculate and set map length. */ | |||
354 | rsrc.map_length = str_offset - rsrc.map_offset ; | |||
355 | write_int (rsrc.rsrc_data, 12, rsrc.map_length) ; | |||
356 | write_int (rsrc.rsrc_data, rsrc.map_offset + 12, rsrc.map_length) ; | |||
357 | ||||
358 | rsrc.rsrc_len = rsrc.map_offset + rsrc.map_length ; | |||
359 | ||||
360 | psf_fwrite (rsrc.rsrc_data, rsrc.rsrc_len, 1, psf) ; | |||
361 | ||||
362 | psf_use_rsrc (psf, SF_FALSE) ; | |||
363 | ||||
364 | if (psf->error) | |||
365 | return psf->error ; | |||
366 | ||||
367 | return 0 ; | |||
368 | } /* sd2_write_rsrc_fork */ | |||
369 | ||||
370 | /*------------------------------------------------------------------------------ | |||
371 | */ | |||
372 | ||||
373 | static inline int | |||
374 | read_rsrc_char (const SD2_RSRC *prsrc, int offset) | |||
375 | { const unsigned char * data = prsrc->rsrc_data ; | |||
376 | if (offset < 0 || offset >= prsrc->rsrc_len) | |||
377 | return 0 ; | |||
378 | return data [offset] ; | |||
379 | } /* read_rsrc_char */ | |||
380 | ||||
381 | static inline int | |||
382 | read_rsrc_short (const SD2_RSRC *prsrc, int offset) | |||
383 | { const unsigned char * data = prsrc->rsrc_data ; | |||
384 | if (offset < 0 || offset + 1 >= prsrc->rsrc_len) | |||
385 | return 0 ; | |||
386 | return (data [offset] << 8) + data [offset + 1] ; | |||
387 | } /* read_rsrc_short */ | |||
388 | ||||
389 | static inline int | |||
390 | read_rsrc_int (const SD2_RSRC *prsrc, int offset) | |||
391 | { const unsigned char * data = prsrc->rsrc_data ; | |||
392 | if (offset < 0 || offset + 3 >= prsrc->rsrc_len) | |||
393 | return 0 ; | |||
394 | return (data [offset] << 24) + (data [offset + 1] << 16) + (data [offset + 2] << 8) + data [offset + 3] ; | |||
395 | } /* read_rsrc_int */ | |||
396 | ||||
397 | static inline int | |||
398 | read_rsrc_marker (const SD2_RSRC *prsrc, int offset) | |||
399 | { const unsigned char * data = prsrc->rsrc_data ; | |||
400 | ||||
401 | if (offset < 0 || offset + 3 >= prsrc->rsrc_len) | |||
402 | return 0 ; | |||
403 | ||||
404 | if (CPU_IS_BIG_ENDIAN0) | |||
405 | return (data [offset] << 24) + (data [offset + 1] << 16) + (data [offset + 2] << 8) + data [offset + 3] ; | |||
406 | if (CPU_IS_LITTLE_ENDIAN1) | |||
407 | return data [offset] + (data [offset + 1] << 8) + (data [offset + 2] << 16) + (data [offset + 3] << 24) ; | |||
408 | ||||
409 | return 0 ; | |||
410 | } /* read_rsrc_marker */ | |||
411 | ||||
412 | static void | |||
413 | read_rsrc_str (const SD2_RSRC *prsrc, int offset, char * buffer, int buffer_len) | |||
414 | { const unsigned char * data = prsrc->rsrc_data ; | |||
415 | int k ; | |||
416 | ||||
417 | memset (buffer, 0, buffer_len) ; | |||
418 | ||||
419 | if (offset < 0 || offset + buffer_len >= prsrc->rsrc_len) | |||
420 | return ; | |||
421 | ||||
422 | for (k = 0 ; k < buffer_len - 1 ; k++) | |||
423 | { if (psf_isprint (data [offset + k]) == 0) | |||
424 | return ; | |||
425 | buffer [k] = data [offset + k] ; | |||
426 | } ; | |||
427 | return ; | |||
428 | } /* read_rsrc_str */ | |||
429 | ||||
430 | static int | |||
431 | sd2_parse_rsrc_fork (SF_PRIVATE *psf) | |||
432 | { SD2_RSRC rsrc ; | |||
433 | int k, marker, error = 0 ; | |||
434 | ||||
435 | psf_use_rsrc (psf, SF_TRUE) ; | |||
436 | ||||
437 | memset (&rsrc, 0, sizeof (rsrc)) ; | |||
438 | ||||
439 | rsrc.rsrc_len = psf_get_filelen (psf) ; | |||
440 | psf_log_printf (psf, "Resource length : %d (0x%04X)\n", rsrc.rsrc_len, rsrc.rsrc_len) ; | |||
441 | ||||
442 | if (rsrc.rsrc_len > SIGNED_SIZEOF (psf->header)((int) sizeof (psf->header))) | |||
443 | { rsrc.rsrc_data = calloc (1, rsrc.rsrc_len) ; | |||
444 | rsrc.need_to_free_rsrc_data = SF_TRUE ; | |||
445 | } | |||
446 | else | |||
447 | rsrc.rsrc_data = psf->header ; | |||
448 | ||||
449 | /* Read in the whole lot. */ | |||
450 | psf_fread (rsrc.rsrc_data, rsrc.rsrc_len, 1, psf) ; | |||
451 | ||||
452 | /* Reset the header storage because we have changed to the rsrcdes. */ | |||
453 | psf->headindex = psf->headend = rsrc.rsrc_len ; | |||
454 | ||||
455 | rsrc.data_offset = read_rsrc_int (&rsrc, 0) ; | |||
456 | rsrc.map_offset = read_rsrc_int (&rsrc, 4) ; | |||
457 | rsrc.data_length = read_rsrc_int (&rsrc, 8) ; | |||
458 | rsrc.map_length = read_rsrc_int (&rsrc, 12) ; | |||
459 | ||||
460 | if (rsrc.data_offset == 0x51607 && rsrc.map_offset == 0x20000) | |||
461 | { psf_log_printf (psf, "Trying offset of 0x52 bytes.\n") ; | |||
462 | rsrc.data_offset = read_rsrc_int (&rsrc, 0x52 + 0) + 0x52 ; | |||
463 | rsrc.map_offset = read_rsrc_int (&rsrc, 0x52 + 4) + 0x52 ; | |||
464 | rsrc.data_length = read_rsrc_int (&rsrc, 0x52 + 8) ; | |||
465 | rsrc.map_length = read_rsrc_int (&rsrc, 0x52 + 12) ; | |||
466 | } ; | |||
467 | ||||
468 | psf_log_printf (psf, " data offset : 0x%04X\n map offset : 0x%04X\n" | |||
469 | " data length : 0x%04X\n map length : 0x%04X\n", | |||
470 | rsrc.data_offset, rsrc.map_offset, rsrc.data_length, rsrc.map_length) ; | |||
471 | ||||
472 | if (rsrc.data_offset > rsrc.rsrc_len) | |||
473 | { psf_log_printf (psf, "Error : rsrc.data_offset (%d, 0x%x) > len\n", rsrc.data_offset, rsrc.data_offset) ; | |||
474 | error = SFE_SD2_BAD_DATA_OFFSET ; | |||
475 | goto parse_rsrc_fork_cleanup ; | |||
476 | } ; | |||
477 | ||||
478 | if (rsrc.map_offset > rsrc.rsrc_len) | |||
479 | { psf_log_printf (psf, "Error : rsrc.map_offset > len\n") ; | |||
480 | error = SFE_SD2_BAD_MAP_OFFSET ; | |||
481 | goto parse_rsrc_fork_cleanup ; | |||
482 | } ; | |||
483 | ||||
484 | if (rsrc.data_length > rsrc.rsrc_len) | |||
485 | { psf_log_printf (psf, "Error : rsrc.data_length > len\n") ; | |||
486 | error = SFE_SD2_BAD_DATA_LENGTH ; | |||
487 | goto parse_rsrc_fork_cleanup ; | |||
488 | } ; | |||
489 | ||||
490 | if (rsrc.map_length > rsrc.rsrc_len) | |||
491 | { psf_log_printf (psf, "Error : rsrc.map_length > len\n") ; | |||
492 | error = SFE_SD2_BAD_MAP_LENGTH ; | |||
493 | goto parse_rsrc_fork_cleanup ; | |||
494 | } ; | |||
495 | ||||
496 | if (rsrc.data_offset + rsrc.data_length != rsrc.map_offset || rsrc.map_offset + rsrc.map_length != rsrc.rsrc_len) | |||
497 | { psf_log_printf (psf, "Error : This does not look like a MacOSX resource fork.\n") ; | |||
498 | error = SFE_SD2_BAD_RSRC ; | |||
499 | goto parse_rsrc_fork_cleanup ; | |||
500 | } ; | |||
501 | ||||
502 | if (rsrc.map_offset + 28 >= rsrc.rsrc_len) | |||
503 | { psf_log_printf (psf, "Bad map offset (%d + 28 > %d).\n", rsrc.map_offset, rsrc.rsrc_len) ; | |||
504 | error = SFE_SD2_BAD_RSRC ; | |||
505 | goto parse_rsrc_fork_cleanup ; | |||
506 | } ; | |||
507 | ||||
508 | rsrc.string_offset = rsrc.map_offset + read_rsrc_short (&rsrc, rsrc.map_offset + 26) ; | |||
509 | if (rsrc.string_offset > rsrc.rsrc_len) | |||
510 | { psf_log_printf (psf, "Bad string offset (%d).\n", rsrc.string_offset) ; | |||
511 | error = SFE_SD2_BAD_RSRC ; | |||
512 | goto parse_rsrc_fork_cleanup ; | |||
513 | } ; | |||
514 | ||||
515 | rsrc.type_offset = rsrc.map_offset + 30 ; | |||
516 | ||||
517 | rsrc.type_count = read_rsrc_short (&rsrc, rsrc.map_offset + 28) + 1 ; | |||
518 | if (rsrc.type_count < 1) | |||
519 | { psf_log_printf (psf, "Bad type count.\n") ; | |||
520 | error = SFE_SD2_BAD_RSRC ; | |||
521 | goto parse_rsrc_fork_cleanup ; | |||
522 | } ; | |||
523 | ||||
524 | rsrc.item_offset = rsrc.type_offset + rsrc.type_count * 8 ; | |||
525 | if (rsrc.item_offset < 0 || rsrc.item_offset > rsrc.rsrc_len) | |||
526 | { psf_log_printf (psf, "Bad item offset (%d).\n", rsrc.item_offset) ; | |||
527 | error = SFE_SD2_BAD_RSRC ; | |||
528 | goto parse_rsrc_fork_cleanup ; | |||
529 | } ; | |||
530 | ||||
531 | rsrc.str_index = -1 ; | |||
532 | for (k = 0 ; k < rsrc.type_count ; k ++) | |||
533 | { marker = read_rsrc_marker (&rsrc, rsrc.type_offset + k * 8) ; | |||
534 | ||||
535 | if (marker == STR_MARKER((uint32_t) (('S') | (('T') << 8) | (('R') << 16) | (((uint32_t) (' ')) << 24)))) | |||
536 | { rsrc.str_index = k ; | |||
537 | rsrc.str_count = read_rsrc_short (&rsrc, rsrc.type_offset + k * 8 + 4) + 1 ; | |||
538 | error = parse_str_rsrc (psf, &rsrc) ; | |||
539 | goto parse_rsrc_fork_cleanup ; | |||
540 | } ; | |||
541 | } ; | |||
542 | ||||
543 | psf_log_printf (psf, "No 'STR ' resource.\n") ; | |||
544 | error = SFE_SD2_BAD_RSRC ; | |||
545 | ||||
546 | parse_rsrc_fork_cleanup : | |||
547 | ||||
548 | psf_use_rsrc (psf, SF_FALSE) ; | |||
549 | ||||
550 | if (rsrc.need_to_free_rsrc_data) | |||
551 | free (rsrc.rsrc_data) ; | |||
552 | ||||
553 | return error ; | |||
554 | } /* sd2_parse_rsrc_fork */ | |||
555 | ||||
556 | static int | |||
557 | parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc) | |||
558 | { char name [32], value [32] ; | |||
559 | int k, str_offset, rsrc_id, data_offset = 0, data_len = 0 ; | |||
560 | ||||
561 | psf_log_printf (psf, "Finding parameters :\n") ; | |||
562 | ||||
563 | str_offset = rsrc->string_offset ; | |||
564 | psf_log_printf (psf, " Offset RsrcId dlen slen Value\n") ; | |||
565 | ||||
566 | for (k = 0 ; data_offset + data_len < rsrc->rsrc_len ; k++) | |||
567 | { int slen ; | |||
568 | ||||
569 | slen = read_rsrc_char (rsrc, str_offset) ; | |||
570 | read_rsrc_str (rsrc, str_offset + 1, name, SF_MIN (SIGNED_SIZEOF (name), slen + 1)({ typeof (((int) sizeof (name))) sf_min_x2 = (((int) sizeof ( name))) ; typeof (slen + 1) sf_min_y2 = (slen + 1) ; (void) ( &sf_min_x2 == &sf_min_y2) ; sf_min_x2 < sf_min_y2 ? sf_min_x2 : sf_min_y2 ; })) ; | |||
571 | str_offset += slen + 1 ; | |||
572 | ||||
573 | rsrc_id = read_rsrc_short (rsrc, rsrc->item_offset + k * 12) ; | |||
574 | ||||
575 | data_offset = rsrc->data_offset + read_rsrc_int (rsrc, rsrc->item_offset + k * 12 + 4) ; | |||
576 | if (data_offset < 0 || data_offset > rsrc->rsrc_len) | |||
577 | { psf_log_printf (psf, "Exiting parser on data offset of %d.\n", data_offset) ; | |||
578 | break ; | |||
579 | } ; | |||
580 | ||||
581 | data_len = read_rsrc_int (rsrc, data_offset) ; | |||
582 | if (data_len < 0 || data_len > rsrc->rsrc_len) | |||
583 | { psf_log_printf (psf, "Exiting parser on data length of %d.\n", data_len) ; | |||
584 | break ; | |||
585 | } ; | |||
586 | ||||
587 | slen = read_rsrc_char (rsrc, data_offset + 4) ; | |||
588 | read_rsrc_str (rsrc, data_offset + 5, value, SF_MIN (SIGNED_SIZEOF (value), slen + 1)({ typeof (((int) sizeof (value))) sf_min_x2 = (((int) sizeof (value))) ; typeof (slen + 1) sf_min_y2 = (slen + 1) ; (void ) (&sf_min_x2 == &sf_min_y2) ; sf_min_x2 < sf_min_y2 ? sf_min_x2 : sf_min_y2 ; })) ; | |||
589 | ||||
590 | psf_log_printf (psf, " 0x%04x %4d %4d %3d '%s'\n", data_offset, rsrc_id, data_len, slen, value) ; | |||
591 | ||||
592 | if (rsrc_id == 1000 && rsrc->sample_size == 0) | |||
593 | rsrc->sample_size = strtol (value, NULL((void*)0), 10) ; | |||
594 | else if (rsrc_id == 1001 && rsrc->sample_rate == 0) | |||
595 | rsrc->sample_rate = strtol (value, NULL((void*)0), 10) ; | |||
596 | else if (rsrc_id == 1002 && rsrc->channels == 0) | |||
597 | rsrc->channels = strtol (value, NULL((void*)0), 10) ; | |||
598 | } ; | |||
599 | ||||
600 | psf_log_printf (psf, "Found Parameters :\n") ; | |||
601 | psf_log_printf (psf, " sample-size : %d\n", rsrc->sample_size) ; | |||
602 | psf_log_printf (psf, " sample-rate : %d\n", rsrc->sample_rate) ; | |||
603 | psf_log_printf (psf, " channels : %d\n", rsrc->channels) ; | |||
604 | ||||
605 | if (rsrc->sample_rate <= 4 && rsrc->sample_size > 4) | |||
606 | { int temp ; | |||
607 | ||||
608 | psf_log_printf (psf, "Geez!! Looks like sample rate and sample size got switched.\nCorrecting this screw up.\n") ; | |||
609 | temp = rsrc->sample_rate ; | |||
610 | rsrc->sample_rate = rsrc->sample_size ; | |||
611 | rsrc->sample_size = temp ; | |||
612 | } ; | |||
613 | ||||
614 | if (rsrc->sample_rate < 0) | |||
615 | { psf_log_printf (psf, "Bad sample rate (%d)\n", rsrc->sample_rate) ; | |||
616 | return SFE_SD2_BAD_RSRC ; | |||
617 | } ; | |||
618 | ||||
619 | if (rsrc->channels < 0) | |||
620 | { psf_log_printf (psf, "Bad channel count (%d)\n", rsrc->channels) ; | |||
621 | return SFE_SD2_BAD_RSRC ; | |||
622 | } ; | |||
623 | ||||
624 | psf->sf.samplerate = rsrc->sample_rate ; | |||
625 | psf->sf.channels = rsrc->channels ; | |||
626 | psf->bytewidth = rsrc->sample_size ; | |||
627 | ||||
628 | switch (rsrc->sample_size) | |||
629 | { case 1 : | |||
630 | psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_S8 ; | |||
631 | break ; | |||
632 | ||||
633 | case 2 : | |||
634 | psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_16 ; | |||
635 | break ; | |||
636 | ||||
637 | case 3 : | |||
638 | psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_24 ; | |||
639 | break ; | |||
640 | ||||
641 | case 4 : | |||
642 | psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_32 ; | |||
643 | break ; | |||
644 | ||||
645 | default : | |||
646 | psf_log_printf (psf, "Bad sample size (%d)\n", rsrc->sample_size) ; | |||
647 | return SFE_SD2_BAD_SAMPLE_SIZE ; | |||
648 | } ; | |||
649 | ||||
650 | psf_log_printf (psf, "ok\n") ; | |||
651 | ||||
652 | return 0 ; | |||
653 | } /* parse_str_rsrc */ | |||
654 |