Ver Fonte

2010-03-03 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	In Metalink4, if size element contains invalid size, discard whole
	document. Added strict hash value check for metalink3/4.
	* src/MetalinkParserController.cc
	* src/MetalinkParserStateMachine.cc
	* src/MetalinkParserStateMachine.h
	* src/MetalinkParserStateV3Impl.cc
	* src/MetalinkParserStateV4Impl.cc
	* src/util.cc
	* src/util.h
	* test/MetalinkParserControllerTest.cc
	* test/MetalinkProcessorTest.cc
	* test/metalink4.xml
Tatsuhiro Tsujikawa há 15 anos atrás
pai
commit
3bb7855a56

+ 15 - 0
ChangeLog

@@ -1,3 +1,18 @@
+2010-03-03  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	In Metalink4, if size element contains invalid size, discard whole
+	document. Added strict hash value check for metalink3/4.
+	* src/MetalinkParserController.cc
+	* src/MetalinkParserStateMachine.cc
+	* src/MetalinkParserStateMachine.h
+	* src/MetalinkParserStateV3Impl.cc
+	* src/MetalinkParserStateV4Impl.cc
+	* src/util.cc
+	* src/util.h
+	* test/MetalinkParserControllerTest.cc
+	* test/MetalinkProcessorTest.cc
+	* test/metalink4.xml
+
 2010-03-02  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Added strict attribute validation for metalink4. When

+ 27 - 4
src/MetalinkParserController.cc

@@ -53,6 +53,13 @@
 
 namespace aria2 {
 
+static bool isValidHash(const std::string& algo, const std::string& hash)
+{
+  return util::isHexDigit(hash) &&
+    MessageDigestContext::supports(algo) &&
+    MessageDigestContext::digestLength(algo)*2 == hash.size();
+}
+
 MetalinkParserController::MetalinkParserController():
   _metalinker(new Metalinker())
 {}
@@ -281,7 +288,11 @@ void MetalinkParserController::setHashOfChecksum(const std::string& md)
   if(_tChecksum.isNull()) {
     return;
   }
-  _tChecksum->setMessageDigest(md);
+  if(isValidHash(_tChecksum->getAlgo(), md)) {
+    _tChecksum->setMessageDigest(md);
+  } else {
+    cancelChecksumTransaction();
+  }
 #endif // ENABLE_MESSAGE_DIGEST
 }
 
@@ -352,7 +363,11 @@ void MetalinkParserController::addHashOfChunkChecksumV4(const std::string& md)
   if(_tChunkChecksumV4.isNull()) {
     return;
   }
-  _tempChunkChecksumsV4.push_back(md);
+  if(isValidHash(_tChunkChecksumV4->getAlgo(), md)) {
+    _tempChunkChecksumsV4.push_back(md);
+  } else {
+    cancelChunkChecksumTransactionV4();
+  }
 #endif // ENABLE_MESSAGE_DIGEST  
 }
 
@@ -426,7 +441,11 @@ void MetalinkParserController::addHashOfChunkChecksum(size_t order, const std::s
   if(_tChunkChecksum.isNull()) {
     return;
   }
-  _tempChunkChecksums.push_back(std::pair<size_t, std::string>(order, md));
+  if(isValidHash(_tChunkChecksum->getAlgo(), md)) {
+    _tempChunkChecksums.push_back(std::make_pair(order, md));
+  } else {
+    cancelChunkChecksumTransaction();
+  }
 #endif // ENABLE_MESSAGE_DIGEST
 }
 
@@ -446,7 +465,11 @@ void MetalinkParserController::setMessageDigestOfChunkChecksum(const std::string
   if(_tChunkChecksum.isNull()) {
     return;
   }
-  _tempHashPair.second = md;
+  if(isValidHash(_tChunkChecksum->getAlgo(), md)) {
+    _tempHashPair.second = md;
+  } else {
+    cancelChunkChecksumTransaction();
+  }
 #endif // ENABLE_MESSAGE_DIGEST
 }
 

