| 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 |