From 4fc7861cebaa82e5057a7ff7d385b49b79e442a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Mon, 6 Dec 2010 20:22:07 +0100
Subject: Fixed assertion failure on invalid stream start.

Resolves: #707

diff --git a/Swiften/Parser/UnitTest/XMPPParserTest.cpp b/Swiften/Parser/UnitTest/XMPPParserTest.cpp
index 90a4b03..1eaa798 100644
--- a/Swiften/Parser/UnitTest/XMPPParserTest.cpp
+++ b/Swiften/Parser/UnitTest/XMPPParserTest.cpp
@@ -33,6 +33,7 @@ class XMPPParserTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST(testParse_UnknownElement);
 		CPPUNIT_TEST(testParse_StrayCharacterData);
 		CPPUNIT_TEST(testParse_InvalidStreamStart);
+		CPPUNIT_TEST(testParse_ElementEndAfterInvalidStreamStart);
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
@@ -149,6 +150,12 @@ class XMPPParserTest : public CppUnit::TestFixture {
 			CPPUNIT_ASSERT(!testling.parse("<tream>"));
 		}
 
+		void testParse_ElementEndAfterInvalidStreamStart() {
+			XMPPParser testling(&client_, &factories_);
+
+			CPPUNIT_ASSERT(!testling.parse("<tream/>"));
+		}
+
 	private:
 		class Client : public XMPPParserClient {
 			public:
diff --git a/Swiften/Parser/XMPPParser.cpp b/Swiften/Parser/XMPPParser.cpp
index 93797b3..6bd6082 100644
--- a/Swiften/Parser/XMPPParser.cpp
+++ b/Swiften/Parser/XMPPParser.cpp
@@ -67,54 +67,60 @@ bool XMPPParser::parse(const String& data) {
 }
 
 void XMPPParser::handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) {
-	if (level_ == TopLevel) {
-		if (element == "stream" && ns == "http://etherx.jabber.org/streams") {
-			ProtocolHeader header;
-			header.setFrom(attributes.getAttribute("from"));
-			header.setTo(attributes.getAttribute("to"));
-			header.setID(attributes.getAttribute("id"));
-			header.setVersion(attributes.getAttribute("version"));
-			client_->handleStreamStart(header);
+	if (!parseErrorOccurred_) {
+		if (level_ == TopLevel) {
+			if (element == "stream" && ns == "http://etherx.jabber.org/streams") {
+				ProtocolHeader header;
+				header.setFrom(attributes.getAttribute("from"));
+				header.setTo(attributes.getAttribute("to"));
+				header.setID(attributes.getAttribute("id"));
+				header.setVersion(attributes.getAttribute("version"));
+				client_->handleStreamStart(header);
+			}
+			else {
+				parseErrorOccurred_ = true;
+			}
 		}
 		else {
-			parseErrorOccurred_ = true;
+			if (level_ == StreamLevel) {
+				assert(!currentElementParser_);
+				currentElementParser_ = createElementParser(element, ns);
+			}
+			currentElementParser_->handleStartElement(element, ns, attributes);
 		}
 	}
-	else {
-		if (level_ == StreamLevel) {
-			assert(!currentElementParser_);
-			currentElementParser_ = createElementParser(element, ns);
-		}
-		currentElementParser_->handleStartElement(element, ns, attributes);
-	}
 	++level_;
 }
 
 void XMPPParser::handleEndElement(const String& element, const String& ns) {
 	assert(level_ > TopLevel);
 	--level_;
-	if (level_ == TopLevel) {
-		assert(element == "stream");
-		client_->handleStreamEnd();
-	}
-	else {
-		assert(currentElementParser_);
-		currentElementParser_->handleEndElement(element, ns);
-		if (level_ == StreamLevel) {
-			client_->handleElement(currentElementParser_->getElement());
-			delete currentElementParser_;
-			currentElementParser_ = NULL;
+	if (!parseErrorOccurred_) {
+		if (level_ == TopLevel) {
+			assert(element == "stream");
+			client_->handleStreamEnd();
+		}
+		else {
+			assert(currentElementParser_);
+			currentElementParser_->handleEndElement(element, ns);
+			if (level_ == StreamLevel) {
+				client_->handleElement(currentElementParser_->getElement());
+				delete currentElementParser_;
+				currentElementParser_ = NULL;
+			}
 		}
 	}
 }
 
 void XMPPParser::handleCharacterData(const String& data) {
-	if (currentElementParser_) {
-		currentElementParser_->handleCharacterData(data);
-	}
+	if (!parseErrorOccurred_) {
+		if (currentElementParser_) {
+			currentElementParser_->handleCharacterData(data);
+		}
 	//else {
 	//	std::cerr << "XMPPParser: Ignoring stray character data: " << data << std::endl;
 	//}
+	}
 }
 
 ElementParser* XMPPParser::createElementParser(const String& element, const String& ns) {
-- 
cgit v0.10.2-6-g49f6