$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r86705 - in trunk/tools/quickbook: src test test/unit
From: dnljms_at_[hidden]
Date: 2013-11-14 14:23:27
Author: danieljames
Date: 2013-11-14 14:23:26 EST (Thu, 14 Nov 2013)
New Revision: 86705
URL: http://svn.boost.org/trac/boost/changeset/86705
Log:
Validate globs.
Added:
   trunk/tools/quickbook/test/include_invalid_path3-1_7-fail.quickbook   (contents, props changed)
Text files modified: 
   trunk/tools/quickbook/src/glob.cpp                                  |   100 ++++++++++++++++++++++++++++++++++++++++
   trunk/tools/quickbook/src/glob.hpp                                  |    11 ++++                                    
   trunk/tools/quickbook/src/include_paths.cpp                         |    18 +++----                                 
   trunk/tools/quickbook/test/Jamfile.v2                               |     1                                         
   trunk/tools/quickbook/test/include_invalid_path3-1_7-fail.quickbook |     5 ++                                      
   trunk/tools/quickbook/test/unit/glob_test.cpp                       |    25 ++++++++++                              
   6 files changed, 150 insertions(+), 10 deletions(-)
Modified: trunk/tools/quickbook/src/glob.cpp
==============================================================================
--- trunk/tools/quickbook/src/glob.cpp	Thu Nov 14 14:22:48 2013	(r86704)
+++ trunk/tools/quickbook/src/glob.cpp	2013-11-14 14:23:26 EST (Thu, 14 Nov 2013)	(r86705)
@@ -13,11 +13,111 @@
 {
     typedef boost::string_ref::const_iterator glob_iterator;
 
+    void check_glob_range(glob_iterator&, glob_iterator);
+    void check_glob_escape(glob_iterator&, glob_iterator);
+
     bool match_section(glob_iterator& pattern_begin, glob_iterator pattern_end,
             glob_iterator& filename_begin, glob_iterator& filename_end);
     bool match_range(glob_iterator& pattern_begin, glob_iterator pattern_end,
             unsigned char x);
 
+    bool check_glob(boost::string_ref pattern)
+    {
+        bool is_glob = false;
+
+        glob_iterator begin = pattern.begin();
+        glob_iterator end = pattern.end();
+
+        while (begin != end) {
+            switch(*begin) {
+                case '\\':
+                    check_glob_escape(begin, end);
+                    break;
+
+                case '[':
+                    check_glob_range(begin, end);
+                    is_glob = true;
+                    break;
+
+                case ']':
+                    throw glob_error("uneven square brackets");
+
+                case '?':
+                    is_glob = true;
+                    ++begin;
+                    break;
+
+                case '*':
+                    is_glob = true;
+                    ++begin;
+
+                    if (begin != end && *begin == '*') {
+                        throw glob_error("'**' not supported");
+                    }
+                    break;
+
+                default:
+                    ++begin;
+            }
+        }
+
+        return is_glob;
+    }
+
+    void check_glob_range(glob_iterator& begin, glob_iterator end)
+    {
+        assert(begin != end && *begin == '[');
+        ++begin;
+
+        if (*begin == ']')
+            throw glob_error("empty range");
+
+        while (begin != end) {
+            switch (*begin) {
+                case '\\':
+                    ++begin;
+
+                    if (begin == end) {
+                        throw glob_error("trailing escape");
+                    }
+                    else if (*begin == '\\' || *begin == '/') {
+                        throw glob_error("contains escaped slash");
+                    }
+
+                    ++begin;
+                    break;
+                case '[':
+                    // TODO: Allow?
+                    throw glob_error("nested square brackets");
+                case ']':
+                    ++begin;
+                    return;
+                case '/':
+                    throw glob_error("slash in square brackets");
+                default:
+                    ++begin;
+            }
+        }
+
+        throw glob_error("uneven square brackets");
+    }
+
+    void check_glob_escape(glob_iterator& begin, glob_iterator end)
+    {
+        assert(begin != end && *begin == '\\');
+
+        ++begin;
+
+        if (begin == end) {
+            throw glob_error("trailing escape");
+        }
+        else if (*begin == '\\' || *begin == '/') {
+            throw glob_error("contains escaped slash");
+        }
+
+        ++begin;
+    }
+
     bool glob(boost::string_ref const& pattern,
             boost::string_ref const& filename)
     {
Modified: trunk/tools/quickbook/src/glob.hpp
==============================================================================
--- trunk/tools/quickbook/src/glob.hpp	Thu Nov 14 14:22:48 2013	(r86704)
+++ trunk/tools/quickbook/src/glob.hpp	2013-11-14 14:23:26 EST (Thu, 14 Nov 2013)	(r86705)
@@ -7,9 +7,20 @@
 =============================================================================*/
 
 #include <boost/utility/string_ref.hpp>
+#include <stdexcept>
 
 namespace quickbook
 {
+    struct glob_error : std::runtime_error
+    {
+        explicit glob_error(char const* error) :
+            std::runtime_error(error) {}
+    };
+
+    // Is this path a glob? Throws glob_error if glob is invalid.
+    bool check_glob(boost::string_ref);
+
+    // pre: glob is valid (call check_glob first on user data).
     bool glob(boost::string_ref const& pattern,
             boost::string_ref const& filename);
 }
Modified: trunk/tools/quickbook/src/include_paths.cpp
==============================================================================
--- trunk/tools/quickbook/src/include_paths.cpp	Thu Nov 14 14:22:48 2013	(r86704)
+++ trunk/tools/quickbook/src/include_paths.cpp	2013-11-14 14:23:26 EST (Thu, 14 Nov 2013)	(r86705)
@@ -31,21 +31,19 @@
         if (qbk_version_n >= 107u) {
             std::string path_text = path.get_encoded();
 
-            if (path_text.find("\\\\") != std::string::npos ||
-                    path_text.find("\\/") != std::string::npos)
-            {
+            try {
+                bool is_glob = check_glob(path_text);
+
+                return path_parameter(path_text,
+                    is_glob ? path_parameter::glob : path_parameter::path);
+            } catch(glob_error& e) {
                 detail::outerr(path.get_file(), path.get_position())
-                    << "Invalid path (contains escaped slash): "
+                    << "Invalid path (" << e.what() << "): "
                     << path_text
-                   << std::endl;
+                    << std::endl;
                 ++state.error_count;
                 return path_parameter(path_text, path_parameter::invalid);
             }
-
-            bool is_glob = path_text.find_first_of("[]?*") != std::string::npos;
-
-            return path_parameter(path_text,
-                is_glob ? path_parameter::glob : path_parameter::path);
         }
         else {
             // Paths are encoded for quickbook 1.6+ and also xmlbase
Modified: trunk/tools/quickbook/test/Jamfile.v2
==============================================================================
--- trunk/tools/quickbook/test/Jamfile.v2	Thu Nov 14 14:22:48 2013	(r86704)
+++ trunk/tools/quickbook/test/Jamfile.v2	2013-11-14 14:23:26 EST (Thu, 14 Nov 2013)	(r86705)
@@ -70,6 +70,7 @@
     [ quickbook-error-test include_win_path-1_6-fail ]
     [ quickbook-error-test include_invalid_path1-1_7-fail ]
     [ quickbook-error-test include_invalid_path2-1_7-fail ]
+    [ quickbook-error-test include_invalid_path3-1_7-fail ]
     [ quickbook-test link-1_1 ]
     [ quickbook-test link-1_6 ]
     [ quickbook-test link-1_7 ]
Added: trunk/tools/quickbook/test/include_invalid_path3-1_7-fail.quickbook
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/tools/quickbook/test/include_invalid_path3-1_7-fail.quickbook	2013-11-14 14:23:26 EST (Thu, 14 Nov 2013)	(r86705)
@@ -0,0 +1,5 @@
+[article Include invalid path fail
+[quickbook 1.7]
+]
+
+[include empty\[-/\]inc.quickbook]
Modified: trunk/tools/quickbook/test/unit/glob_test.cpp
==============================================================================
--- trunk/tools/quickbook/test/unit/glob_test.cpp	Thu Nov 14 14:22:48 2013	(r86704)
+++ trunk/tools/quickbook/test/unit/glob_test.cpp	2013-11-14 14:23:26 EST (Thu, 14 Nov 2013)	(r86705)
@@ -90,8 +90,33 @@
     BOOST_TEST(!quickbook::glob("1234*1234*1234", "12341231231234123123123"));
 }
 
+void check_glob_tests()
+{
+    BOOST_TEST(!quickbook::check_glob(""));
+    BOOST_TEST(!quickbook::check_glob("file"));
+    BOOST_TEST(!quickbook::check_glob("file\\[\\]"));
+    BOOST_TEST(quickbook::check_glob("[x]"));
+    BOOST_TEST(quickbook::check_glob("abc[x]"));
+    BOOST_TEST(quickbook::check_glob("[x]abd"));
+    BOOST_TEST_THROWS(quickbook::check_glob("["), quickbook::glob_error);
+    BOOST_TEST_THROWS(quickbook::check_glob("[xyz"), quickbook::glob_error);
+    BOOST_TEST_THROWS(quickbook::check_glob("xyx["), quickbook::glob_error);
+    BOOST_TEST_THROWS(quickbook::check_glob("]"), quickbook::glob_error);
+    BOOST_TEST_THROWS(quickbook::check_glob("abc]"), quickbook::glob_error);
+    BOOST_TEST_THROWS(quickbook::check_glob("]def"), quickbook::glob_error);
+    BOOST_TEST_THROWS(quickbook::check_glob("[]"), quickbook::glob_error);
+    BOOST_TEST_THROWS(quickbook::check_glob("[[]"), quickbook::glob_error);
+    BOOST_TEST_THROWS(quickbook::check_glob("[]]"), quickbook::glob_error);
+    BOOST_TEST_THROWS(quickbook::check_glob("**"), quickbook::glob_error);
+    BOOST_TEST_THROWS(quickbook::check_glob("[/]"), quickbook::glob_error);
+    BOOST_TEST_THROWS(quickbook::check_glob("\\"), quickbook::glob_error);
+    BOOST_TEST_THROWS(quickbook::check_glob("\\\\"), quickbook::glob_error);
+}
+
 int main()
 {
     glob_tests();
+    check_glob_tests();
+
     return boost::report_errors();
 }