From 375de02b368746ce23ea56490d5bb9a9bfc3cc86 Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Wed, 2 Nov 2022 18:11:00 +0100 Subject: [PATCH] doc type version handler: create EBML Void inside EBML Head instead of after it When the Matroska version numbers stored in the EBML Head element are updated, the updated EBML Head element might be smaller than the existing one. In that case the programs used to shrink the EBML Head & write a small EBML Void element between the updated EBML Head & the following element, usually a Matroska Segment element. This isn't widely supported by programs including MKVToolNix itself, causing them to declare such files as invalid. The programs will now create the EBML Void element inside the EBML Head element, making them a level 1 element instead of a level 0 element. Affects mkvpropedit, MKVToolNix GUI's chapter & header editors. Fixes #3355. --- NEWS.md | 9 +++++++++ src/common/doc_type_version_handler.cpp | 15 +++++++++------ tests/results.txt | 1 + ...pe_version_handler_create_void_in_ebml_head.rb | 15 +++++++++++++++ 4 files changed, 34 insertions(+), 6 deletions(-) create mode 100755 tests/test-0748doc_type_version_handler_create_void_in_ebml_head.rb diff --git a/NEWS.md b/NEWS.md index c48fc9c88..60a4bde9d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -26,6 +26,15 @@ those elements, even if they're found in the file to be modified. The programs will no longer abort with error messages such as `assertion "false" failed`. Fixes #3416. +* mkvpropedit, MKVToolNix GUI's chapter & header editors: when the Matroska + version numbers stored in the EBML Head element are updated, the updated + EBML Head element might be smaller than the existing one. In that case the + programs used to shrink the EBML Head & write a small EBML Void element + between the updated EBML Head & the following element, usually a Matroska + Segment element. This isn't widely supported by programs including + MKVToolNix itself, causing them to declare such files as invalid. The + programs will now create the EBML Void element inside the EBML Head element, + making them a level 1 element instead of a level 0 element. Fixes #3355. # Version 71.1.0 "Fortitude" 2022-10-09 diff --git a/src/common/doc_type_version_handler.cpp b/src/common/doc_type_version_handler.cpp index 33cfc3554..23ffcf35f 100644 --- a/src/common/doc_type_version_handler.cpp +++ b/src/common/doc_type_version_handler.cpp @@ -156,15 +156,18 @@ doc_type_version_handler_c::do_update_ebml_head(mm_io_c &file) { if (diff == 1) head->SetSizeLength(head->GetSizeLength() + 1); + else if (diff > 1) { + auto v = new EbmlVoid; + v->SetSize(diff - 2); + head->PushElement(*v); + new_size = head->UpdateSize(true); + + mxdebug_if(p->debug, fmt::format("do_update_ebml_head: diff > 1 case; new size now {0}\n", new_size)); + } + file.setFilePointer(head->GetElementPosition()); head->Render(*stream, true); - if (diff > 1) { - EbmlVoid v; - v.SetSize(diff - 2); - v.Render(*stream); - } - } catch (mtx::mm_io::exception &) { return update_result_e::err_read_or_write_failure; } diff --git a/tests/results.txt b/tests/results.txt index d792cb7c7..b26c174ee 100644 --- a/tests/results.txt +++ b/tests/results.txt @@ -592,3 +592,4 @@ T_0744hevc_first_unspec_nalus_after_one_mb_of_data:8083c1cd24908eba1f86fec60e307 T_0745av1_single_frame:294681d11be5149ba29728a1e37a00bc:passed:20220730-122150:0.044258962 T_0746ogg_unknown_track_and_kate_missing_headers:43cb49944b1552ba9df35f2e1ed303d3:passed:20220904-153425:0.031062254 T_0747reversed_attachment_selection:ok-67de61ddef39f3a39fbf68136783b63b-ok-b5bc906a30ca7b969571d29b235cf80f-ok:passed:20221101-125728:0.367793332 +T_0748doc_type_version_handler_create_void_in_ebml_head:4692b2494f3ab58b5e9c09e1ea9ba8c2-429b083f5497fd6085e80c24b660cae5:passed:20221102-180257:0.230079273 diff --git a/tests/test-0748doc_type_version_handler_create_void_in_ebml_head.rb b/tests/test-0748doc_type_version_handler_create_void_in_ebml_head.rb new file mode 100755 index 000000000..e2d62b4b6 --- /dev/null +++ b/tests/test-0748doc_type_version_handler_create_void_in_ebml_head.rb @@ -0,0 +1,15 @@ +#!/usr/bin/ruby -w + +# T_748doc_type_version_handler_create_void_in_ebml_head +describe "mkvpropedit / doc type version handler should create void inside EBLM Head, not on top level" + +work = "#{tmp}.work" + +test "propedit" do + cp "data/mkv/bug3355.mkv", work + propedit work, "--tags track:1:data/tags/bug3355.xml --edit info --set title=Test" + + hash_file work +end + +test_identify work