2009-12-25 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

Check structure depth when decoding.
	* src/bencode.cc
	* src/bencode.h
	* test/BencodeTest.cc
pull/1/head
Tatsuhiro Tsujikawa 2009-12-25 14:53:11 +00:00
parent 49bd2c1b92
commit 838fcbbecd
4 changed files with 47 additions and 10 deletions

View File

@ -1,3 +1,10 @@
2009-12-25 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Check structure depth when decoding.
* src/bencode.cc
* src/bencode.h
* test/BencodeTest.cc
2009-12-25 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net> 2009-12-25 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Documented tellStopped XML-RPC method in man page. Documented tellStopped XML-RPC method in man page.

View File

@ -44,7 +44,7 @@ namespace aria2 {
namespace bencode { namespace bencode {
static BDE decodeiter(std::istream& ss); static BDE decodeiter(std::istream& ss, size_t depth);
static void checkdelim(std::istream& ss, const char delim = ':') static void checkdelim(std::istream& ss, const char delim = ':')
{ {
@ -96,7 +96,7 @@ static BDE decodeinteger(std::istream& ss)
return BDE(integer); return BDE(integer);
} }
static BDE decodedict(std::istream& ss) static BDE decodedict(std::istream& ss, size_t depth)
{ {
BDE dict = BDE::dict(); BDE dict = BDE::dict();
char c; char c;
@ -106,14 +106,14 @@ static BDE decodedict(std::istream& ss)
} else { } else {
ss.unget(); ss.unget();
std::string key = decoderawstring(ss); std::string key = decoderawstring(ss);
dict[key] = decodeiter(ss); dict[key] = decodeiter(ss, depth);
} }
} }
throw DL_ABORT_EX("Bencode decoding failed:" throw DL_ABORT_EX("Bencode decoding failed:"
" Unexpected EOF in dict context. 'e' expected."); " Unexpected EOF in dict context. 'e' expected.");
} }
static BDE decodelist(std::istream& ss) static BDE decodelist(std::istream& ss, size_t depth)
{ {
BDE list = BDE::list(); BDE list = BDE::list();
char c; char c;
@ -122,15 +122,23 @@ static BDE decodelist(std::istream& ss)
return list; return list;
} else { } else {
ss.unget(); ss.unget();
list << decodeiter(ss); list << decodeiter(ss, depth);
} }
} }
throw DL_ABORT_EX("Bencode decoding failed:" throw DL_ABORT_EX("Bencode decoding failed:"
" Unexpected EOF in list context. 'e' expected."); " Unexpected EOF in list context. 'e' expected.");
} }
static BDE decodeiter(std::istream& ss) static void checkDepth(size_t depth)
{ {
if(depth >= MAX_STRUCTURE_DEPTH) {
throw DL_ABORT_EX("Bencode decoding failed: Structure is too deep.");
}
}
static BDE decodeiter(std::istream& ss, size_t depth)
{
checkDepth(depth);
char c; char c;
if(!ss.get(c)) { if(!ss.get(c)) {
throw DL_ABORT_EX("Bencode decoding failed:" throw DL_ABORT_EX("Bencode decoding failed:"
@ -138,9 +146,9 @@ static BDE decodeiter(std::istream& ss)
" 'd', 'l', 'i' or digit is expected."); " 'd', 'l', 'i' or digit is expected.");
} }
if(c == 'd') { if(c == 'd') {
return decodedict(ss); return decodedict(ss, depth+1);
} else if(c == 'l') { } else if(c == 'l') {
return decodelist(ss); return decodelist(ss, depth+1);
} else if(c == 'i') { } else if(c == 'i') {
return decodeinteger(ss); return decodeinteger(ss);
} else { } else {
@ -151,7 +159,7 @@ static BDE decodeiter(std::istream& ss)
BDE decode(std::istream& in) BDE decode(std::istream& in)
{ {
return decodeiter(in); return decodeiter(in, 0);
} }
BDE decode(const std::string& s) BDE decode(const std::string& s)
@ -167,7 +175,7 @@ BDE decode(const std::string& s, size_t& end)
} }
std::istringstream ss(s); std::istringstream ss(s);
BDE bde = decodeiter(ss); BDE bde = decodeiter(ss, 0);
end = ss.tellg(); end = ss.tellg();
return bde; return bde;
} }

View File

@ -46,6 +46,8 @@ namespace aria2 {
namespace bencode { namespace bencode {
const size_t MAX_STRUCTURE_DEPTH = 100;
BDE decode(std::istream& in); BDE decode(std::istream& in);
// Decode the data in s. // Decode the data in s.

View File

@ -10,12 +10,14 @@ class BencodeTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(BencodeTest); CPPUNIT_TEST_SUITE(BencodeTest);
CPPUNIT_TEST(testDecode); CPPUNIT_TEST(testDecode);
CPPUNIT_TEST(testDecode_overflow);
CPPUNIT_TEST(testEncode); CPPUNIT_TEST(testEncode);
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
private: private:
public: public:
void testDecode(); void testDecode();
void testDecode_overflow();
void testEncode(); void testEncode();
}; };
@ -155,6 +157,24 @@ void BencodeTest::testDecode()
} }
} }
void BencodeTest::testDecode_overflow()
{
std::string s;
size_t depth = bencode::MAX_STRUCTURE_DEPTH+1;
for(size_t i = 0; i < depth; ++i) {
s += "l";
}
for(size_t i = 0; i < depth; ++i) {
s += "e";
}
try {
bencode::decode(s);
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {
// success
}
}
void BencodeTest::testEncode() void BencodeTest::testEncode()
{ {
{ {