diff --git a/src/cli.cc b/src/cli.cc index 992cf6d..300496d 100644 --- a/src/cli.cc +++ b/src/cli.cc @@ -190,6 +190,8 @@ static ot::status process(ot::ogg_reader& reader, ot::ogg_writer* writer, const ot::status rc = reader.next_page(); if (rc == ot::st::end_of_stream) break; + else if (rc == ot::st::bad_stream && absolute_page_no == 0) + return {ot::st::bad_stream, "Input is not a valid Ogg file."}; else if (rc != ot::st::ok) return rc; auto serialno = ogg_page_serialno(&reader.page); diff --git a/src/ogg.cc b/src/ogg.cc index 2ee21c5..281ee8e 100644 --- a/src/ogg.cc +++ b/src/ogg.cc @@ -25,19 +25,25 @@ bool ot::is_opus_stream(const ogg_page& identification_header) ot::status ot::ogg_reader::next_page() { - while (ogg_sync_pageout(&sync, &page) != 1) { - if (feof(file)) - return {st::end_of_stream, "End of stream was reached"}; + int rc; + while ((rc = ogg_sync_pageout(&sync, &page)) != 1) { + if (rc == -1) + return {st::bad_stream, "Unsynced data in stream."}; + if (ogg_sync_check(&sync) != 0) + return {st::libogg_error, "ogg_sync_check signalled an error."}; + if (feof(file)) { + if (sync.fill != sync.returned) + return {st::bad_stream, "Unsynced data at end of stream."}; + return {st::end_of_stream, "End of stream was reached."}; + } char* buf = ogg_sync_buffer(&sync, 65536); if (buf == nullptr) - return {st::libogg_error, "ogg_sync_buffer failed"}; + return {st::libogg_error, "ogg_sync_buffer failed."}; size_t len = fread(buf, 1, 65536, file); if (ferror(file)) return {st::standard_error, "fread error: "s + strerror(errno)}; if (ogg_sync_wrote(&sync, len) != 0) - return {st::libogg_error, "ogg_sync_wrote failed"}; - if (ogg_sync_check(&sync) != 0) - return {st::libogg_error, "ogg_sync_check failed"}; + return {st::libogg_error, "ogg_sync_wrote failed."}; } return st::ok; } diff --git a/src/opustags.h b/src/opustags.h index d851eb9..37b82c7 100644 --- a/src/opustags.h +++ b/src/opustags.h @@ -56,6 +56,7 @@ enum class st { standard_error, /**< Error raised by the C standard library. */ int_overflow, /* Ogg */ + bad_stream, end_of_stream, libogg_error, /* Opus */ diff --git a/t/ogg.cc b/t/ogg.cc index f4b6181..1c170d8 100644 --- a/t/ogg.cc +++ b/t/ogg.cc @@ -116,6 +116,16 @@ static void check_memory_ogg() } } +void check_bad_stream() +{ + auto err_msg = "did not detect the stream is not an ogg stream"; + ot::file input = fmemopen((void*) err_msg, 20, "r"); + ot::ogg_reader reader(input.get()); + ot::status rc = reader.next_page(); + if (rc != ot::st::bad_stream) + throw failure(err_msg); +} + void check_identification() { auto good_header = (unsigned char*) @@ -151,9 +161,10 @@ void check_identification() int main(int argc, char **argv) { - std::cout << "1..3\n"; + std::cout << "1..4\n"; run(check_ref_ogg, "check a reference ogg stream"); run(check_memory_ogg, "build and check a fresh stream"); + run(check_bad_stream, "read a non-ogg stream"); run(check_identification, "stream identification"); return 0; } diff --git a/t/opustags.t b/t/opustags.t index 06962d8..bf9f6a2 100644 --- a/t/opustags.t +++ b/t/opustags.t @@ -4,7 +4,7 @@ use strict; use warnings; use utf8; -use Test::More tests => 27; +use Test::More tests => 28; use Digest::MD5; use File::Basename; @@ -73,6 +73,10 @@ is_deeply(opustags('--derp'), ['', <<"EOF", 256], 'unrecognized option shows an error: Unrecognized option '--derp'. EOF +is_deeply(opustags('../opustags'), ['', <<"EOF", 256], 'not an Ogg stream'); +error: Input is not a valid Ogg file. +EOF + #################################################################################################### # Test the main features of opustags on an Ogg Opus sample file.