+ 5 - 0
src/MetalinkParserStateMachine.cc

@@ -290,6 +290,11 @@ void MetalinkParserStateMachine::commitEntryTransaction()
   _ctrl->commitEntryTransaction();
 }
 
+void MetalinkParserStateMachine::cancelEntryTransaction()
+{
+  _ctrl->cancelEntryTransaction();
+}
+
 void MetalinkParserStateMachine::newResourceTransaction()
 {
   _ctrl->newResourceTransaction();

+ 2 - 0
src/MetalinkParserStateMachine.h

@@ -166,6 +166,8 @@ public:
 
   void commitEntryTransaction();
 
+  void cancelEntryTransaction();
+
   void newResourceTransaction();
 
   void setURLOfResource(const std::string& url);

+ 1 - 1
src/MetalinkParserStateV3Impl.cc

@@ -183,7 +183,7 @@ void SizeMetalinkParserState::endElement
  const std::string& characters)
 {
   try {
-    stm->setFileLengthOfEntry(util::parseLLInt(characters));
+    stm->setFileLengthOfEntry(util::parseULLInt(characters));
   } catch(RecoverableException& e) {
     // current metalink specification doesn't require size element.
   }

+ 3 - 2
src/MetalinkParserStateV4Impl.cc

@@ -281,9 +281,10 @@ void SizeMetalinkParserStateV4::endElement
  const std::string& characters)
 {
   try {
-    stm->setFileLengthOfEntry(util::parseLLInt(characters));
+    stm->setFileLengthOfEntry(util::parseULLInt(characters));
   } catch(RecoverableException& e) {
-    // current metalink specification doesn't require size element.
+    stm->cancelEntryTransaction();
+    stm->logError("Bad size");
   }
 }
 

+ 10 - 0
src/util.cc

@@ -216,6 +216,16 @@ bool isHexDigit(const char c)
   return isDigit(c) || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f');
 }
 
