From 8678e1f380a4bd1d964d04f4ed4ad6d7373279ea Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sat, 26 Apr 2008 07:43:01 +0000 Subject: [PATCH] 2008-04-26 Tatsuhiro Tsujikawa Fixed the bug that causes segmentaion fault when reading XML containing unescapsed character like '&'. Also a modification was made which avoids adding unnecessary characters stack and appending unused string. * src/ExpatMetalinkProcessor.cc * src/FileMetalinkParserState.h * src/FilesMetalinkParserState.h * src/FinMetalinkParserState.h * src/HashMetalinkParserState.h * src/InitialMetalinkParserState.h * src/LanguageMetalinkParserState.h * src/MetalinkMetalinkParserState.h * src/MetalinkParserState.h * src/MetalinkParserStateMachine.cc * src/MetalinkParserStateMachine.h * src/OSMetalinkParserState.h * src/PieceHashMetalinkParserState.h * src/PiecesMetalinkParserState.h * src/ResourcesMetalinkParserState.h * src/SizeMetalinkParserState.h * src/SkipTagMetalinkParserState.h * src/URLMetalinkParserState.h * src/VerificationMetalinkParserState.h * src/VersionMetalinkParserState.h * src/XML2SAXMetalinkProcessor.cc --- ChangeLog | 28 +++++++++++++++++++++++++++ src/ExpatMetalinkProcessor.cc | 24 ++++++++++++++++------- src/FileMetalinkParserState.h | 5 +++++ src/FilesMetalinkParserState.h | 5 +++++ src/FinMetalinkParserState.h | 5 +++++ src/HashMetalinkParserState.h | 5 +++++ src/InitialMetalinkParserState.h | 5 +++++ src/LanguageMetalinkParserState.h | 5 +++++ src/MetalinkMetalinkParserState.h | 5 +++++ src/MetalinkParserState.h | 2 ++ src/MetalinkParserStateMachine.cc | 5 +++++ src/MetalinkParserStateMachine.h | 2 ++ src/OSMetalinkParserState.h | 5 +++++ src/PieceHashMetalinkParserState.h | 5 +++++ src/PiecesMetalinkParserState.h | 5 +++++ src/ResourcesMetalinkParserState.h | 5 +++++ src/SizeMetalinkParserState.h | 5 +++++ src/SkipTagMetalinkParserState.h | 5 +++++ src/URLMetalinkParserState.h | 5 +++++ src/VerificationMetalinkParserState.h | 5 +++++ src/VersionMetalinkParserState.h | 5 +++++ src/XML2SAXMetalinkProcessor.cc | 23 +++++++++++++++------- 22 files changed, 150 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3b767fa5..38b5aa95 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2008-04-26 Tatsuhiro Tsujikawa + + Fixed the bug that causes segmentaion fault when reading XML containing + unescapsed character like '&'. + Also a modification was made which avoids adding unnecessary + characters stack and appending unused string. + * src/ExpatMetalinkProcessor.cc + * src/FileMetalinkParserState.h + * src/FilesMetalinkParserState.h + * src/FinMetalinkParserState.h + * src/HashMetalinkParserState.h + * src/InitialMetalinkParserState.h + * src/LanguageMetalinkParserState.h + * src/MetalinkMetalinkParserState.h + * src/MetalinkParserState.h + * src/MetalinkParserStateMachine.cc + * src/MetalinkParserStateMachine.h + * src/OSMetalinkParserState.h + * src/PieceHashMetalinkParserState.h + * src/PiecesMetalinkParserState.h + * src/ResourcesMetalinkParserState.h + * src/SizeMetalinkParserState.h + * src/SkipTagMetalinkParserState.h + * src/URLMetalinkParserState.h + * src/VerificationMetalinkParserState.h + * src/VersionMetalinkParserState.h + * src/XML2SAXMetalinkProcessor.cc + 2008-04-26 Tatsuhiro Tsujikawa Added StringFormat class, which internally calls vasprintf. diff --git a/src/ExpatMetalinkProcessor.cc b/src/ExpatMetalinkProcessor.cc index a27b2a43..fcfbdf9e 100644 --- a/src/ExpatMetalinkProcessor.cc +++ b/src/ExpatMetalinkProcessor.cc @@ -54,7 +54,8 @@ public: static void mlStartElement(void* userData, const char* name, const char** attrs) { - ((SessionData*)userData)->_charactersStack.push_front(std::string()); + SessionData* sd = reinterpret_cast(userData); + std::map attrmap; if(attrs) { const char** p = attrs; @@ -67,20 +68,29 @@ static void mlStartElement(void* userData, const char* name, const char** attrs) attrmap[name] = value; } } - ((SessionData*)userData)->_stm->beginElement(name, attrmap); + sd->_stm->beginElement(name, attrmap); + if(sd->_stm->needsCharactersBuffering()) { + sd->_charactersStack.push_front(std::string()); + } } static void mlEndElement(void* userData, const char* name) { - SessionData* sd = (SessionData*)userData; - - sd->_stm->endElement(name, Util::trim(sd->_charactersStack.front())); - sd->_charactersStack.pop_front(); + SessionData* sd = reinterpret_cast(userData); + std::string characters; + if(sd->_stm->needsCharactersBuffering()) { + characters = Util::trim(sd->_charactersStack.front()); + sd->_charactersStack.pop_front(); + } + sd->_stm->endElement(name, characters); } static void mlCharacters(void* userData, const char* ch, int len) { - ((SessionData*)userData)->_charactersStack.front() += std::string(&ch[0], &ch[len]); + SessionData* sd = reinterpret_cast(userData); + if(sd->_stm->needsCharactersBuffering()) { + sd->_charactersStack.front() += std::string(&ch[0], &ch[len]); + } } ExpatMetalinkProcessor::ExpatMetalinkProcessor() {} diff --git a/src/FileMetalinkParserState.h b/src/FileMetalinkParserState.h index 76035eb9..55d87957 100644 --- a/src/FileMetalinkParserState.h +++ b/src/FileMetalinkParserState.h @@ -47,6 +47,11 @@ public: void endElement(MetalinkParserStateMachine* stm, const std::string& name, const std::string& characters); + + virtual bool needsCharactersBuffering() const + { + return true; + } }; } // namespace aria2 diff --git a/src/FilesMetalinkParserState.h b/src/FilesMetalinkParserState.h index f0394bab..8cb6b61e 100644 --- a/src/FilesMetalinkParserState.h +++ b/src/FilesMetalinkParserState.h @@ -47,6 +47,11 @@ public: void endElement(MetalinkParserStateMachine* stm, const std::string& name, const std::string& characters); + + virtual bool needsCharactersBuffering() const + { + return true; + } }; } // namespace aria2 diff --git a/src/FinMetalinkParserState.h b/src/FinMetalinkParserState.h index 6f0b827d..25cfde48 100644 --- a/src/FinMetalinkParserState.h +++ b/src/FinMetalinkParserState.h @@ -47,6 +47,11 @@ public: void endElement(MetalinkParserStateMachine* stm, const std::string& name, const std::string& characters); + + virtual bool needsCharactersBuffering() const + { + return false; + } }; } // namespace aria2 diff --git a/src/HashMetalinkParserState.h b/src/HashMetalinkParserState.h index 2c187871..4e278083 100644 --- a/src/HashMetalinkParserState.h +++ b/src/HashMetalinkParserState.h @@ -47,6 +47,11 @@ public: void endElement(MetalinkParserStateMachine* stm, const std::string& name, const std::string& characters); + + virtual bool needsCharactersBuffering() const + { + return true; + } }; } // namespace aria2 diff --git a/src/InitialMetalinkParserState.h b/src/InitialMetalinkParserState.h index 12c5050c..d2318742 100644 --- a/src/InitialMetalinkParserState.h +++ b/src/InitialMetalinkParserState.h @@ -47,6 +47,11 @@ public: void endElement(MetalinkParserStateMachine* stm, const std::string& name, const std::string& characters); + + virtual bool needsCharactersBuffering() const + { + return false; + } }; } // namespace aria2 diff --git a/src/LanguageMetalinkParserState.h b/src/LanguageMetalinkParserState.h index 2961b8d2..67a0cc86 100644 --- a/src/LanguageMetalinkParserState.h +++ b/src/LanguageMetalinkParserState.h @@ -47,6 +47,11 @@ public: void endElement(MetalinkParserStateMachine* stm, const std::string& name, const std::string& characters); + + virtual bool needsCharactersBuffering() const + { + return true; + } }; } // namespace aria2 diff --git a/src/MetalinkMetalinkParserState.h b/src/MetalinkMetalinkParserState.h index e095c127..c5cc7fbc 100644 --- a/src/MetalinkMetalinkParserState.h +++ b/src/MetalinkMetalinkParserState.h @@ -47,6 +47,11 @@ public: void endElement(MetalinkParserStateMachine* stm, const std::string& name, const std::string& characters); + + virtual bool needsCharactersBuffering() const + { + return false; + } }; } // namespace aria2 diff --git a/src/MetalinkParserState.h b/src/MetalinkParserState.h index 59c69c00..5d82a86a 100644 --- a/src/MetalinkParserState.h +++ b/src/MetalinkParserState.h @@ -51,6 +51,8 @@ public: virtual void endElement(MetalinkParserStateMachine* stm, const std::string& name, const std::string& characters) = 0; + + virtual bool needsCharactersBuffering() const = 0; }; } // namespace aria2 diff --git a/src/MetalinkParserStateMachine.cc b/src/MetalinkParserStateMachine.cc index c623b4d5..e0d368f5 100644 --- a/src/MetalinkParserStateMachine.cc +++ b/src/MetalinkParserStateMachine.cc @@ -324,6 +324,11 @@ void MetalinkParserStateMachine::endElement(const std::string& name, const std:: _state->endElement(this, name, characters); } +bool MetalinkParserStateMachine::needsCharactersBuffering() const +{ + return _state->needsCharactersBuffering(); +} + SharedHandle MetalinkParserStateMachine::getResult() const { return _ctrl->getResult(); diff --git a/src/MetalinkParserStateMachine.h b/src/MetalinkParserStateMachine.h index 174774f4..00b26f5d 100644 --- a/src/MetalinkParserStateMachine.h +++ b/src/MetalinkParserStateMachine.h @@ -173,6 +173,8 @@ public: void cancelChunkChecksumTransaction(); + bool needsCharactersBuffering() const; + SharedHandle getResult() const; }; diff --git a/src/OSMetalinkParserState.h b/src/OSMetalinkParserState.h index cf6fec3a..87a738af 100644 --- a/src/OSMetalinkParserState.h +++ b/src/OSMetalinkParserState.h @@ -47,6 +47,11 @@ public: void endElement(MetalinkParserStateMachine* stm, const std::string& name, const std::string& characters); + + virtual bool needsCharactersBuffering() const + { + return true; + } }; } // namespace aria2 diff --git a/src/PieceHashMetalinkParserState.h b/src/PieceHashMetalinkParserState.h index 28bf3094..b980b08c 100644 --- a/src/PieceHashMetalinkParserState.h +++ b/src/PieceHashMetalinkParserState.h @@ -47,6 +47,11 @@ public: void endElement(MetalinkParserStateMachine* stm, const std::string& name, const std::string& characters); + + virtual bool needsCharactersBuffering() const + { + return true; + } }; } // namespace aria2 diff --git a/src/PiecesMetalinkParserState.h b/src/PiecesMetalinkParserState.h index 68e16e30..0ad10110 100644 --- a/src/PiecesMetalinkParserState.h +++ b/src/PiecesMetalinkParserState.h @@ -47,6 +47,11 @@ public: void endElement(MetalinkParserStateMachine* stm, const std::string& name, const std::string& characters); + + virtual bool needsCharactersBuffering() const + { + return true; + } }; } // namespace aria2 diff --git a/src/ResourcesMetalinkParserState.h b/src/ResourcesMetalinkParserState.h index 13372472..4333d497 100644 --- a/src/ResourcesMetalinkParserState.h +++ b/src/ResourcesMetalinkParserState.h @@ -47,6 +47,11 @@ public: void endElement(MetalinkParserStateMachine* stm, const std::string& name, const std::string& characters); + + virtual bool needsCharactersBuffering() const + { + return true; + } }; } // namespace aria2 diff --git a/src/SizeMetalinkParserState.h b/src/SizeMetalinkParserState.h index f9820b02..45f8ef92 100644 --- a/src/SizeMetalinkParserState.h +++ b/src/SizeMetalinkParserState.h @@ -47,6 +47,11 @@ public: void endElement(MetalinkParserStateMachine* stm, const std::string& name, const std::string& characters); + + virtual bool needsCharactersBuffering() const + { + return true; + } }; } // namespace aria2 diff --git a/src/SkipTagMetalinkParserState.h b/src/SkipTagMetalinkParserState.h index fe547a68..244814e0 100644 --- a/src/SkipTagMetalinkParserState.h +++ b/src/SkipTagMetalinkParserState.h @@ -53,6 +53,11 @@ public: void endElement(MetalinkParserStateMachine* stm, const std::string& name, const std::string& characters); + virtual bool needsCharactersBuffering() const + { + return false; + } + MetalinkParserState* getPreviousState() const { return _prevState; diff --git a/src/URLMetalinkParserState.h b/src/URLMetalinkParserState.h index 4c35261a..25c604a4 100644 --- a/src/URLMetalinkParserState.h +++ b/src/URLMetalinkParserState.h @@ -47,6 +47,11 @@ public: void endElement(MetalinkParserStateMachine* stm, const std::string& name, const std::string& characters); + + virtual bool needsCharactersBuffering() const + { + return true; + } }; } // namespace aria2 diff --git a/src/VerificationMetalinkParserState.h b/src/VerificationMetalinkParserState.h index cae02ff2..97808b91 100644 --- a/src/VerificationMetalinkParserState.h +++ b/src/VerificationMetalinkParserState.h @@ -47,6 +47,11 @@ public: void endElement(MetalinkParserStateMachine* stm, const std::string& name, const std::string& characters); + + virtual bool needsCharactersBuffering() const + { + return true; + } }; } // namespace aria2 diff --git a/src/VersionMetalinkParserState.h b/src/VersionMetalinkParserState.h index 2b6b74ce..c6b88dcd 100644 --- a/src/VersionMetalinkParserState.h +++ b/src/VersionMetalinkParserState.h @@ -47,6 +47,11 @@ public: void endElement(MetalinkParserStateMachine* stm, const std::string& name, const std::string& characters); + + virtual bool needsCharactersBuffering() const + { + return true; + } }; } // namespace aria2 diff --git a/src/XML2SAXMetalinkProcessor.cc b/src/XML2SAXMetalinkProcessor.cc index 0e2c7cf1..f6740ac7 100644 --- a/src/XML2SAXMetalinkProcessor.cc +++ b/src/XML2SAXMetalinkProcessor.cc @@ -54,7 +54,7 @@ public: static void mlStartElement(void* userData, const xmlChar* name, const xmlChar** attrs) { - ((SessionData*)userData)->_charactersStack.push_front(std::string()); + SessionData* sd = reinterpret_cast(userData); std::map attrmap; if(attrs) { const xmlChar** p = attrs; @@ -67,20 +67,29 @@ static void mlStartElement(void* userData, const xmlChar* name, const xmlChar** attrmap[name] = value; } } - ((SessionData*)userData)->_stm->beginElement((const char*)name, attrmap); + sd->_stm->beginElement((const char*)name, attrmap); + if(sd->_stm->needsCharactersBuffering()) { + sd->_charactersStack.push_front(std::string()); + } } static void mlEndElement(void* userData, const xmlChar* name) { - SessionData* sd = (SessionData*)userData; - - sd->_stm->endElement((const char*)name, Util::trim(sd->_charactersStack.front())); - sd->_charactersStack.pop_front(); + SessionData* sd = reinterpret_cast(userData); + std::string characters; + if(sd->_stm->needsCharactersBuffering()) { + characters = Util::trim(sd->_charactersStack.front()); + sd->_charactersStack.pop_front(); + } + sd->_stm->endElement((const char*)name, characters); } static void mlCharacters(void* userData, const xmlChar* ch, int len) { - ((SessionData*)userData)->_charactersStack.front() += std::string(&ch[0], &ch[len]); + SessionData* sd = reinterpret_cast(userData); + if(sd->_stm->needsCharactersBuffering()) { + sd->_charactersStack.front() += std::string(&ch[0], &ch[len]); + } } static xmlSAXHandler mySAXHandler =