Browse Source

Ignore floating number in torrent file

Tatsuhiro Tsujikawa 9 năm trước cách đây
mục cha
commit
f316c94710
3 tập tin đã thay đổi với 52 bổ sung3 xóa
  1. 38 2
      src/BencodeParser.cc
  2. 2 1
      src/BencodeParser.h
  3. 12 0
      test/ValueBaseBencodeParserTest.cc

+ 38 - 2
src/BencodeParser.cc

@@ -55,7 +55,8 @@ enum {
   BENCODE_STRING_LEN,
   BENCODE_STRING,
   BENCODE_NUMBER_SIGN,
-  BENCODE_NUMBER
+  BENCODE_NUMBER,
+  BENCODE_FLOAT_NUMBER_IGNORE,
 };
 } // namespace
 
@@ -216,11 +217,32 @@ ssize_t BencodeParser::parseUpdate(const char* data, size_t size)
       }
       numConsumed_ += j - i;
       if (j != size) {
-        if (data[j] != 'e' || numConsumed_ == 0) {
+        if (numConsumed_ == 0) {
           currentState_ = BENCODE_ERROR;
           return lastError_ = ERR_INVALID_NUMBER;
         }
+
+        auto c = data[j];
+        if (util::isDigit(c) || c == '.' || c == 'E' || c == '+' || c == '-') {
+          // some torrent generator adds floating point number in
+          // scientific notation (e.g., -1.134E+3) in integer field.
+          // In this case, just skip these bytes until we find 'e'.
+          number_ = 0;
+          numConsumed_ = 0;
+          currentState_ = BENCODE_FLOAT_NUMBER_IGNORE;
+
+          i = j;
+
+          break;
+        }
+
+        if (c != 'e') {
+          currentState_ = BENCODE_ERROR;
+          return lastError_ = ERR_INVALID_NUMBER;
+        }
+
         i = j;
+
         onNumberEnd();
       }
       else {
@@ -228,6 +250,20 @@ ssize_t BencodeParser::parseUpdate(const char* data, size_t size)
       }
       break;
     }
+    case BENCODE_FLOAT_NUMBER_IGNORE: {
+      auto c = data[i];
+      if (util::isDigit(c) || c == '.' || c == 'E' || c == '+' || c == '-') {
+        continue;
+      }
+
+      if (c != 'e') {
+        currentState_ = BENCODE_ERROR;
+        return lastError_ = ERR_INVALID_FLOAT_NUMBER;
+      }
+
+      onNumberEnd();
+      break;
+    }
     }
   }
   return i;

+ 2 - 1
src/BencodeParser.h

@@ -52,7 +52,8 @@ enum BencodeError {
   ERR_PREMATURE_DATA = -4,
   ERR_STRUCTURE_TOO_DEEP = -5,
   ERR_INVALID_STRING_LENGTH = -6,
-  ERR_STRING_LENGTH_OUT_OF_RANGE = -7
+  ERR_STRING_LENGTH_OUT_OF_RANGE = -7,
+  ERR_INVALID_FLOAT_NUMBER = -8,
 };
 
 class BencodeParser {

+ 12 - 0
test/ValueBaseBencodeParserTest.cc

@@ -3,6 +3,7 @@
 #include <cppunit/extensions/HelperMacros.h>
 
 #include "ValueBase.h"
+#include "BencodeParser.h"
 
 namespace aria2 {
 
@@ -77,6 +78,12 @@ void ValueBaseBencodeParserTest::testParseUpdate()
     CPPUNIT_ASSERT_EQUAL((int64_t)9223372036854775807LL,
                          downcast<Integer>(s)->i());
   }
+  {
+    // float number, ignored and always 0.
+    std::string src = "i+343243.342E-1333e";
+    auto s = parser.parseFinal(src.c_str(), src.size(), error);
+    CPPUNIT_ASSERT_EQUAL((int64_t)0, downcast<Integer>(s)->i());
+  }
   {
     // dict, size 1
     std::string src = "d3:fooi123ee";
@@ -187,6 +194,11 @@ void ValueBaseBencodeParserTest::testParseUpdate()
   checkDecodeError(std::string(51, 'l') + std::string(51, 'e'));
   checkDecodeError(std::string(50, 'l') + "d3:fooi100ee" +
                    std::string(50, 'e'));
+  // float number, but including bad characters
+  checkDecodeError("i-1.134a+33e");
+  checkDecodeError("ixe");
+  // empty number
+  checkDecodeError("ie");
   {
     // ignore trailing garbage at the end of the input.
     std::string src = "5:aria2trail";