src/libFLAC/stream_decoder.c : Fix buffer read overflow.
[platform/upstream/flac.git] / src / test_libFLAC++ / encoders.cpp
1 /* test_libFLAC++ - Unit tester for libFLAC++
2  * Copyright (C) 2002-2009  Josh Coalson
3  * Copyright (C) 2011-2013  Xiph.Org Foundation
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (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 General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19
20 #include "encoders.h"
21 #include "FLAC/assert.h"
22 #include "FLAC++/encoder.h"
23 #include "share/grabbag.h"
24 extern "C" {
25 #include "test_libs_common/file_utils_flac.h"
26 #include "test_libs_common/metadata_utils.h"
27 }
28 #include <errno.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include "share/compat.h"
33
34 typedef enum {
35         LAYER_STREAM = 0, /* FLAC__stream_encoder_init_stream() without seeking */
36         LAYER_SEEKABLE_STREAM, /* FLAC__stream_encoder_init_stream() with seeking */
37         LAYER_FILE, /* FLAC__stream_encoder_init_FILE() */
38         LAYER_FILENAME /* FLAC__stream_encoder_init_file() */
39 } Layer;
40
41 static const char * const LayerString[] = {
42         "Stream",
43         "Seekable Stream",
44         "FILE*",
45         "Filename"
46 };
47
48 static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
49 static ::FLAC__StreamMetadata *metadata_sequence_[] = { &vorbiscomment_, &padding_, &seektable_, &application1_, &application2_, &cuesheet_, &picture_, &unknown_ };
50 static const unsigned num_metadata_ = sizeof(metadata_sequence_) / sizeof(metadata_sequence_[0]);
51
52 static const char *flacfilename(bool is_ogg)
53 {
54         return is_ogg? "metadata.oga" : "metadata.flac";
55 }
56
57 static bool die_(const char *msg)
58 {
59         printf("ERROR: %s\n", msg);
60         return false;
61 }
62
63 static bool die_s_(const char *msg, const FLAC::Encoder::Stream *encoder)
64 {
65         FLAC::Encoder::Stream::State state = encoder->get_state();
66
67         if(msg)
68                 printf("FAILED, %s", msg);
69         else
70                 printf("FAILED");
71
72         printf(", state = %u (%s)\n", (unsigned)((::FLAC__StreamEncoderState)state), state.as_cstring());
73         if(state == ::FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
74                 FLAC::Decoder::Stream::State dstate = encoder->get_verify_decoder_state();
75                 printf("      verify decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
76         }
77
78         return false;
79 }
80
81 static void init_metadata_blocks_()
82 {
83         mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
84 }
85
86 static void free_metadata_blocks_()
87 {
88         mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
89 }
90
91 class StreamEncoder : public FLAC::Encoder::Stream {
92 public:
93         Layer layer_;
94         FILE *file_;
95
96         StreamEncoder(Layer layer): FLAC::Encoder::Stream(), layer_(layer), file_(0) { }
97         ~StreamEncoder() { }
98
99         // from FLAC::Encoder::Stream
100         ::FLAC__StreamEncoderReadStatus read_callback(FLAC__byte buffer[], size_t *bytes);
101         ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame);
102         ::FLAC__StreamEncoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
103         ::FLAC__StreamEncoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
104         void metadata_callback(const ::FLAC__StreamMetadata *metadata);
105 };
106
107 ::FLAC__StreamEncoderReadStatus StreamEncoder::read_callback(FLAC__byte buffer[], size_t *bytes)
108 {
109         if(*bytes > 0) {
110                 *bytes = fread(buffer, sizeof(FLAC__byte), *bytes, file_);
111                 if(ferror(file_))
112                         return ::FLAC__STREAM_ENCODER_READ_STATUS_ABORT;
113                 else if(*bytes == 0)
114                         return ::FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM;
115                 else
116                         return ::FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE;
117         }
118         else
119                 return ::FLAC__STREAM_ENCODER_READ_STATUS_ABORT;
120 }
121
122 ::FLAC__StreamEncoderWriteStatus StreamEncoder::write_callback(const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame)
123 {
124         (void)samples, (void)current_frame;
125
126         if(fwrite(buffer, 1, bytes, file_) != bytes)
127                 return ::FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
128         else
129                 return ::FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
130 }
131
132 ::FLAC__StreamEncoderSeekStatus StreamEncoder::seek_callback(FLAC__uint64 absolute_byte_offset)
133 {
134         if(layer_==LAYER_STREAM)
135                 return ::FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED;
136         else if(fseeko(file_, (FLAC__off_t)absolute_byte_offset, SEEK_SET) < 0)
137                 return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR;
138         else
139                 return FLAC__STREAM_ENCODER_SEEK_STATUS_OK;
140 }
141
142 ::FLAC__StreamEncoderTellStatus StreamEncoder::tell_callback(FLAC__uint64 *absolute_byte_offset)
143 {
144         FLAC__off_t pos;
145         if(layer_==LAYER_STREAM)
146                 return ::FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED;
147         else if((pos = ftello(file_)) < 0)
148                 return FLAC__STREAM_ENCODER_TELL_STATUS_ERROR;
149         else {
150                 *absolute_byte_offset = (FLAC__uint64)pos;
151                 return FLAC__STREAM_ENCODER_TELL_STATUS_OK;
152         }
153 }
154
155 void StreamEncoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
156 {
157         (void)metadata;
158 }
159
160 class FileEncoder : public FLAC::Encoder::File {
161 public:
162         Layer layer_;
163
164         FileEncoder(Layer layer): FLAC::Encoder::File(), layer_(layer) { }
165         ~FileEncoder() { }
166
167         // from FLAC::Encoder::File
168         void progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate);
169 };
170
171 void FileEncoder::progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate)
172 {
173         (void)bytes_written, (void)samples_written, (void)frames_written, (void)total_frames_estimate;
174 }
175
176 static FLAC::Encoder::Stream *new_by_layer(Layer layer)
177 {
178         if(layer < LAYER_FILE)
179                 return new StreamEncoder(layer);
180         else
181                 return new FileEncoder(layer);
182 }
183
184 static bool test_stream_encoder(Layer layer, bool is_ogg)
185 {
186         FLAC::Encoder::Stream *encoder;
187         ::FLAC__StreamEncoderInitStatus init_status;
188         FILE *file = 0;
189         FLAC__int32 samples[1024];
190         FLAC__int32 *samples_array[1] = { samples };
191         unsigned i;
192
193         printf("\n+++ libFLAC++ unit test: FLAC::Encoder::%s (layer: %s, format: %s)\n\n", layer<LAYER_FILE? "Stream":"File", LayerString[layer], is_ogg? "Ogg FLAC":"FLAC");
194
195         printf("allocating encoder instance... ");
196         encoder = new_by_layer(layer);
197         if(0 == encoder) {
198                 printf("FAILED, new returned NULL\n");
199                 return false;
200         }
201         printf("OK\n");
202
203         printf("testing is_valid()... ");
204         if(!encoder->is_valid()) {
205                 printf("FAILED, returned false\n");
206                 return false;
207         }
208         printf("OK\n");
209
210         if(is_ogg) {
211                 printf("testing set_ogg_serial_number()... ");
212                 if(!encoder->set_ogg_serial_number(file_utils__ogg_serial_number))
213                         return die_s_("returned false", encoder);
214                 printf("OK\n");
215         }
216
217         printf("testing set_verify()... ");
218         if(!encoder->set_verify(true))
219                 return die_s_("returned false", encoder);
220         printf("OK\n");
221
222         printf("testing set_streamable_subset()... ");
223         if(!encoder->set_streamable_subset(true))
224                 return die_s_("returned false", encoder);
225         printf("OK\n");
226
227         printf("testing set_channels()... ");
228         if(!encoder->set_channels(streaminfo_.data.stream_info.channels))
229                 return die_s_("returned false", encoder);
230         printf("OK\n");
231
232         printf("testing set_bits_per_sample()... ");
233         if(!encoder->set_bits_per_sample(streaminfo_.data.stream_info.bits_per_sample))
234                 return die_s_("returned false", encoder);
235         printf("OK\n");
236
237         printf("testing set_sample_rate()... ");
238         if(!encoder->set_sample_rate(streaminfo_.data.stream_info.sample_rate))
239                 return die_s_("returned false", encoder);
240         printf("OK\n");
241
242         printf("testing set_compression_level()... ");
243         if(!encoder->set_compression_level((unsigned)(-1)))
244                 return die_s_("returned false", encoder);
245         printf("OK\n");
246
247         printf("testing set_blocksize()... ");
248         if(!encoder->set_blocksize(streaminfo_.data.stream_info.min_blocksize))
249                 return die_s_("returned false", encoder);
250         printf("OK\n");
251
252         printf("testing set_do_mid_side_stereo()... ");
253         if(!encoder->set_do_mid_side_stereo(false))
254                 return die_s_("returned false", encoder);
255         printf("OK\n");
256
257         printf("testing set_loose_mid_side_stereo()... ");
258         if(!encoder->set_loose_mid_side_stereo(false))
259                 return die_s_("returned false", encoder);
260         printf("OK\n");
261
262         printf("testing set_max_lpc_order()... ");
263         if(!encoder->set_max_lpc_order(0))
264                 return die_s_("returned false", encoder);
265         printf("OK\n");
266
267         printf("testing set_qlp_coeff_precision()... ");
268         if(!encoder->set_qlp_coeff_precision(0))
269                 return die_s_("returned false", encoder);
270         printf("OK\n");
271
272         printf("testing set_do_qlp_coeff_prec_search()... ");
273         if(!encoder->set_do_qlp_coeff_prec_search(false))
274                 return die_s_("returned false", encoder);
275         printf("OK\n");
276
277         printf("testing set_do_escape_coding()... ");
278         if(!encoder->set_do_escape_coding(false))
279                 return die_s_("returned false", encoder);
280         printf("OK\n");
281
282         printf("testing set_do_exhaustive_model_search()... ");
283         if(!encoder->set_do_exhaustive_model_search(false))
284                 return die_s_("returned false", encoder);
285         printf("OK\n");
286
287         printf("testing set_min_residual_partition_order()... ");
288         if(!encoder->set_min_residual_partition_order(0))
289                 return die_s_("returned false", encoder);
290         printf("OK\n");
291
292         printf("testing set_max_residual_partition_order()... ");
293         if(!encoder->set_max_residual_partition_order(0))
294                 return die_s_("returned false", encoder);
295         printf("OK\n");
296
297         printf("testing set_rice_parameter_search_dist()... ");
298         if(!encoder->set_rice_parameter_search_dist(0))
299                 return die_s_("returned false", encoder);
300         printf("OK\n");
301
302         printf("testing set_total_samples_estimate()... ");
303         if(!encoder->set_total_samples_estimate(streaminfo_.data.stream_info.total_samples))
304                 return die_s_("returned false", encoder);
305         printf("OK\n");
306
307         printf("testing set_metadata()... ");
308         if(!encoder->set_metadata(metadata_sequence_, num_metadata_))
309                 return die_s_("returned false", encoder);
310         printf("OK\n");
311
312         if(layer < LAYER_FILENAME) {
313                 printf("opening file for FLAC output... ");
314                 file = ::flac_fopen(flacfilename(is_ogg), "w+b");
315                 if(0 == file) {
316                         printf("ERROR (%s)\n", strerror(errno));
317                         return false;
318                 }
319                 printf("OK\n");
320                 if(layer < LAYER_FILE)
321                         dynamic_cast<StreamEncoder*>(encoder)->file_ = file;
322         }
323
324         switch(layer) {
325                 case LAYER_STREAM:
326                 case LAYER_SEEKABLE_STREAM:
327                         printf("testing init%s()... ", is_ogg? "_ogg":"");
328                         init_status = is_ogg? encoder->init_ogg() : encoder->init();
329                         break;
330                 case LAYER_FILE:
331                         printf("testing init%s()... ", is_ogg? "_ogg":"");
332                         init_status = is_ogg?
333                                 dynamic_cast<FLAC::Encoder::File*>(encoder)->init_ogg(file) :
334                                 dynamic_cast<FLAC::Encoder::File*>(encoder)->init(file);
335                         break;
336                 case LAYER_FILENAME:
337                         printf("testing init%s()... ", is_ogg? "_ogg":"");
338                         init_status = is_ogg?
339                                 dynamic_cast<FLAC::Encoder::File*>(encoder)->init_ogg(flacfilename(is_ogg)) :
340                                 dynamic_cast<FLAC::Encoder::File*>(encoder)->init(flacfilename(is_ogg));
341                         break;
342                 default:
343                         die_("internal error 001");
344                         return false;
345         }
346         if(init_status != ::FLAC__STREAM_ENCODER_INIT_STATUS_OK)
347                 return die_s_(0, encoder);
348         printf("OK\n");
349
350         printf("testing get_state()... ");
351         FLAC::Encoder::Stream::State state = encoder->get_state();
352         printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamEncoderState)state), state.as_cstring());
353
354         printf("testing get_verify_decoder_state()... ");
355         FLAC::Decoder::Stream::State dstate = encoder->get_verify_decoder_state();
356         printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
357
358         {
359                 FLAC__uint64 absolute_sample;
360                 unsigned frame_number;
361                 unsigned channel;
362                 unsigned sample;
363                 FLAC__int32 expected;
364                 FLAC__int32 got;
365
366                 printf("testing get_verify_decoder_error_stats()... ");
367                 encoder->get_verify_decoder_error_stats(&absolute_sample, &frame_number, &channel, &sample, &expected, &got);
368                 printf("OK\n");
369         }
370
371         printf("testing get_verify()... ");
372         if(encoder->get_verify() != true) {
373                 printf("FAILED, expected true, got false\n");
374                 return false;
375         }
376         printf("OK\n");
377
378         printf("testing get_streamable_subset()... ");
379         if(encoder->get_streamable_subset() != true) {
380                 printf("FAILED, expected true, got false\n");
381                 return false;
382         }
383         printf("OK\n");
384
385         printf("testing get_do_mid_side_stereo()... ");
386         if(encoder->get_do_mid_side_stereo() != false) {
387                 printf("FAILED, expected false, got true\n");
388                 return false;
389         }
390         printf("OK\n");
391
392         printf("testing get_loose_mid_side_stereo()... ");
393         if(encoder->get_loose_mid_side_stereo() != false) {
394                 printf("FAILED, expected false, got true\n");
395                 return false;
396         }
397         printf("OK\n");
398
399         printf("testing get_channels()... ");
400         if(encoder->get_channels() != streaminfo_.data.stream_info.channels) {
401                 printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.channels, encoder->get_channels());
402                 return false;
403         }
404         printf("OK\n");
405
406         printf("testing get_bits_per_sample()... ");
407         if(encoder->get_bits_per_sample() != streaminfo_.data.stream_info.bits_per_sample) {
408                 printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.bits_per_sample, encoder->get_bits_per_sample());
409                 return false;
410         }
411         printf("OK\n");
412
413         printf("testing get_sample_rate()... ");
414         if(encoder->get_sample_rate() != streaminfo_.data.stream_info.sample_rate) {
415                 printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.sample_rate, encoder->get_sample_rate());
416                 return false;
417         }
418         printf("OK\n");
419
420         printf("testing get_blocksize()... ");
421         if(encoder->get_blocksize() != streaminfo_.data.stream_info.min_blocksize) {
422                 printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.min_blocksize, encoder->get_blocksize());
423                 return false;
424         }
425         printf("OK\n");
426
427         printf("testing get_max_lpc_order()... ");
428         if(encoder->get_max_lpc_order() != 0) {
429                 printf("FAILED, expected %u, got %u\n", 0, encoder->get_max_lpc_order());
430                 return false;
431         }
432         printf("OK\n");
433
434         printf("testing get_qlp_coeff_precision()... ");
435         (void)encoder->get_qlp_coeff_precision();
436         /* we asked the encoder to auto select this so we accept anything */
437         printf("OK\n");
438
439         printf("testing get_do_qlp_coeff_prec_search()... ");
440         if(encoder->get_do_qlp_coeff_prec_search() != false) {
441                 printf("FAILED, expected false, got true\n");
442                 return false;
443         }
444         printf("OK\n");
445
446         printf("testing get_do_escape_coding()... ");
447         if(encoder->get_do_escape_coding() != false) {
448                 printf("FAILED, expected false, got true\n");
449                 return false;
450         }
451         printf("OK\n");
452
453         printf("testing get_do_exhaustive_model_search()... ");
454         if(encoder->get_do_exhaustive_model_search() != false) {
455                 printf("FAILED, expected false, got true\n");
456                 return false;
457         }
458         printf("OK\n");
459
460         printf("testing get_min_residual_partition_order()... ");
461         if(encoder->get_min_residual_partition_order() != 0) {
462                 printf("FAILED, expected %u, got %u\n", 0, encoder->get_min_residual_partition_order());
463                 return false;
464         }
465         printf("OK\n");
466
467         printf("testing get_max_residual_partition_order()... ");
468         if(encoder->get_max_residual_partition_order() != 0) {
469                 printf("FAILED, expected %u, got %u\n", 0, encoder->get_max_residual_partition_order());
470                 return false;
471         }
472         printf("OK\n");
473
474         printf("testing get_rice_parameter_search_dist()... ");
475         if(encoder->get_rice_parameter_search_dist() != 0) {
476                 printf("FAILED, expected %u, got %u\n", 0, encoder->get_rice_parameter_search_dist());
477                 return false;
478         }
479         printf("OK\n");
480
481         printf("testing get_total_samples_estimate()... ");
482         if(encoder->get_total_samples_estimate() != streaminfo_.data.stream_info.total_samples) {
483                 printf("FAILED, expected %" PRIu64 ", got %" PRIu64 "\n", streaminfo_.data.stream_info.total_samples, encoder->get_total_samples_estimate());
484                 return false;
485         }
486         printf("OK\n");
487
488         /* init the dummy sample buffer */
489         for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
490                 samples[i] = i & 7;
491
492         printf("testing process()... ");
493         if(!encoder->process(samples_array, sizeof(samples) / sizeof(FLAC__int32)))
494                 return die_s_("returned false", encoder);
495         printf("OK\n");
496
497         printf("testing process_interleaved()... ");
498         if(!encoder->process_interleaved(samples, sizeof(samples) / sizeof(FLAC__int32)))
499                 return die_s_("returned false", encoder);
500         printf("OK\n");
501
502         printf("testing finish()... ");
503         if(!encoder->finish()) {
504                 state = encoder->get_state();
505                 printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::FLAC__StreamEncoderState)state), state.as_cstring());
506                 return false;
507         }
508         printf("OK\n");
509
510         if(layer < LAYER_FILE)
511                 ::fclose(dynamic_cast<StreamEncoder*>(encoder)->file_);
512
513         printf("freeing encoder instance... ");
514         delete encoder;
515         printf("OK\n");
516
517         printf("\nPASSED!\n");
518
519         return true;
520 }
521
522 bool test_encoders()
523 {
524         FLAC__bool is_ogg = false;
525
526         while(1) {
527                 init_metadata_blocks_();
528
529                 if(!test_stream_encoder(LAYER_STREAM, is_ogg))
530                         return false;
531
532                 if(!test_stream_encoder(LAYER_SEEKABLE_STREAM, is_ogg))
533                         return false;
534
535                 if(!test_stream_encoder(LAYER_FILE, is_ogg))
536                         return false;
537
538                 if(!test_stream_encoder(LAYER_FILENAME, is_ogg))
539                         return false;
540
541                 (void) grabbag__file_remove_file(flacfilename(is_ogg));
542
543                 free_metadata_blocks_();
544
545                 if(!FLAC_API_SUPPORTS_OGG_FLAC || is_ogg)
546                         break;
547                 is_ogg = true;
548         }
549
550         return true;
551 }