Ignore floating number in torrent file

pull/599/head
Tatsuhiro Tsujikawa 2016-03-17 23:28:28 +09:00
parent 9b607bbae0
commit f316c94710
3 changed files with 52 additions and 3 deletions

View File

@ -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;

View File

@ -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 {

View File

@ -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";