Переглянути джерело

2010-01-09 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Fixed the bug that causes segmentation fault if unknown option is
	put in aria2.conf file. BUG#2928303
	* src/OptionParser.cc
	* src/OptionParser.h
	* src/option_processing.cc
	* test/OptionParserTest.cc
Tatsuhiro Tsujikawa 15 роки тому
батько
коміт
d56459bb88
5 змінених файлів з 48 додано та 8 видалено
  1. 9 0
      ChangeLog
  2. 13 4
      src/OptionParser.cc
  3. 3 0
      src/OptionParser.h
  4. 7 4
      src/option_processing.cc
  5. 16 0
      test/OptionParserTest.cc

+ 9 - 0
ChangeLog

@@ -1,3 +1,12 @@
+2010-01-09  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Fixed the bug that causes segmentation fault if unknown option is
+	put in aria2.conf file. BUG#2928303
+	* src/OptionParser.cc
+	* src/OptionParser.h
+	* src/option_processing.cc
+	* test/OptionParserTest.cc
+
 2010-01-07  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Ignore port message with port=0.

+ 13 - 4
src/OptionParser.cc

@@ -48,10 +48,15 @@
 #include "a2functional.h"
 #include "array_fun.h"
 #include "OptionHandlerFactory.h"
+#include "Logger.h"
+#include "LogFactory.h"
 
 namespace aria2 {
 
-OptionParser::OptionParser():_idCounter(0) {}
+OptionParser::OptionParser():
+  _idCounter(0),
+  _logger(LogFactory::getInstance())
+{}
 
 template<typename InputIterator>
 static size_t countPublicOption(InputIterator first, InputIterator last)
@@ -167,6 +172,9 @@ void OptionParser::parse(Option& option, std::istream& is)
       continue;
     }
     std::pair<std::string, std::string> nv = util::split(line, A2STR::EQUAL_C);
+    if(nv.first.empty()) {
+      continue;
+    }
     OptionHandlerHandle handler = getOptionHandlerByName(nv.first);
     handler->parse(option, nv.second);
   }
@@ -191,10 +199,11 @@ OptionHandlerHandle OptionParser::getOptionHandlerByName
   std::vector<SharedHandle<OptionHandler> >::const_iterator i =
     std::lower_bound(_optionHandlers.begin(), _optionHandlers.end(),
                      handler, OptionHandlerNameLesser());
-  if(i == _optionHandlers.end()) {
-    handler.reset(new NullOptionHandler());
-  } else {
+  if(i != _optionHandlers.end() && (*i)->canHandle(optName)) {
     handler = *i;
+  } else {
+    handler.reset(new NullOptionHandler());
+    _logger->warn("Skipped unknown option --%s.", optName.c_str());
   }
   return handler;
 }

+ 3 - 0
src/OptionParser.h

@@ -48,11 +48,14 @@ namespace aria2 {
 
 class Option;
 class OptionHandler;
+class Logger;
 
 class OptionParser {
 private:
   int _idCounter;
 
+  Logger* _logger;
+
   // _optionHandlers is sorted by OptionHandler::getName() in
   // ascending order.
   std::vector<SharedHandle<OptionHandler> > _optionHandlers;

+ 7 - 4
src/option_processing.cc

@@ -136,10 +136,13 @@ void option_processing(Option& op, std::deque<std::string>& uris,
           oparser.parse(op, cfstream);
         } catch(OptionHandlerException& e) {
           std::cerr << "Parse error in " << cfname << "\n"
-                    << e.stackTrace() << "\n"
-                    << "Usage:" << "\n"
-                    << oparser.findByName(e.getOptionName())->getDescription()
-                    << std::endl;
+                    << e.stackTrace() << std::endl;
+          SharedHandle<OptionHandler> h = oparser.findByName(e.getOptionName());
+          if(!h.isNull()) {
+            std::cerr << "Usage:" << "\n"
+                      << oparser.findByName(e.getOptionName())->getDescription()
+                      << std::endl;
+          }
           exit(downloadresultcode::UNKNOWN_ERROR);
         } catch(Exception& e) {
           std::cerr << "Parse error in " << cfname << "\n"

+ 16 - 0
test/OptionParserTest.cc

@@ -24,6 +24,7 @@ class OptionParserTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testFindByID);
   CPPUNIT_TEST(testParseDefaultValues);
   CPPUNIT_TEST(testParseArg);
+  CPPUNIT_TEST(testParse);
   CPPUNIT_TEST_SUITE_END();
 private:
   SharedHandle<OptionParser> _oparser;
@@ -67,6 +68,7 @@ public:
   void testFindByID();
   void testParseDefaultValues();
   void testParseArg();
+  void testParse();
 };
 
 
@@ -174,4 +176,18 @@ void OptionParserTest::testParseArg()
   CPPUNIT_ASSERT_EQUAL(std::string("nonopt2"), nonopts[1]);
 }
 
+void OptionParserTest::testParse()
+{
+  Option option;
+  std::istringstream in("alpha=Hello\n"
+                        "UNKNOWN=x\n"
+                        "\n"
+                        "bravo=World");
+  _oparser->parse(option, in);
+  CPPUNIT_ASSERT_EQUAL
+    ((ptrdiff_t)2, std::distance(option.begin(), option.end()));
+  CPPUNIT_ASSERT_EQUAL(std::string("Hello"), option.get("alpha"));
+  CPPUNIT_ASSERT_EQUAL(std::string("World"), option.get("bravo"));
+}
+
 } // namespace aria2