1 /*
2  *
3  * Copyright (c) 1998-2004
4  * John Maddock
5  *
6  * Use, modification and distribution are subject to the
7  * Boost Software License, Version 1.0. (See accompanying file
8  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9  *
10  */
11 
12  /*
13   *   LOCATION:    see http://www.boost.org for most recent version.
14   *   FILE:        regex.cpp
15   *   VERSION:     see <boost/version.hpp>
16   *   DESCRIPTION: Misc boost::regbase member funnctions.
17   */
18 
19 
20 #define BOOST_REGEX_SOURCE
21 
22 #include <boost/config.hpp>
23 #include <new>
24 #include <boost/regex.hpp>
25 #include <boost/throw_exception.hpp>
26 
27 #if defined(BOOST_REGEX_HAS_MS_STACK_GUARD) && defined(_MSC_VER) && (_MSC_VER >= 1300)
28 #  include <malloc.h>
29 #endif
30 #ifdef BOOST_REGEX_HAS_MS_STACK_GUARD
31 #define WIN32_LEAN_AND_MEAN
32 #ifndef NOMINMAX
33 #  define NOMINMAX
34 #endif
35 #define NOGDI
36 #define NOUSER
37 #include <windows.h>
38 #endif
39 
40 #if defined(BOOST_REGEX_NON_RECURSIVE) && !defined(BOOST_REGEX_V3)
41 #if BOOST_REGEX_MAX_CACHE_BLOCKS == 0
42 #include <new>
43 #else
44 #include <boost/regex/v4/mem_block_cache.hpp>
45 #endif
46 #endif
47 
48 #ifdef BOOST_INTEL
49 #pragma warning(disable:383)
50 #endif
51 
52 namespace boost{
53 
54 //
55 // fix: these are declared out of line here to ensure
56 // that dll builds contain the Virtual table for these
57 // types - this ensures that exceptions can be thrown
58 // from the dll and caught in an exe.
regex_error(const std::string & s,regex_constants::error_type err,std::ptrdiff_t pos)59 regex_error::regex_error(const std::string& s, regex_constants::error_type err, std::ptrdiff_t pos)
60    : std::runtime_error(s)
61    , m_error_code(err)
62    , m_position(pos)
63 {
64 }
65 
regex_error(regex_constants::error_type err)66 regex_error::regex_error(regex_constants::error_type err)
67    : std::runtime_error(::boost::re_detail::get_default_error_string(err))
68    , m_error_code(err)
69    , m_position(0)
70 {
71 }
72 
~regex_error()73 regex_error::~regex_error() throw()
74 {
75 }
76 
raise() const77 void regex_error::raise()const
78 {
79 #ifndef BOOST_NO_EXCEPTIONS
80    ::boost::throw_exception(*this);
81 #endif
82 }
83 
84 
85 
86 namespace re_detail{
87 
raise_runtime_error(const std::runtime_error & ex)88 BOOST_REGEX_DECL void BOOST_REGEX_CALL raise_runtime_error(const std::runtime_error& ex)
89 {
90    ::boost::throw_exception(ex);
91 }
92 //
93 // error checking API:
94 //
verify_options(boost::regex::flag_type,match_flag_type mf)95 BOOST_REGEX_DECL void BOOST_REGEX_CALL verify_options(boost::regex::flag_type /*ef*/, match_flag_type mf)
96 {
97 #ifndef BOOST_REGEX_V3
98    //
99    // can't mix match_extra with POSIX matching rules:
100    //
101    if((mf & match_extra) && (mf & match_posix))
102    {
103       std::logic_error msg("Usage Error: Can't mix regular expression captures with POSIX matching rules");
104       throw_exception(msg);
105    }
106 #endif
107 }
108 
109 #ifdef BOOST_REGEX_HAS_MS_STACK_GUARD
110 
execute_eror()111 static void execute_eror()
112 {
113    // we only get here after a stack overflow,
114    // this has to be a separate proceedure because we
115    // can't mix __try{}__except block with local objects
116    // that have destructors:
117    reset_stack_guard_page();
118    std::runtime_error err("Out of stack space, while attempting to match a regular expression.");
119    raise_runtime_error(err);
120 }
121 
execute() const122 bool BOOST_REGEX_CALL abstract_protected_call::execute()const
123 {
124    __try{
125       return this->call();
126    }__except(EXCEPTION_STACK_OVERFLOW == GetExceptionCode())
127    {
128       execute_eror();
129    }
130    // We never really get here at all:
131    return false;
132 }
133 
reset_stack_guard_page()134 BOOST_REGEX_DECL void BOOST_REGEX_CALL reset_stack_guard_page()
135 {
136 #if defined(BOOST_REGEX_HAS_MS_STACK_GUARD) && defined(_MSC_VER) && (_MSC_VER >= 1300)
137    _resetstkoflw();
138 #else
139    //
140    // We need to locate the current page being used by the stack,
141    // move to the page below it and then deallocate and protect
142    // that page.  Note that ideally we would protect only the lowest
143    // stack page that has been allocated: in practice there
144    // seems to be no easy way to locate this page, in any case as
145    // long as the next page is protected, then Windows will figure
146    // the rest out for us...
147    //
148    SYSTEM_INFO si;
149    GetSystemInfo(&si);
150    MEMORY_BASIC_INFORMATION mi;
151    DWORD previous_protection_status;
152    //
153    // this is an address in our stack space:
154    //
155    LPBYTE page = (LPBYTE)&page;
156    //
157    // Get the current memory page in use:
158    //
159    VirtualQuery(page, &mi, sizeof(mi));
160    //
161    // Go to the page one below this:
162    //
163    page = (LPBYTE)(mi.BaseAddress)-si.dwPageSize;
164    //
165    // Free and protect everything from the start of the
166    // allocation range, to the end of the page below the
167    // one in use:
168    //
169    if (!VirtualFree(mi.AllocationBase, (LPBYTE)page - (LPBYTE)mi.AllocationBase, MEM_DECOMMIT)
170       || !VirtualProtect(page, si.dwPageSize, PAGE_GUARD | PAGE_READWRITE, &previous_protection_status))
171    {
172       throw std::bad_exception();
173    }
174 #endif
175 }
176 #endif
177 
178 #if defined(BOOST_REGEX_NON_RECURSIVE) && !defined(BOOST_REGEX_V3)
179 
180 #if BOOST_REGEX_MAX_CACHE_BLOCKS == 0
181 
get_mem_block()182 BOOST_REGEX_DECL void* BOOST_REGEX_CALL get_mem_block()
183 {
184    return ::operator new(BOOST_REGEX_BLOCKSIZE);
185 }
186 
put_mem_block(void * p)187 BOOST_REGEX_DECL void BOOST_REGEX_CALL put_mem_block(void* p)
188 {
189    ::operator delete(p);
190 }
191 
192 #else
193 
194 #ifdef BOOST_HAS_THREADS
195 mem_block_cache block_cache = { 0, 0, BOOST_STATIC_MUTEX_INIT, };
196 #else
197 mem_block_cache block_cache = { 0, 0, };
198 #endif
199 
get_mem_block()200 BOOST_REGEX_DECL void* BOOST_REGEX_CALL get_mem_block()
201 {
202    return block_cache.get();
203 }
204 
put_mem_block(void * p)205 BOOST_REGEX_DECL void BOOST_REGEX_CALL put_mem_block(void* p)
206 {
207    block_cache.put(p);
208 }
209 
210 #endif
211 
212 #endif
213 
214 } // namespace re_detail
215 
216 
217 
218 } // namespace boost
219 
220 #if defined(BOOST_RE_USE_VCL) && defined(BOOST_REGEX_DYN_LINK)
221 
DllEntryPoint(HINSTANCE,unsigned long,void *)222 int WINAPI DllEntryPoint(HINSTANCE , unsigned long , void*)
223 {
224    return 1;
225 }
226 #endif
227 
228