+bool isHexDigit(const std::string& s)
+{
+  for(std::string::const_iterator i = s.begin(), eoi = s.end(); i != eoi; ++i) {
+    if(!isHexDigit(*i)) {
+      return false;
+    }
+  }
+  return true;
+}
+
 bool inRFC3986ReservedChars(const char c)
 {
   static const char reserved[] = {

+ 5 - 1
src/util.h

@@ -254,11 +254,15 @@ void sleep(long seconds);
 void usleep(long microseconds);
   
 bool isNumber(const std::string& what);
+
+bool isHexDigit(const char c);
+
+bool isHexDigit(const std::string& s);
   
 bool isLowercase(const std::string& what);
   
 bool isUppercase(const std::string& what);
-  
+
 /**
  * Converts alphabets to unsigned int, assuming alphabets as a base 26
  * integer and 'a' or 'A' is 0.

+ 60 - 23
test/MetalinkParserControllerTest.cc

@@ -150,19 +150,27 @@ void MetalinkParserControllerTest::testChecksumTransaction()
   ctrl.newEntryTransaction();
   ctrl.newChecksumTransaction();
   ctrl.setTypeOfChecksum("md5");
-  ctrl.setHashOfChecksum("hash");
+  ctrl.setHashOfChecksum("acbd18db4cc2f85cedef654fccc4a4d8");
   ctrl.commitEntryTransaction();
   {
     SharedHandle<Metalinker> m = ctrl.getResult();
     SharedHandle<Checksum> md = m->entries.front()->checksum;
     CPPUNIT_ASSERT_EQUAL(std::string("md5"), md->getAlgo());
-    CPPUNIT_ASSERT_EQUAL(std::string("hash"), md->getMessageDigest());
+    CPPUNIT_ASSERT_EQUAL(std::string("acbd18db4cc2f85cedef654fccc4a4d8"),
+                         md->getMessageDigest());
   }
   ctrl.newEntryTransaction();
   ctrl.newChecksumTransaction();
-  ctrl.cancelChecksumTransaction();
+  ctrl.setTypeOfChecksum("md5");
+  ctrl.setHashOfChecksum("badhash");
   ctrl.commitEntryTransaction();
   CPPUNIT_ASSERT(ctrl.getResult()->entries[1]->checksum.isNull());
+
+  ctrl.newEntryTransaction();
+  ctrl.newChecksumTransaction();
+  ctrl.cancelChecksumTransaction();
+  ctrl.commitEntryTransaction();
+  CPPUNIT_ASSERT(ctrl.getResult()->entries[2]->checksum.isNull());
 }
 
 void MetalinkParserControllerTest::testChunkChecksumTransaction()
@@ -172,11 +180,11 @@ void MetalinkParserControllerTest::testChunkChecksumTransaction()
   ctrl.newChunkChecksumTransaction();
   ctrl.setTypeOfChunkChecksum("md5");
   ctrl.setLengthOfChunkChecksum(256*1024);
-  ctrl.addHashOfChunkChecksum(4, "hash4");
-  ctrl.addHashOfChunkChecksum(1, "hash1");
-  ctrl.addHashOfChunkChecksum(3, "hash3");
-  ctrl.addHashOfChunkChecksum(2, "hash2");
-  ctrl.addHashOfChunkChecksum(5, "hash5");
+  ctrl.addHashOfChunkChecksum(4, "4cbd18db4cc2f85cedef654fccc4a4d8");
+  ctrl.addHashOfChunkChecksum(1, "1cbd18db4cc2f85cedef654fccc4a4d8");
+  ctrl.addHashOfChunkChecksum(3, "3cbd18db4cc2f85cedef654fccc4a4d8");
+  ctrl.addHashOfChunkChecksum(2, "2cbd18db4cc2f85cedef654fccc4a4d8");
+  ctrl.addHashOfChunkChecksum(5, "5cbd18db4cc2f85cedef654fccc4a4d8");
   ctrl.commitEntryTransaction();
   {
     SharedHandle<Metalinker> m = ctrl.getResult();
@@ -184,17 +192,30 @@ void MetalinkParserControllerTest::testChunkChecksumTransaction()
     CPPUNIT_ASSERT_EQUAL(std::string("md5"), md->getAlgo());
     CPPUNIT_ASSERT_EQUAL((size_t)256*1024, md->getChecksumLength());
     CPPUNIT_ASSERT_EQUAL((size_t)5, md->countChecksum());
-    CPPUNIT_ASSERT_EQUAL(std::string("hash1"), md->getChecksums()[0]);
-    CPPUNIT_ASSERT_EQUAL(std::string("hash2"), md->getChecksums()[1]);
-    CPPUNIT_ASSERT_EQUAL(std::string("hash3"), md->getChecksums()[2]);
-    CPPUNIT_ASSERT_EQUAL(std::string("hash4"), md->getChecksums()[3]);
-    CPPUNIT_ASSERT_EQUAL(std::string("hash5"), md->getChecksums()[4]);
+    CPPUNIT_ASSERT_EQUAL(std::string("1cbd18db4cc2f85cedef654fccc4a4d8"),
+                         md->getChecksums()[0]);
+    CPPUNIT_ASSERT_EQUAL(std::string("2cbd18db4cc2f85cedef654fccc4a4d8"),
+                         md->getChecksums()[1]);
+    CPPUNIT_ASSERT_EQUAL(std::string("3cbd18db4cc2f85cedef654fccc4a4d8"),
+                         md->getChecksums()[2]);
+    CPPUNIT_ASSERT_EQUAL(std::string("4cbd18db4cc2f85cedef654fccc4a4d8"),
+                         md->getChecksums()[3]);
+    CPPUNIT_ASSERT_EQUAL(std::string("5cbd18db4cc2f85cedef654fccc4a4d8"),
+                         md->getChecksums()[4]);
   }
   ctrl.newEntryTransaction();
   ctrl.newChunkChecksumTransaction();
-  ctrl.cancelChunkChecksumTransaction();
+  ctrl.setTypeOfChunkChecksum("md5");
+  ctrl.setLengthOfChunkChecksum(256*1024);
+  ctrl.addHashOfChunkChecksum(1, "badhash");
   ctrl.commitEntryTransaction();
   CPPUNIT_ASSERT(ctrl.getResult()->entries[1]->chunkChecksum.isNull());
+
+  ctrl.newEntryTransaction();
+  ctrl.newChunkChecksumTransaction();
+  ctrl.cancelChunkChecksumTransaction();
+  ctrl.commitEntryTransaction();
+  CPPUNIT_ASSERT(ctrl.getResult()->entries[2]->chunkChecksum.isNull());
 }
 
 void MetalinkParserControllerTest::testChunkChecksumTransactionV4()
@@ -202,27 +223,43 @@ void MetalinkParserControllerTest::testChunkChecksumTransactionV4()
   MetalinkParserController ctrl;
   ctrl.newEntryTransaction();
   ctrl.newChunkChecksumTransactionV4();
-  ctrl.setTypeOfChunkChecksumV4("md5");
+  ctrl.setTypeOfChunkChecksumV4("sha-1");
   ctrl.setLengthOfChunkChecksumV4(256*1024);
-  ctrl.addHashOfChunkChecksumV4("hash1");
-  ctrl.addHashOfChunkChecksumV4("hash2");
-  ctrl.addHashOfChunkChecksumV4("hash3");
+
+  ctrl.addHashOfChunkChecksumV4("5bd9f7248df0f3a6a86ab6c95f48787d546efa14");
+  ctrl.addHashOfChunkChecksumV4("9413ee70957a09d55704123687478e07f18c7b29");
+  ctrl.addHashOfChunkChecksumV4("44213f9f4d59b557314fadcd233232eebcac8012");
   ctrl.commitEntryTransaction();
   {
     SharedHandle<Metalinker> m = ctrl.getResult();
     SharedHandle<ChunkChecksum> md = m->entries.front()->chunkChecksum;
-    CPPUNIT_ASSERT_EQUAL(std::string("md5"), md->getAlgo());
+    CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), md->getAlgo());
     CPPUNIT_ASSERT_EQUAL((size_t)256*1024, md->getChecksumLength());
     CPPUNIT_ASSERT_EQUAL((size_t)3, md->countChecksum());
-    CPPUNIT_ASSERT_EQUAL(std::string("hash1"), md->getChecksums()[0]);
-    CPPUNIT_ASSERT_EQUAL(std::string("hash2"), md->getChecksums()[1]);
-    CPPUNIT_ASSERT_EQUAL(std::string("hash3"), md->getChecksums()[2]);
+    CPPUNIT_ASSERT_EQUAL
+      (std::string("5bd9f7248df0f3a6a86ab6c95f48787d546efa14"),
+       md->getChecksums()[0]);
+    CPPUNIT_ASSERT_EQUAL
+      (std::string("9413ee70957a09d55704123687478e07f18c7b29"),
+       md->getChecksums()[1]);
+    CPPUNIT_ASSERT_EQUAL
+      (std::string("44213f9f4d59b557314fadcd233232eebcac8012"),
+       md->getChecksums()[2]);
   }
   ctrl.newEntryTransaction();
   ctrl.newChunkChecksumTransactionV4();
-  ctrl.cancelChunkChecksumTransactionV4();
+  ctrl.setTypeOfChunkChecksumV4("sha-1");
+  ctrl.setLengthOfChunkChecksumV4(256*1024);
+  ctrl.addHashOfChunkChecksumV4("5bd9f7248df0f3a6a86ab6c95f48787d546efa14");
+  ctrl.addHashOfChunkChecksumV4("badhash");
   ctrl.commitEntryTransaction();
   CPPUNIT_ASSERT(ctrl.getResult()->entries[1]->chunkChecksum.isNull());
+
+  ctrl.newEntryTransaction();
+  ctrl.newChunkChecksumTransactionV4();
+  ctrl.cancelChunkChecksumTransactionV4();
+  ctrl.commitEntryTransaction();
+  CPPUNIT_ASSERT(ctrl.getResult()->entries[2]->chunkChecksum.isNull());
 }
 #endif // ENABLE_MESSAGE_DIGEST
 

+ 93 - 47
test/MetalinkProcessorTest.cc

@@ -33,6 +33,7 @@ class MetalinkProcessorTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testMalformedXML);
   CPPUNIT_TEST(testMalformedXML2);
   CPPUNIT_TEST(testBadSize);
+  CPPUNIT_TEST(testBadSizeV4);
   CPPUNIT_TEST(testBadMaxConn);
   CPPUNIT_TEST(testNoName);  
   CPPUNIT_TEST(testBadURLPrefs);
@@ -58,6 +59,7 @@ public:
   void testMalformedXML();
   void testMalformedXML2();
   void testBadSize();
+  void testBadSizeV4();
   void testBadMaxConn();
   void testNoName();
   void testBadURLPrefs();
@@ -90,7 +92,7 @@ void MetalinkProcessorTest::testParseFileV4()
   CPPUNIT_ASSERT_EQUAL((uint64_t)786430LL, e->getLength());
   CPPUNIT_ASSERT_EQUAL(-1, e->maxConnections);
 #ifdef ENABLE_MESSAGE_DIGEST
-  CPPUNIT_ASSERT_EQUAL(std::string("80bc95fd391772fa61c91ed68567f0980bb45fd9"),
+  CPPUNIT_ASSERT_EQUAL(std::string("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"),
 		       e->checksum->getMessageDigest());
   CPPUNIT_ASSERT(!e->checksum.isNull());
   CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), e->checksum->getAlgo());
@@ -98,11 +100,11 @@ void MetalinkProcessorTest::testParseFileV4()
   CPPUNIT_ASSERT_EQUAL(std::string("sha-256"), e->chunkChecksum->getAlgo());
   CPPUNIT_ASSERT_EQUAL((size_t)262144, e->chunkChecksum->getChecksumLength());
   CPPUNIT_ASSERT_EQUAL((size_t)3, e->chunkChecksum->countChecksum());
-  CPPUNIT_ASSERT_EQUAL(std::string("metalinkhash1"),
+  CPPUNIT_ASSERT_EQUAL(std::string("0245178074fd042e19b7c3885b360fc21064b30e73f5626c7e3b005d048069c5"),
 		       e->chunkChecksum->getChecksum(0));
-  CPPUNIT_ASSERT_EQUAL(std::string("metalinkhash2"),
+  CPPUNIT_ASSERT_EQUAL(std::string("487ba2299be7f759d7c7bf6a4ac3a32cee81f1bb9332fc485947e32918864fb2"),
 		       e->chunkChecksum->getChecksum(1));
-  CPPUNIT_ASSERT_EQUAL(std::string("metalinkhash3"),
+  CPPUNIT_ASSERT_EQUAL(std::string("37290d74ac4d186e3a8e5785d259d2ec04fac91ae28092e7620ec8bc99e830aa"),
 		       e->chunkChecksum->getChecksum(2));
 #endif // ENABLE_MESSAGE_DIGEST
   CPPUNIT_ASSERT(!e->getSignature().isNull());
@@ -202,6 +204,11 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
     } catch(RecoverableException& e) {
       // success
     }
+    dw->setString(StringFormat(tmpl, "A").str());
+    try {
+      m = proc.parseFromBinaryStream(dw);
+      CPPUNIT_FAIL("exception must be thrown.");
+    } catch(RecoverableException& e) {}
   }
   {
     // Testing metaurl@priority
@@ -239,6 +246,11 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
     } catch(RecoverableException& e) {
       // success
     }
+    dw->setString(StringFormat(tmpl, "A").str());
+    try {
+      m = proc.parseFromBinaryStream(dw);
+      CPPUNIT_FAIL("exception must be thrown.");
+    } catch(RecoverableException& e) {}
   }
   {
     // Testing metaurl@mediatype
@@ -346,6 +358,12 @@ void MetalinkProcessorTest::testParseFileV4_attrs()
       m = proc.parseFromBinaryStream(dw);
       CPPUNIT_FAIL("exception must be thrown.");
     } catch(RecoverableException& e) {}
+    // not a number
+    try {
+      dw->setString(StringFormat(tmpl, "A").str());
+      m = proc.parseFromBinaryStream(dw);
+      CPPUNIT_FAIL("exception must be thrown.");
+    } catch(RecoverableException& e) {}
   }
   {
     // Testing pieces@type
@@ -622,6 +640,31 @@ void MetalinkProcessorTest::testMalformedXML2()
   }
 }
 
+void MetalinkProcessorTest::testBadSizeV4()
+{
+  MetalinkProcessor proc;
+  SharedHandle<Metalinker> m;
+  SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
+
+  const char* tmpl =
+    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+    "<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
+    "<file name=\"foo\">"
+    "<size>%s</size>"
+    "<url>http://example.org</url>"
+     "</file>"
+    "</metalink>";
+
+  dw->setString(StringFormat(tmpl, "9223372036854775807").str());
+  m = proc.parseFromBinaryStream(dw);
+
+  dw->setString(StringFormat(tmpl, "-1").str());
+  try {
+    m = proc.parseFromBinaryStream(dw);
+    CPPUNIT_FAIL("exception must be thrown.");
+  } catch(RecoverableException& e) {}
+}
+  
 void MetalinkProcessorTest::testBadSize()
 {
   MetalinkProcessor proc;
@@ -850,21 +893,22 @@ void MetalinkProcessorTest::testBadPieceNo()
 {
   MetalinkProcessor proc;
   SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
-  dw->setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
-                "<files>"
-                "<file name=\"aria2.tar.bz2\">"
-                "  <verification>"
-                "    <pieces length=\"512\" type=\"sha1\">"
-                "      <hash piece=\"0\">abc</hash>"
-                "      <hash piece=\"xyz\">xyz</hash>"
-                "    </pieces>"
-                "    <pieces length=\"1024\" type=\"sha1\">"
-                "      <hash piece=\"0\">abc</hash>"
-                "    </pieces>"
-                "  </verification>"
-                "</file>"
-                "</files>"
-                "</metalink>");
+  dw->setString
+    ("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
+     "<files>"
+     "<file name=\"aria2.tar.bz2\">"
+     "  <verification>"
+     "    <pieces length=\"512\" type=\"sha1\">"
+     "      <hash piece=\"0\">44213f9f4d59b557314fadcd233232eebcac8012</hash>"
+     "      <hash piece=\"xyz\">44213f9f4d59b557314fadcd233232eebcac8012</hash>"
+     "    </pieces>"
+     "    <pieces length=\"1024\" type=\"sha1\">"
+     "      <hash piece=\"0\">44213f9f4d59b557314fadcd233232eebcac8012</hash>"
+     "    </pieces>"
+     "  </verification>"
+     "</file>"
+     "</files>"
+     "</metalink>");
 
   try {
     SharedHandle<Metalinker> m = proc.parseFromBinaryStream(dw);
@@ -883,20 +927,21 @@ void MetalinkProcessorTest::testBadPieceLength()
 {
   MetalinkProcessor proc;
   SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
-  dw->setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
-                "<files>"
-                "<file name=\"aria2.tar.bz2\">"
-                "  <verification>"
-                "    <pieces length=\"xyz\" type=\"sha1\">"
-                "      <hash piece=\"0\">abc</hash>"
-                "    </pieces>"
-                "    <pieces length=\"1024\" type=\"sha1\">"
-                "      <hash piece=\"0\">abc</hash>"
-                "    </pieces>"
-                "  </verification>"
-                "</file>"
-                "</files>"
-                "</metalink>");
+  dw->setString
+    ("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
+     "<files>"
+     "<file name=\"aria2.tar.bz2\">"
+     "  <verification>"
+     "    <pieces length=\"xyz\" type=\"sha1\">"
+     "      <hash piece=\"0\">44213f9f4d59b557314fadcd233232eebcac8012</hash>"
+     "    </pieces>"
+     "    <pieces length=\"1024\" type=\"sha1\">"
+     "      <hash piece=\"0\">44213f9f4d59b557314fadcd233232eebcac8012</hash>"
+     "    </pieces>"
+     "  </verification>"
+     "</file>"
+     "</files>"
+     "</metalink>");
 
   try {
     SharedHandle<Metalinker> m = proc.parseFromBinaryStream(dw);
@@ -915,20 +960,21 @@ void MetalinkProcessorTest::testUnsupportedType_piece()
 {
   MetalinkProcessor proc;
   SharedHandle<ByteArrayDiskWriter> dw(new ByteArrayDiskWriter());
-  dw->setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
-                "<files>"
-                "<file name=\"aria2.tar.bz2\">"
-                "  <verification>"
-                "    <pieces length=\"512\" type=\"ARIA2\">"
-                "      <hash piece=\"0\">abc</hash>"
-                "    </pieces>"
-                "    <pieces length=\"1024\" type=\"sha1\">"
-                "      <hash piece=\"0\">abc</hash>"
-                "    </pieces>"
-                "  </verification>"
-                "</file>"
-                "</files>"
-                "</metalink>");
+  dw->setString
+    ("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
+     "<files>"
+     "<file name=\"aria2.tar.bz2\">"
+     "  <verification>"
+     "    <pieces length=\"512\" type=\"ARIA2\">"
+     "      <hash piece=\"0\">44213f9f4d59b557314fadcd233232eebcac8012</hash>"
+     "    </pieces>"
+     "    <pieces length=\"1024\" type=\"sha1\">"
+     "      <hash piece=\"0\">44213f9f4d59b557314fadcd233232eebcac8012</hash>"
+     "    </pieces>"
+     "  </verification>"
+     "</file>"
+     "</files>"
+     "</metalink>");
 
   try {
     SharedHandle<Metalinker> m = proc.parseFromBinaryStream(dw);

+ 8 - 8
test/metalink4.xml

@@ -7,17 +7,17 @@
     <version>1.0</version>
     <language>en</language>
     <description>A description of the example file for download.</description>
-    <hash type="md5">80bc95fd391772fa61c91ed68567f0980bb45fd9</hash>
-    <hash type="sha-1">80bc95fd391772fa61c91ed68567f0980bb45fd9</hash>
+    <hash type="md5">cbd18db4cc2f85cedef654fccc4a4d8</hash>
+    <hash type="sha-1">0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33</hash>
     <pieces length="262144" type="sha-1">
-      <hash>metalinkhash1</hash>
-      <hash>metalinkhash2</hash>
-      <hash>metalinkhash3</hash>
+      <hash>5bd9f7248df0f3a6a86ab6c95f48787d546efa14</hash>
+      <hash>9413ee70957a09d55704123687478e07f18c7b29</hash>
+      <hash>44213f9f4d59b557314fadcd233232eebcac8012</hash>
     </pieces>
     <pieces length="262144" type="sha-256">
-      <hash>metalinkhash1</hash>
-      <hash>metalinkhash2</hash>
-      <hash>metalinkhash3</hash>
+      <hash>0245178074fd042e19b7c3885b360fc21064b30e73f5626c7e3b005d048069c5</hash>
+      <hash>487ba2299be7f759d7c7bf6a4ac3a32cee81f1bb9332fc485947e32918864fb2</hash>
+      <hash>37290d74ac4d186e3a8e5785d259d2ec04fac91ae28092e7620ec8bc99e830aa</hash>
     </pieces>
     <url location="de" priority="1">ftp://ftp.example.com/example.ext</url>
     <url location="fr" priority="1">http://example.com/example.ext</url>