From: Tsuda Kageyu <tsuda.kageyu@gmail.com>
Date: Thu, 1 Dec 2016 01:50:30 +0000 (+0900)
Subject: Prevent the segment table of Ogg pages from exceeding the size limit.
X-Git-Tag: v1.12-beta-1~104
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cfbaf3459776e45cdbf2954de57bde8b689264fa;p=taglib

Prevent the segment table of Ogg pages from exceeding the size limit.
---

diff --git a/taglib/ogg/oggpage.cpp b/taglib/ogg/oggpage.cpp
index 75aea22a..414d3d53 100644
--- a/taglib/ogg/oggpage.cpp
+++ b/taglib/ogg/oggpage.cpp
@@ -208,15 +208,15 @@ List<Ogg::Page *> Ogg::Page::paginate(const ByteVectorList &packets,
 
   static const unsigned int SplitSize = 32 * 255;
 
-  // Force repagination if the packets are too large for a page.
+  // Force repagination if the segment table will exceed the size limit.
 
   if(strategy != Repaginate) {
 
-    size_t totalSize = packets.size();
+    size_t tableSize = 0;
     for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it)
-      totalSize += it->size();
+      tableSize += it->size() / 255 + 1;
 
-    if(totalSize > 255 * 255)
+    if(tableSize > 255)
       strategy = Repaginate;
   }
 
diff --git a/tests/test_ogg.cpp b/tests/test_ogg.cpp
index af2d5b94..5569e59c 100644
--- a/tests/test_ogg.cpp
+++ b/tests/test_ogg.cpp
@@ -42,7 +42,8 @@ class TestOGG : public CppUnit::TestFixture
 {
   CPPUNIT_TEST_SUITE(TestOGG);
   CPPUNIT_TEST(testSimple);
-  CPPUNIT_TEST(testSplitPackets);
+  CPPUNIT_TEST(testSplitPackets1);
+  CPPUNIT_TEST(testSplitPackets2);
   CPPUNIT_TEST(testDictInterface1);
   CPPUNIT_TEST(testDictInterface2);
   CPPUNIT_TEST(testAudioProperties);
@@ -67,7 +68,7 @@ public:
     }
   }
 
-  void testSplitPackets()
+  void testSplitPackets1()
   {
     ScopedFileCopy copy("empty", ".ogg");
     string newname = copy.fileName();
@@ -110,6 +111,33 @@ public:
     }
   }
 
+  void testSplitPackets2()
+  {
+    ScopedFileCopy copy("empty", ".ogg");
+    string newname = copy.fileName();
+
+    const String text = longText(60890, true);
+
+    {
+      Vorbis::File f(newname.c_str());
+      f.tag()->setTitle(text);
+      f.save();
+    }
+    {
+      Vorbis::File f(newname.c_str());
+      CPPUNIT_ASSERT(f.isValid());
+      CPPUNIT_ASSERT_EQUAL(text, f.tag()->title());
+
+      f.tag()->setTitle("ABCDE");
+      f.save();
+    }
+    {
+      Vorbis::File f(newname.c_str());
+      CPPUNIT_ASSERT(f.isValid());
+      CPPUNIT_ASSERT_EQUAL(String("ABCDE"), f.tag()->title());
+    }
+  }
+
   void testDictInterface1()
   {
     ScopedFileCopy copy("empty", ".ogg");