mirror of
https://github.com/fmang/opustags.git
synced 2025-01-15 12:43:17 +01:00
Migrate the opus module to use exceptions
This commit is contained in:
parent
1c03c31e82
commit
8a54361b8f
@ -374,13 +374,7 @@ static void process(ot::ogg_reader& reader, ot::ogg_writer* writer, const ot::op
|
||||
writer->write_page(reader.page);
|
||||
} else if (reader.absolute_page_no == 1) { // Comment header
|
||||
ot::opus_tags tags;
|
||||
reader.process_header_packet(
|
||||
[&tags](ogg_packet& p) {
|
||||
ot::status rc = ot::parse_tags(p, tags);
|
||||
if (rc != ot::st::ok)
|
||||
throw rc;
|
||||
}
|
||||
);
|
||||
reader.process_header_packet([&tags](ogg_packet& p) { tags = ot::parse_tags(p); });
|
||||
edit_tags(tags, opt);
|
||||
if (writer) {
|
||||
if (opt.edit_interactively) {
|
||||
|
25
src/opus.cc
25
src/opus.cc
@ -39,10 +39,10 @@
|
||||
#define le32toh(x) OSSwapLittleToHostInt32(x)
|
||||
#endif
|
||||
|
||||
ot::status ot::parse_tags(const ogg_packet& packet, opus_tags& tags)
|
||||
ot::opus_tags ot::parse_tags(const ogg_packet& packet)
|
||||
{
|
||||
if (packet.bytes < 0)
|
||||
return {st::int_overflow, "Overflowing comment header length"};
|
||||
throw status {st::int_overflow, "Overflowing comment header length"};
|
||||
size_t size = static_cast<size_t>(packet.bytes);
|
||||
const char* data = reinterpret_cast<char*>(packet.packet);
|
||||
size_t pos = 0;
|
||||
@ -50,36 +50,36 @@ ot::status ot::parse_tags(const ogg_packet& packet, opus_tags& tags)
|
||||
|
||||
// Magic number
|
||||
if (8 > size)
|
||||
return {st::cut_magic_number, "Comment header too short for the magic number"};
|
||||
throw status {st::cut_magic_number, "Comment header too short for the magic number"};
|
||||
if (memcmp(data, "OpusTags", 8) != 0)
|
||||
return {st::bad_magic_number, "Comment header did not start with OpusTags"};
|
||||
throw status {st::bad_magic_number, "Comment header did not start with OpusTags"};
|
||||
|
||||
// Vendor
|
||||
pos = 8;
|
||||
if (pos + 4 > size)
|
||||
return {st::cut_vendor_length,
|
||||
throw status {st::cut_vendor_length,
|
||||
"Vendor string length did not fit the comment header"};
|
||||
size_t vendor_length = le32toh(*((uint32_t*) (data + pos)));
|
||||
if (pos + 4 + vendor_length > size)
|
||||
return {st::cut_vendor_data, "Vendor string did not fit the comment header"};
|
||||
throw status {st::cut_vendor_data, "Vendor string did not fit the comment header"};
|
||||
my_tags.vendor = std::string(data + pos + 4, vendor_length);
|
||||
pos += 4 + my_tags.vendor.size();
|
||||
|
||||
// Comment count
|
||||
if (pos + 4 > size)
|
||||
return {st::cut_comment_count, "Comment count did not fit the comment header"};
|
||||
throw status {st::cut_comment_count, "Comment count did not fit the comment header"};
|
||||
uint32_t count = le32toh(*((uint32_t*) (data + pos)));
|
||||
pos += 4;
|
||||
|
||||
// Comments' data
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
if (pos + 4 > size)
|
||||
return {st::cut_comment_length,
|
||||
"Comment length did not fit the comment header"};
|
||||
throw status {st::cut_comment_length,
|
||||
"Comment length did not fit the comment header"};
|
||||
uint32_t comment_length = le32toh(*((uint32_t*) (data + pos)));
|
||||
if (pos + 4 + comment_length > size)
|
||||
return {st::cut_comment_data,
|
||||
"Comment string did not fit the comment header"};
|
||||
throw status {st::cut_comment_data,
|
||||
"Comment string did not fit the comment header"};
|
||||
const char *comment_value = data + pos + 4;
|
||||
my_tags.comments.emplace_back(comment_value, comment_length);
|
||||
pos += 4 + comment_length;
|
||||
@ -88,8 +88,7 @@ ot::status ot::parse_tags(const ogg_packet& packet, opus_tags& tags)
|
||||
// Extra data
|
||||
my_tags.extra_data = std::string(data + pos, size - pos);
|
||||
|
||||
tags = std::move(my_tags);
|
||||
return st::ok;
|
||||
return my_tags;
|
||||
}
|
||||
|
||||
ot::dynamic_ogg_packet ot::render_tags(const opus_tags& tags)
|
||||
|
@ -376,10 +376,8 @@ struct opus_tags {
|
||||
|
||||
/**
|
||||
* Read the given OpusTags packet and extract its content into an opus_tags object.
|
||||
*
|
||||
* On error, the tags object is left unchanged.
|
||||
*/
|
||||
status parse_tags(const ogg_packet& packet, opus_tags& tags);
|
||||
opus_tags parse_tags(const ogg_packet& packet);
|
||||
|
||||
/**
|
||||
* Serialize an #opus_tags object into an OpusTags Ogg packet.
|
||||
|
39
t/opus.cc
39
t/opus.cc
@ -14,13 +14,10 @@ static const char standard_OpusTags[] =
|
||||
|
||||
static void parse_standard()
|
||||
{
|
||||
ot::opus_tags tags;
|
||||
ogg_packet op;
|
||||
op.bytes = sizeof(standard_OpusTags) - 1;
|
||||
op.packet = (unsigned char*) standard_OpusTags;
|
||||
auto rc = ot::parse_tags(op, tags);
|
||||
if (rc != ot::st::ok)
|
||||
throw failure("ot::parse_tags did not return ok");
|
||||
ot::opus_tags tags = ot::parse_tags(op);
|
||||
if (tags.vendor != "opustags test packet")
|
||||
throw failure("bad vendor string");
|
||||
if (tags.comments.size() != 2)
|
||||
@ -35,6 +32,16 @@ static void parse_standard()
|
||||
throw failure("found mysterious padding data");
|
||||
}
|
||||
|
||||
static ot::status try_parse_tags(const ogg_packet& packet)
|
||||
{
|
||||
try {
|
||||
ot::parse_tags(packet);
|
||||
return ot::st::ok;
|
||||
} catch (const ot::status& rc) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try parse_tags with packets that should not valid, or that might even
|
||||
* corrupt the memory. Run this one with valgrind to ensure we're not
|
||||
@ -59,43 +66,40 @@ static void parse_corrupted()
|
||||
char* end = packet + size;
|
||||
|
||||
op.bytes = 7;
|
||||
if (ot::parse_tags(op, tags) != ot::st::cut_magic_number)
|
||||
if (try_parse_tags(op) != ot::st::cut_magic_number)
|
||||
throw failure("did not detect the overflowing magic number");
|
||||
op.bytes = 11;
|
||||
if (ot::parse_tags(op, tags) != ot::st::cut_vendor_length)
|
||||
if (try_parse_tags(op) != ot::st::cut_vendor_length)
|
||||
throw failure("did not detect the overflowing vendor string length");
|
||||
op.bytes = size;
|
||||
|
||||
header_data[0] = 'o';
|
||||
if (ot::parse_tags(op, tags) != ot::st::bad_magic_number)
|
||||
if (try_parse_tags(op) != ot::st::bad_magic_number)
|
||||
throw failure("did not detect the bad magic number");
|
||||
header_data[0] = 'O';
|
||||
|
||||
*vendor_length = end - vendor_string + 1;
|
||||
if (ot::parse_tags(op, tags) != ot::st::cut_vendor_data)
|
||||
if (try_parse_tags(op) != ot::st::cut_vendor_data)
|
||||
throw failure("did not detect the overflowing vendor string");
|
||||
*vendor_length = end - vendor_string - 3;
|
||||
if (ot::parse_tags(op, tags) != ot::st::cut_comment_count)
|
||||
if (try_parse_tags(op) != ot::st::cut_comment_count)
|
||||
throw failure("did not detect the overflowing comment count");
|
||||
*vendor_length = comment_count - vendor_string;
|
||||
|
||||
++*comment_count;
|
||||
if (ot::parse_tags(op, tags) != ot::st::cut_comment_length)
|
||||
if (try_parse_tags(op) != ot::st::cut_comment_length)
|
||||
throw failure("did not detect the overflowing comment length");
|
||||
*first_comment_length = end - first_comment_data + 1;
|
||||
if (ot::parse_tags(op, tags) != ot::st::cut_comment_data)
|
||||
if (try_parse_tags(op) != ot::st::cut_comment_data)
|
||||
throw failure("did not detect the overflowing comment data");
|
||||
}
|
||||
|
||||
static void recode_standard()
|
||||
{
|
||||
ot::opus_tags tags;
|
||||
ogg_packet op;
|
||||
op.bytes = sizeof(standard_OpusTags) - 1;
|
||||
op.packet = (unsigned char*) standard_OpusTags;
|
||||
auto rc = ot::parse_tags(op, tags);
|
||||
if (rc != ot::st::ok)
|
||||
throw failure("ot::parse_tags did not return ok");
|
||||
ot::opus_tags tags = ot::parse_tags(op);
|
||||
auto packet = ot::render_tags(tags);
|
||||
if (packet.b_o_s != 0)
|
||||
throw failure("b_o_s should not be set");
|
||||
@ -113,7 +117,6 @@ static void recode_standard()
|
||||
|
||||
static void recode_padding()
|
||||
{
|
||||
ot::opus_tags tags;
|
||||
std::string padded_OpusTags(standard_OpusTags, sizeof(standard_OpusTags));
|
||||
// ^ note: padded_OpusTags ends with a null byte here
|
||||
padded_OpusTags += "hello";
|
||||
@ -121,9 +124,7 @@ static void recode_padding()
|
||||
op.bytes = padded_OpusTags.size();
|
||||
op.packet = (unsigned char*) padded_OpusTags.data();
|
||||
|
||||
auto rc = ot::parse_tags(op, tags);
|
||||
if (rc != ot::st::ok)
|
||||
throw failure("ot::parse_tags did not return ok");
|
||||
ot::opus_tags tags = ot::parse_tags(op);
|
||||
if (tags.extra_data != "\0hello"s)
|
||||
throw failure("corrupted extra data");
|
||||
// recode the packet and ensure it's exactly the same
|
||||
|
2
t/tap.h
2
t/tap.h
@ -30,6 +30,8 @@ static void run(F test, const char *name)
|
||||
ok = true;
|
||||
} catch (failure& e) {
|
||||
std::cerr << "# fail: " << e.what() << "\n";
|
||||
} catch (const ot::status &rc) {
|
||||
std::cerr << "# unexpected error: " << rc.message << "\n";
|
||||
}
|
||||
std::cout << (ok ? "ok" : "not ok") << " - " << name << "\n";
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user