summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2016-03-17 23:28:28 +0900
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2016-03-17 23:28:28 +0900
commitf316c947100f7683f4ca9ba1c71bb1446433dbb4 (patch)
tree185ac72d1440f26570b52ba0fb4942deb792b545
parent9b607bbae0b397fffc53339aae36e9f8547cfd12 (diff)
Ignore floating number in torrent file
-rw-r--r--src/BencodeParser.cc40
-rw-r--r--src/BencodeParser.h3
-rw-r--r--test/ValueBaseBencodeParserTest.cc12
3 files changed, 52 insertions, 3 deletions
diff --git a/src/BencodeParser.cc b/src/BencodeParser.cc
index f5423072..08d36b21 100644
--- a/src/BencodeParser.cc
+++ b/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;
diff --git a/src/BencodeParser.h b/src/BencodeParser.h
index c6b7debd..7ef697c1 100644
--- a/src/BencodeParser.h
+++ b/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 {
diff --git a/test/ValueBaseBencodeParserTest.cc b/test/ValueBaseBencodeParserTest.cc
index a24af6d3..30cca2f4 100644
--- a/test/ValueBaseBencodeParserTest.cc
+++ b/test/ValueBaseBencodeParserTest.cc
@@ -3,6 +3,7 @@
#include <cppunit/extensions/HelperMacros.h>
#include "ValueBase.h"
+#include "BencodeParser.h"
namespace aria2 {
@@ -78,6 +79,12 @@ void ValueBaseBencodeParserTest::testParseUpdate()
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";
std::shared_ptr<ValueBase> d =
@@ -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";