1 ////////////////////////////////////////////////////////////////////////////
2 //                           **** WAVPACK ****                            //
3 //                  Hybrid Lossless Wavefile Compressor                   //
4 //                Copyright (c) 1998 - 2019 David Bryant.                 //
5 //                          All Rights Reserved.                          //
6 //      Distributed under the BSD Software License (see license.txt)      //
7 ////////////////////////////////////////////////////////////////////////////
8 
9 // open_utils.c
10 
11 // This module provides all the code required to open an existing WavPack file
12 // for reading by using a reader callback mechanism (NOT a filename). This
13 // includes the code required to find and parse WavPack blocks, process any
14 // included metadata, and queue up the bitstreams containing the encoded audio
15 // data. It does not the actual code to unpack audio data and this was done so
16 // that programs that just want to query WavPack files for information (like,
17 // for example, taggers) don't need to link in a lot of unnecessary code.
18 
19 #include <stdlib.h>
20 #include <string.h>
21 
22 #include "wavpack_local.h"
23 
24 // This function is identical to WavpackOpenFileInput() except that instead
25 // of providing a filename to open, the caller provides a pointer to a set of
26 // reader callbacks and instances of up to two streams. The first of these
27 // streams is required and contains the regular WavPack data stream; the second
28 // contains the "correction" file if desired. Unlike the standard open
29 // function which handles the correction file transparently, in this case it
30 // is the responsibility of the caller to be aware of correction files.
31 
32 static int seek_eof_information (WavpackContext *wpc, int64_t *final_index, int get_wrapper);
33 
WavpackOpenFileInputEx64(WavpackStreamReader64 * reader,void * wv_id,void * wvc_id,char * error,int flags,int norm_offset)34 WavpackContext *WavpackOpenFileInputEx64 (WavpackStreamReader64 *reader, void *wv_id, void *wvc_id, char *error, int flags, int norm_offset)
35 {
36     WavpackContext *wpc = (WavpackContext *)malloc (sizeof (WavpackContext));
37     WavpackStream *wps;
38     int num_blocks = 0;
39     unsigned char first_byte;
40     uint32_t bcount;
41 
42     if (!wpc) {
43         if (error) strcpy (error, "can't allocate memory");
44         return NULL;
45     }
46 
47     CLEAR (*wpc);
48     wpc->wv_in = wv_id;
49     wpc->wvc_in = wvc_id;
50     wpc->reader = reader;
51     wpc->total_samples = -1;
52     wpc->norm_offset = norm_offset;
53     wpc->max_streams = OLD_MAX_STREAMS;     // use this until overwritten with actual number
54     wpc->open_flags = flags;
55 
56     wpc->filelen = wpc->reader->get_length (wpc->wv_in);
57 
58 #ifndef NO_TAGS
59     if ((flags & (OPEN_TAGS | OPEN_EDIT_TAGS)) && wpc->reader->can_seek (wpc->wv_in)) {
60         load_tag (wpc);
61         wpc->reader->set_pos_abs (wpc->wv_in, 0);
62 
63         if ((flags & OPEN_EDIT_TAGS) && !editable_tag (&wpc->m_tag)) {
64             if (error) strcpy (error, "can't edit tags located at the beginning of files!");
65             return WavpackCloseFile (wpc);
66         }
67     }
68 #endif
69 
70     if (wpc->reader->read_bytes (wpc->wv_in, &first_byte, 1) != 1) {
71         if (error) strcpy (error, "can't read all of WavPack file!");
72         return WavpackCloseFile (wpc);
73     }
74 
75     wpc->reader->push_back_byte (wpc->wv_in, first_byte);
76 
77     if (first_byte == 'R') {
78 #ifdef ENABLE_LEGACY
79         return open_file3 (wpc, error);
80 #else
81         if (error) strcpy (error, "this legacy WavPack file is deprecated, use version 4.80.0 to transcode");
82         return WavpackCloseFile (wpc);
83 #endif
84     }
85 
86     wpc->streams = (WavpackStream **)(malloc ((wpc->num_streams = 1) * sizeof (wpc->streams [0])));
87     if (!wpc->streams) {
88         if (error) strcpy (error, "can't allocate memory");
89         return WavpackCloseFile (wpc);
90     }
91 
92     wpc->streams [0] = wps = (WavpackStream *)malloc (sizeof (WavpackStream));
93     if (!wps) {
94         if (error) strcpy (error, "can't allocate memory");
95         return WavpackCloseFile (wpc);
96     }
97     CLEAR (*wps);
98 
99     while (!wps->wphdr.block_samples) {
100 
101         wpc->filepos = wpc->reader->get_pos (wpc->wv_in);
102         bcount = read_next_header (wpc->reader, wpc->wv_in, &wps->wphdr);
103 
104         if (bcount == (uint32_t) -1 ||
105             (!wps->wphdr.block_samples && num_blocks++ > 16)) {
106                 if (error) strcpy (error, "not compatible with this version of WavPack file!");
107                 return WavpackCloseFile (wpc);
108         }
109 
110         wpc->filepos += bcount;
111         wps->blockbuff = (unsigned char *)malloc (wps->wphdr.ckSize + 8);
112         if (!wps->blockbuff) {
113             if (error) strcpy (error, "can't allocate memory");
114             return WavpackCloseFile (wpc);
115         }
116         memcpy (wps->blockbuff, &wps->wphdr, 32);
117 
118         if (wpc->reader->read_bytes (wpc->wv_in, wps->blockbuff + 32, wps->wphdr.ckSize - 24) != wps->wphdr.ckSize - 24) {
119             if (error) strcpy (error, "can't read all of WavPack file!");
120             return WavpackCloseFile (wpc);
121         }
122 
123         // if block does not verify, flag error, free buffer, and continue
124         if (!WavpackVerifySingleBlock (wps->blockbuff, !(flags & OPEN_NO_CHECKSUM))) {
125             wps->wphdr.block_samples = 0;
126             free (wps->blockbuff);
127             wps->blockbuff = NULL;
128             wpc->crc_errors++;
129             continue;
130         }
131 
132         wps->init_done = FALSE;
133 
134         if (wps->wphdr.block_samples) {
135             if (flags & OPEN_STREAMING)
136                 SET_BLOCK_INDEX (wps->wphdr, 0);
137             else if (wpc->total_samples == -1) {
138                 if (GET_BLOCK_INDEX (wps->wphdr) || GET_TOTAL_SAMPLES (wps->wphdr) == -1) {
139                     wpc->initial_index = GET_BLOCK_INDEX (wps->wphdr);
140                     SET_BLOCK_INDEX (wps->wphdr, 0);
141 
142                     if (wpc->reader->can_seek (wpc->wv_in)) {
143                         int64_t final_index = -1;
144 
145                         seek_eof_information (wpc, &final_index, FALSE);
146 
147                         if (final_index != -1)
148                             wpc->total_samples = final_index - wpc->initial_index;
149                     }
150                 }
151                 else
152                     wpc->total_samples = GET_TOTAL_SAMPLES (wps->wphdr);
153             }
154         }
155         else if (wpc->total_samples == -1 && !GET_BLOCK_INDEX (wps->wphdr) && GET_TOTAL_SAMPLES (wps->wphdr))
156             wpc->total_samples = GET_TOTAL_SAMPLES (wps->wphdr);
157 
158         if (wpc->wvc_in && wps->wphdr.block_samples && (wps->wphdr.flags & HYBRID_FLAG)) {
159             unsigned char ch;
160 
161             if (wpc->reader->read_bytes (wpc->wvc_in, &ch, 1) == 1) {
162                 wpc->reader->push_back_byte (wpc->wvc_in, ch);
163                 wpc->file2len = wpc->reader->get_length (wpc->wvc_in);
164                 wpc->wvc_flag = TRUE;
165             }
166         }
167 
168         if (wpc->wvc_flag && !read_wvc_block (wpc)) {
169             if (error) strcpy (error, "not compatible with this version of correction file!");
170             return WavpackCloseFile (wpc);
171         }
172 
173         if (!wps->init_done && !unpack_init (wpc)) {
174             if (error) strcpy (error, wpc->error_message [0] ? wpc->error_message :
175                 "not compatible with this version of WavPack file!");
176 
177             return WavpackCloseFile (wpc);
178         }
179 
180         if (!wps->wphdr.block_samples) {    // free blockbuff if we're going to loop again
181             free (wps->blockbuff);
182             wps->blockbuff = NULL;
183         }
184 
185         wps->init_done = TRUE;
186     }
187 
188     wpc->config.flags &= ~0xff;
189     wpc->config.flags |= wps->wphdr.flags & 0xff;
190 
191     if (!wpc->config.num_channels) {
192         wpc->config.num_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2;
193         wpc->config.channel_mask = 0x5 - wpc->config.num_channels;
194     }
195 
196     if ((flags & OPEN_2CH_MAX) && !(wps->wphdr.flags & FINAL_BLOCK))
197         wpc->reduced_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2;
198 
199     if (wps->wphdr.flags & DSD_FLAG) {
200 #ifdef ENABLE_DSD
201         if (flags & OPEN_DSD_NATIVE) {
202             wpc->config.bytes_per_sample = 1;
203             wpc->config.bits_per_sample = 8;
204         }
205         else if (flags & OPEN_DSD_AS_PCM) {
206             wpc->decimation_context = decimate_dsd_init (wpc->reduced_channels ?
207                 wpc->reduced_channels : wpc->config.num_channels);
208 
209             wpc->config.bytes_per_sample = 3;
210             wpc->config.bits_per_sample = 24;
211         }
212         else {
213             if (error) strcpy (error, "not configured to handle DSD WavPack files!");
214             return WavpackCloseFile (wpc);
215         }
216 #else
217         if (error) strcpy (error, "not configured to handle DSD WavPack files!");
218         return WavpackCloseFile (wpc);
219 #endif
220     }
221     else {
222         wpc->config.bytes_per_sample = (wps->wphdr.flags & BYTES_STORED) + 1;
223         wpc->config.float_norm_exp = wps->float_norm_exp;
224 
225         wpc->config.bits_per_sample = (wpc->config.bytes_per_sample * 8) -
226             ((wps->wphdr.flags & SHIFT_MASK) >> SHIFT_LSB);
227     }
228 
229     if (!wpc->config.sample_rate) {
230         if (!wps->wphdr.block_samples || (wps->wphdr.flags & SRATE_MASK) == SRATE_MASK)
231             wpc->config.sample_rate = 44100;
232         else
233             wpc->config.sample_rate = sample_rates [(wps->wphdr.flags & SRATE_MASK) >> SRATE_LSB];
234     }
235 
236     return wpc;
237 }
238 
239 // This function returns the major version number of the WavPack program
240 // (or library) that created the open file. Currently, this can be 1 to 5.
241 // Minor versions are not recorded in WavPack files.
242 
WavpackGetVersion(WavpackContext * wpc)243 int WavpackGetVersion (WavpackContext *wpc)
244 {
245     if (wpc) {
246 #ifdef ENABLE_LEGACY
247         if (wpc->stream3)
248             return get_version3 (wpc);
249 #endif
250         return wpc->version_five ? 5 : 4;
251     }
252 
253     return 0;
254 }
255 
256 // Return the file format specified in the call to WavpackSetFileInformation()
257 // when the file was created. For all files created prior to WavPack 5.0 this
258 // will 0 (WP_FORMAT_WAV).
259 
WavpackGetFileFormat(WavpackContext * wpc)260 unsigned char WavpackGetFileFormat (WavpackContext *wpc)
261 {
262     return wpc->file_format;
263 }
264 
265 // Return a string representing the recommended file extension for the open
266 // WavPack file. For all files created prior to WavPack 5.0 this will be "wav",
267 // even for raw files with no RIFF into. This string is specified in the
268 // call to WavpackSetFileInformation() when the file was created.
269 
WavpackGetFileExtension(WavpackContext * wpc)270 char *WavpackGetFileExtension (WavpackContext *wpc)
271 {
272     if (wpc && wpc->file_extension [0])
273         return wpc->file_extension;
274     else
275         return "wav";
276 }
277 
278 // This function initializes everything required to unpack a WavPack block
279 // and must be called before unpack_samples() is called to obtain audio data.
280 // It is assumed that the WavpackHeader has been read into the wps->wphdr
281 // (in the current WavpackStream) and that the entire block has been read at
282 // wps->blockbuff. If a correction file is available (wpc->wvc_flag = TRUE)
283 // then the corresponding correction block must be read into wps->block2buff
284 // and its WavpackHeader has overwritten the header at wps->wphdr. This is
285 // where all the metadata blocks are scanned including those that contain
286 // bitstream data.
287 
288 static int read_metadata_buff (WavpackMetadata *wpmd, unsigned char *blockbuff, unsigned char **buffptr);
289 static int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd);
290 static void bs_open_read (Bitstream *bs, void *buffer_start, void *buffer_end);
291 
unpack_init(WavpackContext * wpc)292 int unpack_init (WavpackContext *wpc)
293 {
294     WavpackStream *wps = wpc->streams [wpc->current_stream];
295     unsigned char *blockptr, *block2ptr;
296     WavpackMetadata wpmd;
297 
298     wps->num_terms = 0;
299     wps->mute_error = FALSE;
300     wps->crc = wps->crc_x = 0xffffffff;
301     wps->dsd.ready = 0;
302     CLEAR (wps->wvbits);
303     CLEAR (wps->wvcbits);
304     CLEAR (wps->wvxbits);
305     CLEAR (wps->decorr_passes);
306     CLEAR (wps->dc);
307     CLEAR (wps->w);
308 
309     if (!(wps->wphdr.flags & MONO_FLAG) && wpc->config.num_channels && wps->wphdr.block_samples &&
310         (wpc->reduced_channels == 1 || wpc->config.num_channels == 1)) {
311             wps->mute_error = TRUE;
312             return FALSE;
313     }
314 
315     if ((wps->wphdr.flags & UNKNOWN_FLAGS) || (wps->wphdr.flags & MONO_DATA) == MONO_DATA) {
316         wps->mute_error = TRUE;
317         return FALSE;
318     }
319 
320     blockptr = wps->blockbuff + sizeof (WavpackHeader);
321 
322     while (read_metadata_buff (&wpmd, wps->blockbuff, &blockptr))
323         if (!process_metadata (wpc, &wpmd)) {
324             wps->mute_error = TRUE;
325             return FALSE;
326         }
327 
328     if (wps->wphdr.block_samples && wpc->wvc_flag && wps->block2buff) {
329         block2ptr = wps->block2buff + sizeof (WavpackHeader);
330 
331         while (read_metadata_buff (&wpmd, wps->block2buff, &block2ptr))
332             if (!process_metadata (wpc, &wpmd)) {
333                 wps->mute_error = TRUE;
334                 return FALSE;
335             }
336     }
337 
338     if (wps->wphdr.block_samples && ((wps->wphdr.flags & DSD_FLAG) ? !wps->dsd.ready : !bs_is_open (&wps->wvbits))) {
339         if (bs_is_open (&wps->wvcbits))
340             strcpy (wpc->error_message, "can't unpack correction files alone!");
341 
342         wps->mute_error = TRUE;
343         return FALSE;
344     }
345 
346     if (wps->wphdr.block_samples && !bs_is_open (&wps->wvxbits)) {
347         if ((wps->wphdr.flags & INT32_DATA) && wps->int32_sent_bits)
348             wpc->lossy_blocks = TRUE;
349 
350         if ((wps->wphdr.flags & FLOAT_DATA) &&
351             wps->float_flags & (FLOAT_EXCEPTIONS | FLOAT_ZEROS_SENT | FLOAT_SHIFT_SENT | FLOAT_SHIFT_SAME))
352                 wpc->lossy_blocks = TRUE;
353     }
354 
355     if (wps->wphdr.block_samples)
356         wps->sample_index = GET_BLOCK_INDEX (wps->wphdr);
357 
358     return TRUE;
359 }
360 
361 //////////////////////////////// matadata handlers ///////////////////////////////
362 
363 // These functions handle specific metadata types and are called directly
364 // during WavPack block parsing by process_metadata() at the bottom.
365 
366 // This function initializes the main bitstream for audio samples, which must
367 // be in the "wv" file.
368 
init_wv_bitstream(WavpackStream * wps,WavpackMetadata * wpmd)369 static int init_wv_bitstream (WavpackStream *wps, WavpackMetadata *wpmd)
370 {
371     if (!wpmd->byte_length || (wpmd->byte_length & 1))
372         return FALSE;
373 
374     bs_open_read (&wps->wvbits, wpmd->data, (unsigned char *) wpmd->data + wpmd->byte_length);
375     return TRUE;
376 }
377 
378 // This function initializes the "correction" bitstream for audio samples,
379 // which currently must be in the "wvc" file.
380 
init_wvc_bitstream(WavpackStream * wps,WavpackMetadata * wpmd)381 static int init_wvc_bitstream (WavpackStream *wps, WavpackMetadata *wpmd)
382 {
383     if (!wpmd->byte_length || (wpmd->byte_length & 1))
384         return FALSE;
385 
386     bs_open_read (&wps->wvcbits, wpmd->data, (unsigned char *) wpmd->data + wpmd->byte_length);
387     return TRUE;
388 }
389 
390 // This function initializes the "extra" bitstream for audio samples which
391 // contains the information required to losslessly decompress 32-bit float data
392 // or integer data that exceeds 24 bits. This bitstream is in the "wv" file
393 // for pure lossless data or the "wvc" file for hybrid lossless. This data
394 // would not be used for hybrid lossy mode. There is also a 32-bit CRC stored
395 // in the first 4 bytes of these blocks.
396 
init_wvx_bitstream(WavpackStream * wps,WavpackMetadata * wpmd)397 static int init_wvx_bitstream (WavpackStream *wps, WavpackMetadata *wpmd)
398 {
399     unsigned char *cp = (unsigned char *)wpmd->data;
400 
401     if (wpmd->byte_length <= 4 || (wpmd->byte_length & 1))
402         return FALSE;
403 
404     wps->crc_wvx = *cp++;
405     wps->crc_wvx |= (uint32_t) *cp++ << 8;
406     wps->crc_wvx |= (uint32_t) *cp++ << 16;
407     wps->crc_wvx |= (uint32_t) *cp++ << 24;
408 
409     bs_open_read (&wps->wvxbits, cp, (unsigned char *) wpmd->data + wpmd->byte_length);
410     return TRUE;
411 }
412 
413 // Read the int32 data from the specified metadata into the specified stream.
414 // This data is used for integer data that has more than 24 bits of magnitude
415 // or, in some cases, used to eliminate redundant bits from any audio stream.
416 
read_int32_info(WavpackStream * wps,WavpackMetadata * wpmd)417 static int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd)
418 {
419     int bytecnt = wpmd->byte_length;
420     char *byteptr = (char *)wpmd->data;
421 
422     if (bytecnt != 4)
423         return FALSE;
424 
425     wps->int32_sent_bits = *byteptr++;
426     wps->int32_zeros = *byteptr++;
427     wps->int32_ones = *byteptr++;
428     wps->int32_dups = *byteptr;
429 
430     return TRUE;
431 }
432 
read_float_info(WavpackStream * wps,WavpackMetadata * wpmd)433 static int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
434 {
435     int bytecnt = wpmd->byte_length;
436     char *byteptr = (char *)wpmd->data;
437 
438     if (bytecnt != 4)
439         return FALSE;
440 
441     wps->float_flags = *byteptr++;
442     wps->float_shift = *byteptr++;
443     wps->float_max_exp = *byteptr++;
444     wps->float_norm_exp = *byteptr;
445     return TRUE;
446 }
447 
448 // Read multichannel information from metadata. The first byte is the total
449 // number of channels and the following bytes represent the channel_mask
450 // as described for Microsoft WAVEFORMATEX.
451 
read_channel_info(WavpackContext * wpc,WavpackMetadata * wpmd)452 static int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd)
453 {
454     int bytecnt = wpmd->byte_length, shift = 0, mask_bits;
455     unsigned char *byteptr = (unsigned char *)wpmd->data;
456     uint32_t mask = 0;
457 
458     if (!bytecnt || bytecnt > 7)
459         return FALSE;
460 
461     if (!wpc->config.num_channels) {
462 
463         // if bytecnt is 6 or 7 we are using new configuration with "unlimited" streams
464 
465         if (bytecnt >= 6) {
466             wpc->config.num_channels = (byteptr [0] | ((byteptr [2] & 0xf) << 8)) + 1;
467             wpc->max_streams = (byteptr [1] | ((byteptr [2] & 0xf0) << 4)) + 1;
468 
469             if (wpc->config.num_channels < wpc->max_streams)
470                 return FALSE;
471 
472             byteptr += 3;
473             mask = *byteptr++;
474             mask |= (uint32_t) *byteptr++ << 8;
475             mask |= (uint32_t) *byteptr++ << 16;
476 
477             if (bytecnt == 7)                           // this was introduced in 5.0
478                 mask |= (uint32_t) *byteptr << 24;
479         }
480         else {
481             wpc->config.num_channels = *byteptr++;
482 
483             while (--bytecnt) {
484                 mask |= (uint32_t) *byteptr++ << shift;
485                 shift += 8;
486             }
487         }
488 
489         if (wpc->config.num_channels > wpc->max_streams * 2)
490             return FALSE;
491 
492         wpc->config.channel_mask = mask;
493 
494         for (mask_bits = 0; mask; mask >>= 1)
495             if ((mask & 1) && ++mask_bits > wpc->config.num_channels)
496                 return FALSE;
497     }
498 
499     return TRUE;
500 }
501 
502 // Read multichannel identity information from metadata. Data is an array of
503 // unsigned characters representing any channels in the file that DO NOT
504 // match one the 18 Microsoft standard channels (and are represented in the
505 // channel mask). A value of 0 is not allowed and 0xff means an unknown or
506 // undefined channel identity.
507 
read_channel_identities(WavpackContext * wpc,WavpackMetadata * wpmd)508 static int read_channel_identities (WavpackContext *wpc, WavpackMetadata *wpmd)
509 {
510     unsigned char *idents = wpmd->data;
511     int i;
512 
513     if (!wpmd->data || !wpmd->byte_length)
514         return FALSE;
515 
516     for (i = 0; i < wpmd->byte_length; ++i)
517         if (!idents [i])
518             return FALSE;
519 
520     if (!wpc->channel_identities) {
521         wpc->channel_identities = (unsigned char *)malloc (wpmd->byte_length + 1);
522         memcpy (wpc->channel_identities, wpmd->data, wpmd->byte_length);
523         wpc->channel_identities [wpmd->byte_length] = 0;
524     }
525 
526     return TRUE;
527 }
528 
529 // Read configuration information from metadata.
530 
read_config_info(WavpackContext * wpc,WavpackMetadata * wpmd)531 static int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
532 {
533     int bytecnt = wpmd->byte_length;
534     unsigned char *byteptr = (unsigned char *)wpmd->data;
535 
536     if (bytecnt >= 3) {
537         wpc->config.flags &= 0xff;
538         wpc->config.flags |= (uint32_t) *byteptr++ << 8;
539         wpc->config.flags |= (uint32_t) *byteptr++ << 16;
540         wpc->config.flags |= (uint32_t) *byteptr++ << 24;
541         bytecnt -= 3;
542 
543         if (bytecnt && (wpc->config.flags & CONFIG_EXTRA_MODE)) {
544             wpc->config.xmode = *byteptr++;
545             bytecnt--;
546         }
547 
548         // we used an extra config byte here for the 5.0.0 alpha, so still
549         // honor it now (but this has been replaced with NEW_CONFIG)
550 
551         if (bytecnt) {
552             wpc->config.qmode = (wpc->config.qmode & ~0xff) | *byteptr;
553             wpc->version_five = 1;
554         }
555     }
556 
557     return TRUE;
558 }
559 
560 // Read "new" configuration information from metadata.
561 
read_new_config_info(WavpackContext * wpc,WavpackMetadata * wpmd)562 static int read_new_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
563 {
564     int bytecnt = wpmd->byte_length;
565     unsigned char *byteptr = (unsigned char *)wpmd->data;
566 
567     wpc->version_five = 1;      // just having this block signals version 5.0
568 
569     wpc->file_format = wpc->config.qmode = wpc->channel_layout = 0;
570 
571     if (wpc->channel_reordering) {
572         free (wpc->channel_reordering);
573         wpc->channel_reordering = NULL;
574     }
575 
576     // if there's any data, the first two bytes are file_format and qmode flags
577 
578     if (bytecnt >= 2) {
579         wpc->file_format = *byteptr++;
580         wpc->config.qmode = (wpc->config.qmode & ~0xff) | *byteptr++;
581         bytecnt -= 2;
582 
583         // another byte indicates a channel layout
584 
585         if (bytecnt) {
586             int nchans, i;
587 
588             wpc->channel_layout = (uint32_t) *byteptr++ << 16;
589             bytecnt--;
590 
591             // another byte means we have a channel count for the layout and maybe a reordering
592 
593             if (bytecnt) {
594                 wpc->channel_layout += nchans = *byteptr++;
595                 bytecnt--;
596 
597                 // any more means there's a reordering string
598 
599                 if (bytecnt) {
600                     if (bytecnt > nchans)
601                         return FALSE;
602 
603                     wpc->channel_reordering = (unsigned char *)malloc (nchans);
604 
605                     // note that redundant reordering info is not stored, so we fill in the rest
606 
607                     if (wpc->channel_reordering) {
608                         for (i = 0; i < nchans; ++i)
609                             if (bytecnt) {
610                                 wpc->channel_reordering [i] = *byteptr++;
611 
612                                 if (wpc->channel_reordering [i] >= nchans)  // make sure index is in range
613                                     wpc->channel_reordering [i] = 0;
614 
615                                 bytecnt--;
616                             }
617                             else
618                                 wpc->channel_reordering [i] = i;
619                     }
620                 }
621             }
622             else
623                 wpc->channel_layout += wpc->config.num_channels;
624         }
625     }
626 
627     return TRUE;
628 }
629 
630 // Read non-standard sampling rate from metadata.
631 
read_sample_rate(WavpackContext * wpc,WavpackMetadata * wpmd)632 static int read_sample_rate (WavpackContext *wpc, WavpackMetadata *wpmd)
633 {
634     int bytecnt = wpmd->byte_length;
635     unsigned char *byteptr = (unsigned char *)wpmd->data;
636 
637     if (bytecnt == 3 || bytecnt == 4) {
638         wpc->config.sample_rate = (int32_t) *byteptr++;
639         wpc->config.sample_rate |= (int32_t) *byteptr++ << 8;
640         wpc->config.sample_rate |= (int32_t) *byteptr++ << 16;
641 
642         // for sampling rates > 16777215 (non-audio probably, or ...)
643 
644         if (bytecnt == 4)
645             wpc->config.sample_rate |= (int32_t) (*byteptr & 0x7f) << 24;
646     }
647 
648     return TRUE;
649 }
650 
651 // Read wrapper data from metadata. Currently, this consists of the RIFF
652 // header and trailer that wav files contain around the audio data but could
653 // be used for other formats as well. Because WavPack files contain all the
654 // information required for decoding and playback, this data can probably
655 // be ignored except when an exact wavefile restoration is needed.
656 
read_wrapper_data(WavpackContext * wpc,WavpackMetadata * wpmd)657 static int read_wrapper_data (WavpackContext *wpc, WavpackMetadata *wpmd)
658 {
659     if ((wpc->open_flags & OPEN_WRAPPER) && wpc->wrapper_bytes < MAX_WRAPPER_BYTES && wpmd->byte_length) {
660         wpc->wrapper_data = (unsigned char *)realloc (wpc->wrapper_data, wpc->wrapper_bytes + wpmd->byte_length);
661 	if (!wpc->wrapper_data)
662 	    return FALSE;
663         memcpy (wpc->wrapper_data + wpc->wrapper_bytes, wpmd->data, wpmd->byte_length);
664         wpc->wrapper_bytes += wpmd->byte_length;
665     }
666 
667     return TRUE;
668 }
669 
read_metadata_buff(WavpackMetadata * wpmd,unsigned char * blockbuff,unsigned char ** buffptr)670 static int read_metadata_buff (WavpackMetadata *wpmd, unsigned char *blockbuff, unsigned char **buffptr)
671 {
672     WavpackHeader *wphdr = (WavpackHeader *) blockbuff;
673     unsigned char *buffend = blockbuff + wphdr->ckSize + 8;
674 
675     if (buffend - *buffptr < 2)
676         return FALSE;
677 
678     wpmd->id = *(*buffptr)++;
679     wpmd->byte_length = *(*buffptr)++ << 1;
680 
681     if (wpmd->id & ID_LARGE) {
682         wpmd->id &= ~ID_LARGE;
683 
684         if (buffend - *buffptr < 2)
685             return FALSE;
686 
687         wpmd->byte_length += *(*buffptr)++ << 9;
688         wpmd->byte_length += *(*buffptr)++ << 17;
689     }
690 
691     if (wpmd->id & ID_ODD_SIZE) {
692         if (!wpmd->byte_length)         // odd size and zero length makes no sense
693             return FALSE;
694         wpmd->id &= ~ID_ODD_SIZE;
695         wpmd->byte_length--;
696     }
697 
698     if (wpmd->byte_length) {
699         if (buffend - *buffptr < wpmd->byte_length + (wpmd->byte_length & 1)) {
700             wpmd->data = NULL;
701             return FALSE;
702         }
703 
704         wpmd->data = *buffptr;
705         (*buffptr) += wpmd->byte_length + (wpmd->byte_length & 1);
706     }
707     else
708         wpmd->data = NULL;
709 
710     return TRUE;
711 }
712 
process_metadata(WavpackContext * wpc,WavpackMetadata * wpmd)713 static int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd)
714 {
715     WavpackStream *wps = wpc->streams [wpc->current_stream];
716 
717     switch (wpmd->id) {
718         case ID_DUMMY:
719             return TRUE;
720 
721         case ID_DECORR_TERMS:
722             return read_decorr_terms (wps, wpmd);
723 
724         case ID_DECORR_WEIGHTS:
725             return read_decorr_weights (wps, wpmd);
726 
727         case ID_DECORR_SAMPLES:
728             return read_decorr_samples (wps, wpmd);
729 
730         case ID_ENTROPY_VARS:
731             return read_entropy_vars (wps, wpmd);
732 
733         case ID_HYBRID_PROFILE:
734             return read_hybrid_profile (wps, wpmd);
735 
736         case ID_SHAPING_WEIGHTS:
737             return read_shaping_info (wps, wpmd);
738 
739         case ID_FLOAT_INFO:
740             return read_float_info (wps, wpmd);
741 
742         case ID_INT32_INFO:
743             return read_int32_info (wps, wpmd);
744 
745         case ID_CHANNEL_INFO:
746             return read_channel_info (wpc, wpmd);
747 
748         case ID_CHANNEL_IDENTITIES:
749             return read_channel_identities (wpc, wpmd);
750 
751         case ID_CONFIG_BLOCK:
752             return read_config_info (wpc, wpmd);
753 
754         case ID_NEW_CONFIG_BLOCK:
755             return read_new_config_info (wpc, wpmd);
756 
757         case ID_SAMPLE_RATE:
758             return read_sample_rate (wpc, wpmd);
759 
760         case ID_WV_BITSTREAM:
761             return init_wv_bitstream (wps, wpmd);
762 
763         case ID_WVC_BITSTREAM:
764             return init_wvc_bitstream (wps, wpmd);
765 
766         case ID_WVX_BITSTREAM:
767             return init_wvx_bitstream (wps, wpmd);
768 
769         case ID_DSD_BLOCK:
770 #ifdef ENABLE_DSD
771             return init_dsd_block (wpc, wpmd);
772 #else
773             strcpy (wpc->error_message, "not configured to handle DSD WavPack files!");
774             return FALSE;
775 #endif
776 
777         case ID_ALT_HEADER: case ID_ALT_TRAILER:
778             if (!(wpc->open_flags & OPEN_ALT_TYPES))
779                 return TRUE;
780 
781         case ID_RIFF_HEADER: case ID_RIFF_TRAILER:
782             return read_wrapper_data (wpc, wpmd);
783 
784         case ID_ALT_MD5_CHECKSUM:
785             if (!(wpc->open_flags & OPEN_ALT_TYPES))
786                 return TRUE;
787 
788         case ID_MD5_CHECKSUM:
789             if (wpmd->byte_length == 16) {
790                 memcpy (wpc->config.md5_checksum, wpmd->data, 16);
791                 wpc->config.flags |= CONFIG_MD5_CHECKSUM;
792                 wpc->config.md5_read = 1;
793             }
794 
795             return TRUE;
796 
797         case ID_ALT_EXTENSION:
798             if (wpmd->byte_length && wpmd->byte_length < sizeof (wpc->file_extension)) {
799                 memcpy (wpc->file_extension, wpmd->data, wpmd->byte_length);
800                 wpc->file_extension [wpmd->byte_length] = 0;
801             }
802 
803             return TRUE;
804 
805         // we don't actually verify the checksum here (it's done right after the
806         // block is read), but it's a good indicator of version 5 files
807 
808         case ID_BLOCK_CHECKSUM:
809             wpc->version_five = 1;
810             return TRUE;
811 
812         default:
813             return (wpmd->id & ID_OPTIONAL_DATA) ? TRUE : FALSE;
814     }
815 }
816 
817 //////////////////////////////// bitstream management ///////////////////////////////
818 
819 // Open the specified BitStream and associate with the specified buffer.
820 
821 static void bs_read (Bitstream *bs);
822 
bs_open_read(Bitstream * bs,void * buffer_start,void * buffer_end)823 static void bs_open_read (Bitstream *bs, void *buffer_start, void *buffer_end)
824 {
825     bs->error = bs->sr = bs->bc = 0;
826     bs->ptr = (bs->buf = buffer_start) - 1;
827     bs->end = buffer_end;
828     bs->wrap = bs_read;
829 }
830 
831 // This function is only called from the getbit() and getbits() macros when
832 // the BitStream has been exhausted and more data is required. Sinve these
833 // bistreams no longer access files, this function simple sets an error and
834 // resets the buffer.
835 
bs_read(Bitstream * bs)836 static void bs_read (Bitstream *bs)
837 {
838     bs->ptr = bs->buf;
839     bs->error = 1;
840 }
841 
842 // This function is called to close the bitstream. It returns the number of
843 // full bytes actually read as bits.
844 
bs_close_read(Bitstream * bs)845 uint32_t bs_close_read (Bitstream *bs)
846 {
847     uint32_t bytes_read;
848 
849     if (bs->bc < sizeof (*(bs->ptr)) * 8)
850         bs->ptr++;
851 
852     bytes_read = (uint32_t)(bs->ptr - bs->buf) * sizeof (*(bs->ptr));
853 
854     if (!(bytes_read & 1))
855         ++bytes_read;
856 
857     CLEAR (*bs);
858     return bytes_read;
859 }
860 
861 // Normally the trailing wrapper will not be available when a WavPack file is first
862 // opened for reading because it is stored in the final block of the file. This
863 // function forces a seek to the end of the file to pick up any trailing wrapper
864 // stored there (then use WavPackGetWrapper**() to obtain). This can obviously only
865 // be used for seekable files (not pipes) and is not available for pre-4.0 WavPack
866 // files.
867 
WavpackSeekTrailingWrapper(WavpackContext * wpc)868 void WavpackSeekTrailingWrapper (WavpackContext *wpc)
869 {
870     if ((wpc->open_flags & OPEN_WRAPPER) &&
871         wpc->reader->can_seek (wpc->wv_in) && !wpc->stream3)
872             seek_eof_information (wpc, NULL, TRUE);
873 }
874 
875 // Get any MD5 checksum stored in the metadata (should be called after reading
876 // last sample or an extra seek will occur). A return value of FALSE indicates
877 // that no MD5 checksum was stored.
878 
WavpackGetMD5Sum(WavpackContext * wpc,unsigned char data[16])879 int WavpackGetMD5Sum (WavpackContext *wpc, unsigned char data [16])
880 {
881     if (wpc->config.flags & CONFIG_MD5_CHECKSUM) {
882         if (!wpc->config.md5_read && wpc->reader->can_seek (wpc->wv_in))
883             seek_eof_information (wpc, NULL, FALSE);
884 
885         if (wpc->config.md5_read) {
886             memcpy (data, wpc->config.md5_checksum, 16);
887             return TRUE;
888         }
889     }
890 
891     return FALSE;
892 }
893 
894 // Read from current file position until a valid 32-byte WavPack 4.0 header is
895 // found and read into the specified pointer. The number of bytes skipped is
896 // returned. If no WavPack header is found within 1 meg, then a -1 is returned
897 // to indicate the error. No additional bytes are read past the header and it
898 // is returned in the processor's native endian mode. Seeking is not required.
899 
read_next_header(WavpackStreamReader64 * reader,void * id,WavpackHeader * wphdr)900 uint32_t read_next_header (WavpackStreamReader64 *reader, void *id, WavpackHeader *wphdr)
901 {
902     unsigned char buffer [sizeof (*wphdr)], *sp = buffer + sizeof (*wphdr), *ep = sp;
903     uint32_t bytes_skipped = 0;
904     int bleft;
905 
906     while (1) {
907         if (sp < ep) {
908             bleft = (int)(ep - sp);
909             memmove (buffer, sp, bleft);
910         }
911         else
912             bleft = 0;
913 
914         if (reader->read_bytes (id, buffer + bleft, sizeof (*wphdr) - bleft) != sizeof (*wphdr) - bleft)
915             return -1;
916 
917         sp = buffer;
918 
919         if (*sp++ == 'w' && *sp == 'v' && *++sp == 'p' && *++sp == 'k' &&
920             !(*++sp & 1) && sp [2] < 16 && !sp [3] && (sp [2] || sp [1] || *sp >= 24) && sp [5] == 4 &&
921             sp [4] >= (MIN_STREAM_VERS & 0xff) && sp [4] <= (MAX_STREAM_VERS & 0xff) && sp [18] < 3 && !sp [19]) {
922                 memcpy (wphdr, buffer, sizeof (*wphdr));
923                 WavpackLittleEndianToNative (wphdr, WavpackHeaderFormat);
924                 return bytes_skipped;
925             }
926 
927         while (sp < ep && *sp != 'w')
928             sp++;
929 
930         if ((bytes_skipped += (uint32_t)(sp - buffer)) > 1024 * 1024)
931             return -1;
932     }
933 }
934 
935 // Compare the regular wv file block header to a potential matching wvc
936 // file block header and return action code based on analysis:
937 //
938 //   0 = use wvc block (assuming rest of block is readable)
939 //   1 = bad match; try to read next wvc block
940 //  -1 = bad match; ignore wvc file for this block and backup fp (if
941 //       possible) and try to use this block next time
942 
match_wvc_header(WavpackHeader * wv_hdr,WavpackHeader * wvc_hdr)943 static int match_wvc_header (WavpackHeader *wv_hdr, WavpackHeader *wvc_hdr)
944 {
945     if (GET_BLOCK_INDEX (*wv_hdr) == GET_BLOCK_INDEX (*wvc_hdr) &&
946         wv_hdr->block_samples == wvc_hdr->block_samples) {
947             int wvi = 0, wvci = 0;
948 
949             if (wv_hdr->flags == wvc_hdr->flags)
950                 return 0;
951 
952             if (wv_hdr->flags & INITIAL_BLOCK)
953                 wvi -= 1;
954 
955             if (wv_hdr->flags & FINAL_BLOCK)
956                 wvi += 1;
957 
958             if (wvc_hdr->flags & INITIAL_BLOCK)
959                 wvci -= 1;
960 
961             if (wvc_hdr->flags & FINAL_BLOCK)
962                 wvci += 1;
963 
964             return (wvci - wvi < 0) ? 1 : -1;
965         }
966 
967     if ((GET_BLOCK_INDEX (*wvc_hdr) - GET_BLOCK_INDEX (*wv_hdr)) & 0x8000000000LL)
968         return 1;
969     else
970         return -1;
971 }
972 
973 // Read the wvc block that matches the regular wv block that has been
974 // read for the current stream. If an exact match is not found then
975 // we either keep reading or back up and (possibly) use the block
976 // later. The skip_wvc flag is set if not matching wvc block is found
977 // so that we can still decode using only the lossy version (although
978 // we flag this as an error). A return of FALSE indicates a serious
979 // error (not just that we missed one wvc block).
980 
read_wvc_block(WavpackContext * wpc)981 int read_wvc_block (WavpackContext *wpc)
982 {
983     WavpackStream *wps = wpc->streams [wpc->current_stream];
984     int64_t bcount, file2pos;
985     WavpackHeader orig_wphdr;
986     WavpackHeader wphdr;
987     int compare_result;
988 
989     while (1) {
990         file2pos = wpc->reader->get_pos (wpc->wvc_in);
991         bcount = read_next_header (wpc->reader, wpc->wvc_in, &wphdr);
992 
993         if (bcount == (uint32_t) -1) {
994             wps->wvc_skip = TRUE;
995             wpc->crc_errors++;
996             return FALSE;
997         }
998 
999         memcpy (&orig_wphdr, &wphdr, 32);       // save original header for verify step
1000 
1001         if (wpc->open_flags & OPEN_STREAMING)
1002             SET_BLOCK_INDEX (wphdr, wps->sample_index = 0);
1003         else
1004             SET_BLOCK_INDEX (wphdr, GET_BLOCK_INDEX (wphdr) - wpc->initial_index);
1005 
1006         if (wphdr.flags & INITIAL_BLOCK)
1007             wpc->file2pos = file2pos + bcount;
1008 
1009         compare_result = match_wvc_header (&wps->wphdr, &wphdr);
1010 
1011         if (!compare_result) {
1012             wps->block2buff = (unsigned char *)malloc (wphdr.ckSize + 8);
1013 	    if (!wps->block2buff)
1014 	        return FALSE;
1015 
1016             if (wpc->reader->read_bytes (wpc->wvc_in, wps->block2buff + 32, wphdr.ckSize - 24) !=
1017                 wphdr.ckSize - 24) {
1018                     free (wps->block2buff);
1019                     wps->block2buff = NULL;
1020                     wps->wvc_skip = TRUE;
1021                     wpc->crc_errors++;
1022                     return FALSE;
1023             }
1024 
1025             memcpy (wps->block2buff, &orig_wphdr, 32);
1026 
1027             // don't use corrupt blocks
1028             if (!WavpackVerifySingleBlock (wps->block2buff, !(wpc->open_flags & OPEN_NO_CHECKSUM))) {
1029                 free (wps->block2buff);
1030                 wps->block2buff = NULL;
1031                 wps->wvc_skip = TRUE;
1032                 wpc->crc_errors++;
1033                 return TRUE;
1034             }
1035 
1036             wps->wvc_skip = FALSE;
1037             memcpy (wps->block2buff, &wphdr, 32);
1038             memcpy (&wps->wphdr, &wphdr, 32);
1039             return TRUE;
1040         }
1041         else if (compare_result == -1) {
1042             wps->wvc_skip = TRUE;
1043             wpc->reader->set_pos_rel (wpc->wvc_in, -32, SEEK_CUR);
1044             wpc->crc_errors++;
1045             return TRUE;
1046         }
1047     }
1048 }
1049 
1050 // This function is used to seek to end of a file to obtain certain information
1051 // that is stored there at the file creation time because it is not known at
1052 // the start. This includes the MD5 sum and and trailing part of the file
1053 // wrapper, and in some rare cases may include the total number of samples in
1054 // the file (although we usually try to back up and write that at the front of
1055 // the file). Note this function restores the file position to its original
1056 // location (and obviously requires a seekable file). The normal return value
1057 // is TRUE indicating no errors, although this does not actually mean that any
1058 // information was retrieved. An error return of FALSE usually means the file
1059 // terminated unexpectedly. Note that this could be used to get all three
1060 // types of information in one go, but it's not actually used that way now.
1061 
seek_eof_information(WavpackContext * wpc,int64_t * final_index,int get_wrapper)1062 static int seek_eof_information (WavpackContext *wpc, int64_t *final_index, int get_wrapper)
1063 {
1064     int64_t restore_pos, last_pos = -1;
1065     WavpackStreamReader64 *reader = wpc->reader;
1066     int alt_types = wpc->open_flags & OPEN_ALT_TYPES;
1067     uint32_t blocks = 0, audio_blocks = 0;
1068     void *id = wpc->wv_in;
1069     WavpackHeader wphdr;
1070 
1071     restore_pos = reader->get_pos (id);    // we restore file position when done
1072 
1073     // start 1MB from the end-of-file, or from the start if the file is not that big
1074 
1075     if (reader->get_length (id) > (int64_t) 1048576)
1076         reader->set_pos_rel (id, -1048576, SEEK_END);
1077     else
1078         reader->set_pos_abs (id, 0);
1079 
1080     // Note that we go backward (without parsing inside blocks) until we find a block
1081     // with audio (careful to not get stuck in a loop). Only then do we go forward
1082     // parsing all blocks in their entirety.
1083 
1084     while (1) {
1085         uint32_t bcount = read_next_header (reader, id, &wphdr);
1086         int64_t current_pos = reader->get_pos (id);
1087 
1088         // if we just got to the same place as last time, we're stuck and need to give up
1089 
1090         if (current_pos == last_pos) {
1091             reader->set_pos_abs (id, restore_pos);
1092             return FALSE;
1093         }
1094 
1095         last_pos = current_pos;
1096 
1097         // We enter here if we just read 1 MB without seeing any WavPack block headers.
1098         // Since WavPack blocks are < 1 MB, that means we're in a big APE tag, or we got
1099         // to the end-of-file.
1100 
1101         if (bcount == (uint32_t) -1) {
1102 
1103             // if we have not seen any blocks at all yet, back up almost 2 MB (or to the
1104             // beginning of the file) and try again
1105 
1106             if (!blocks) {
1107                 if (current_pos > (int64_t) 2000000)
1108                     reader->set_pos_rel (id, -2000000, SEEK_CUR);
1109                 else
1110                     reader->set_pos_abs (id, 0);
1111 
1112                 continue;
1113             }
1114 
1115             // if we have seen WavPack blocks, then this means we've done all we can do here
1116 
1117             reader->set_pos_abs (id, restore_pos);
1118             return TRUE;
1119         }
1120 
1121         blocks++;
1122 
1123         // If the block has audio samples, calculate a final index, although this is not
1124         // final since this may not be the last block with audio. On the other hand, if
1125         // this block does not have audio, and we haven't seen one with audio, we have
1126         // to go back some more.
1127 
1128         if (wphdr.block_samples) {
1129             if (final_index)
1130                 *final_index = GET_BLOCK_INDEX (wphdr) + wphdr.block_samples;
1131 
1132             audio_blocks++;
1133         }
1134         else if (!audio_blocks) {
1135             if (current_pos > (int64_t) 1048576)
1136                 reader->set_pos_rel (id, -1048576, SEEK_CUR);
1137             else
1138                 reader->set_pos_abs (id, 0);
1139 
1140             continue;
1141         }
1142 
1143         // at this point we have seen at least one block with audio, so we parse the
1144         // entire block looking for MD5 metadata or (conditionally) trailing wrappers
1145 
1146         bcount = wphdr.ckSize - sizeof (WavpackHeader) + 8;
1147 
1148         while (bcount >= 2) {
1149             unsigned char meta_id, c1, c2;
1150             uint32_t meta_bc, meta_size;
1151 
1152             if (reader->read_bytes (id, &meta_id, 1) != 1 ||
1153                 reader->read_bytes (id, &c1, 1) != 1) {
1154                     reader->set_pos_abs (id, restore_pos);
1155                     return FALSE;
1156             }
1157 
1158             meta_bc = c1 << 1;
1159             bcount -= 2;
1160 
1161             if (meta_id & ID_LARGE) {
1162                 if (bcount < 2 || reader->read_bytes (id, &c1, 1) != 1 ||
1163                     reader->read_bytes (id, &c2, 1) != 1) {
1164                         reader->set_pos_abs (id, restore_pos);
1165                         return FALSE;
1166                 }
1167 
1168                 meta_bc += ((uint32_t) c1 << 9) + ((uint32_t) c2 << 17);
1169                 bcount -= 2;
1170             }
1171 
1172             meta_size = (meta_id & ID_ODD_SIZE) ? meta_bc - 1 : meta_bc;
1173             meta_id &= ID_UNIQUE;
1174 
1175             if (get_wrapper && (meta_id == ID_RIFF_TRAILER || (alt_types && meta_id == ID_ALT_TRAILER)) && meta_bc) {
1176                 wpc->wrapper_data = (unsigned char *)realloc (wpc->wrapper_data, wpc->wrapper_bytes + meta_bc);
1177 
1178                 if (!wpc->wrapper_data) {
1179                     reader->set_pos_abs (id, restore_pos);
1180                     return FALSE;
1181                 }
1182 
1183                 if (reader->read_bytes (id, wpc->wrapper_data + wpc->wrapper_bytes, meta_bc) == meta_bc)
1184                     wpc->wrapper_bytes += meta_size;
1185                 else {
1186                     reader->set_pos_abs (id, restore_pos);
1187                     return FALSE;
1188                 }
1189             }
1190             else if (meta_id == ID_MD5_CHECKSUM || (alt_types && meta_id == ID_ALT_MD5_CHECKSUM)) {
1191                 if (meta_bc == 16 && bcount >= 16) {
1192                     if (reader->read_bytes (id, wpc->config.md5_checksum, 16) == 16)
1193                         wpc->config.md5_read = TRUE;
1194                     else {
1195                         reader->set_pos_abs (id, restore_pos);
1196                         return FALSE;
1197                     }
1198                 }
1199                 else
1200                     reader->set_pos_rel (id, meta_bc, SEEK_CUR);
1201             }
1202             else
1203                 reader->set_pos_rel (id, meta_bc, SEEK_CUR);
1204 
1205             bcount -= meta_bc;
1206         }
1207     }
1208 }
1209 
1210 // Quickly verify the referenced block. It is assumed that the WavPack header has been converted
1211 // to native endian format. If a block checksum is performed, that is done in little-endian
1212 // (file) format. It is also assumed that the caller has made sure that the block length
1213 // indicated in the header is correct (we won't overflow the buffer). If a checksum is present,
1214 // then it is checked, otherwise we just check that all the metadata blocks are formatted
1215 // correctly (without looking at their contents). Returns FALSE for bad block.
1216 
WavpackVerifySingleBlock(unsigned char * buffer,int verify_checksum)1217 int WavpackVerifySingleBlock (unsigned char *buffer, int verify_checksum)
1218 {
1219     WavpackHeader *wphdr = (WavpackHeader *) buffer;
1220     uint32_t checksum_passed = 0, bcount, meta_bc;
1221     unsigned char *dp, meta_id, c1, c2;
1222 
1223     if (strncmp (wphdr->ckID, "wvpk", 4) || wphdr->ckSize + 8 < sizeof (WavpackHeader))
1224         return FALSE;
1225 
1226     bcount = wphdr->ckSize - sizeof (WavpackHeader) + 8;
1227     dp = (unsigned char *)(wphdr + 1);
1228 
1229     while (bcount >= 2) {
1230         meta_id = *dp++;
1231         c1 = *dp++;
1232 
1233         meta_bc = c1 << 1;
1234         bcount -= 2;
1235 
1236         if (meta_id & ID_LARGE) {
1237             if (bcount < 2)
1238                 return FALSE;
1239 
1240             c1 = *dp++;
1241             c2 = *dp++;
1242             meta_bc += ((uint32_t) c1 << 9) + ((uint32_t) c2 << 17);
1243             bcount -= 2;
1244         }
1245 
1246         if (bcount < meta_bc)
1247             return FALSE;
1248 
1249         if (verify_checksum && (meta_id & ID_UNIQUE) == ID_BLOCK_CHECKSUM) {
1250 #ifdef BITSTREAM_SHORTS
1251             uint16_t *csptr = (uint16_t*) buffer;
1252 #else
1253             unsigned char *csptr = buffer;
1254 #endif
1255             int wcount = (int)(dp - 2 - buffer) >> 1;
1256             uint32_t csum = (uint32_t) -1;
1257 
1258             if ((meta_id & ID_ODD_SIZE) || meta_bc < 2 || meta_bc > 4)
1259                 return FALSE;
1260 
1261 #ifdef BITSTREAM_SHORTS
1262             while (wcount--)
1263                 csum = (csum * 3) + *csptr++;
1264 #else
1265             WavpackNativeToLittleEndian ((WavpackHeader *) buffer, WavpackHeaderFormat);
1266 
1267             while (wcount--) {
1268                 csum = (csum * 3) + csptr [0] + (csptr [1] << 8);
1269                 csptr += 2;
1270             }
1271 
1272             WavpackLittleEndianToNative ((WavpackHeader *) buffer, WavpackHeaderFormat);
1273 #endif
1274 
1275             if (meta_bc == 4) {
1276                 if (*dp != (csum & 0xff) || dp[1] != ((csum >> 8) & 0xff) || dp[2] != ((csum >> 16) & 0xff) || dp[3] != ((csum >> 24) & 0xff))
1277                     return FALSE;
1278             }
1279             else {
1280                 csum ^= csum >> 16;
1281 
1282                 if (*dp != (csum & 0xff) || dp[1] != ((csum >> 8) & 0xff))
1283                     return FALSE;
1284             }
1285 
1286             checksum_passed++;
1287         }
1288 
1289         bcount -= meta_bc;
1290         dp += meta_bc;
1291     }
1292 
1293     return (bcount == 0) && (!verify_checksum || !(wphdr->flags & HAS_CHECKSUM) || checksum_passed);
1294 }
1295