Merge pull request #1905 from aria2/bt-bencode-allow-empty-dict-name

Allow empty dist name in bencode which is needed for hybrid torrent
pull/1907/head
Tatsuhiro Tsujikawa 2022-04-08 23:29:13 +09:00 committed by GitHub
commit 998f203288
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 41 additions and 5 deletions

View File

@ -42,9 +42,14 @@
namespace aria2 { namespace aria2 {
template <typename Parser, typename ParserStateMachine> class GenericParser { template <typename Parser, typename ParserStateMachine,
bool allowEmptyName = false>
class GenericParser {
public: public:
GenericParser() : parser_{&psm_} {} GenericParser() : parser_{&psm_}
{
psm_.setAllowEmptyMemberName(allowEmptyName);
}
~GenericParser() = default; ~GenericParser() = default;

View File

@ -43,7 +43,7 @@ namespace aria2 {
namespace bittorrent { namespace bittorrent {
typedef GenericParser<BencodeParser, ValueBaseStructParserStateMachine> typedef GenericParser<BencodeParser, ValueBaseStructParserStateMachine, true>
ValueBaseBencodeParser; ValueBaseBencodeParser;
} // namespace bittorrent } // namespace bittorrent

View File

@ -213,4 +213,9 @@ void ValueBaseStructParserStateMachine::pushNullState()
stateStack_.push(nullState); stateStack_.push(nullState);
} }
void ValueBaseStructParserStateMachine::setAllowEmptyMemberName(bool b)
{
ctrl_->setAllowEmptyMemberName(b);
}
} // namespace aria2 } // namespace aria2

View File

@ -106,6 +106,8 @@ public:
void pushBoolState(); void pushBoolState();
void pushNullState(); void pushNullState();
void setAllowEmptyMemberName(bool b);
private: private:
std::unique_ptr<rpc::XmlRpcRequestParserController> ctrl_; std::unique_ptr<rpc::XmlRpcRequestParserController> ctrl_;
std::stack<ValueBaseStructParserState*> stateStack_; std::stack<ValueBaseStructParserState*> stateStack_;

View File

@ -54,7 +54,7 @@ void XmlRpcRequestParserController::popStructFrame()
Dict* dict = downcast<Dict>(parentFrame.value_); Dict* dict = downcast<Dict>(parentFrame.value_);
assert(dict); assert(dict);
frameStack_.pop(); frameStack_.pop();
if (currentFrame_.validMember()) { if (currentFrame_.validMember(allowEmptyMemberName_)) {
dict->put(std::move(currentFrame_.name_), std::move(currentFrame_.value_)); dict->put(std::move(currentFrame_.name_), std::move(currentFrame_.value_));
} }
currentFrame_ = std::move(parentFrame); currentFrame_ = std::move(parentFrame);
@ -110,6 +110,11 @@ void XmlRpcRequestParserController::setMethodName(std::string methodName)
methodName_ = std::move(methodName); methodName_ = std::move(methodName);
} }
void XmlRpcRequestParserController::setAllowEmptyMemberName(bool b)
{
allowEmptyMemberName_ = b;
}
} // namespace rpc } // namespace rpc
} // namespace aria2 } // namespace aria2

View File

@ -52,7 +52,10 @@ private:
std::unique_ptr<ValueBase> value_; std::unique_ptr<ValueBase> value_;
std::string name_; std::string name_;
bool validMember() const { return value_ && !name_.empty(); } bool validMember(bool allowEmptyMemberName) const
{
return value_ && (allowEmptyMemberName || !name_.empty());
}
void reset() void reset()
{ {
@ -67,7 +70,11 @@ private:
std::string methodName_; std::string methodName_;
bool allowEmptyMemberName_;
public: public:
XmlRpcRequestParserController() : allowEmptyMemberName_(false) {}
void pushFrame(); void pushFrame();
// Pops StateFrame p from frameStack_ and set p[currentFrame_.name_] // Pops StateFrame p from frameStack_ and set p[currentFrame_.name_]
@ -90,6 +97,8 @@ public:
const std::string& getMethodName() const { return methodName_; } const std::string& getMethodName() const { return methodName_; }
void setAllowEmptyMemberName(bool b);
void reset(); void reset();
}; };

View File

@ -208,6 +208,16 @@ void ValueBaseBencodeParserTest::testParseUpdate()
// Get trailing garbage position // Get trailing garbage position
CPPUNIT_ASSERT_EQUAL((ssize_t)7, error); CPPUNIT_ASSERT_EQUAL((ssize_t)7, error);
} }
{
// dict, empty member name
std::string src = "d0:i123ee";
std::shared_ptr<ValueBase> d =
parser.parseFinal(src.c_str(), src.size(), error);
Dict* dict = downcast<Dict>(d);
CPPUNIT_ASSERT(dict);
CPPUNIT_ASSERT(dict->get(""));
CPPUNIT_ASSERT_EQUAL((int64_t)123, downcast<Integer>(dict->get(""))->i());
}
} }
} // namespace aria2 } // namespace aria2