Boost C++ Libraries: Ticket #13028: boost::filesystem::canonical(const path& p, system::error_code& ec) throws exception https://svn.boost.org/trac10/ticket/13028 <p> Per <a href="http://www.boost.org/doc/libs/1_64_0/libs/filesystem/doc/reference.html#Error-reporting">the docs</a>, this function should report filesystem errors through the error_code. In the case of permission issues, this contract is violated. </p> <p> This is best explained with the test case: </p> <pre class="wiki">#include &lt;boost/detail/lightweight_test_report.hpp&gt; #include &lt;boost/filesystem.hpp&gt; namespace fs = boost::filesystem; int test_main(int, char*[]) { // Ensure that we do not have read permissions on pwd fs::path tmp_path = fs::temp_directory_path(); fs::path unique_path = fs::unique_path(); fs::path dir_path = tmp_path / unique_path; fs::create_directory(dir_path); fs::current_path(dir_path); fs::permissions(dir_path, fs::no_perms); // Try to get a canonical path with the error_code API. This should return an // error through the error_code, but instead throws an exception (because // canonical(const path&amp; p, system::error_code&amp; ec) calls current_path() // without error_code) boost::system::error_code e; fs::canonical("foo", e); BOOST_TEST(e.value() != 0); return ::boost::report_errors(); } </pre><p> Test output: </p> <pre class="wiki">bin/bug Clang version 8.0.0 (clang-800.0.38), __GXX_EXPERIMENTAL_CXX0X__ not defined libc++ version 3700 Mac OS Boost version 1.65.0 Command line: bin/bug ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ****************************** std::exception ***************************** boost::filesystem::current_path: Permission denied *************************************************************************** </pre><p> This unexpected exception causes a crash in osquery. See <a class="ext-link" href="https://github.com/facebook/osquery/issues/3279"><span class="icon">​</span>https://github.com/facebook/osquery/issues/3279</a> </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/13028 Trac 1.4.3 anonymous Fri, 14 Jul 2017 19:12:59 GMT <link>https://svn.boost.org/trac10/ticket/13028#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/13028#comment:1</guid> <description> <p> I just ran into the same issue in one of our internal applications. There are actually 2 bugs causing the same problem. The first is that the <code>canonical(const path&amp; p, system::error_code&amp; ec)</code> calls <code>current_path()</code> without passing in the <code>error_code</code>. However, when that is fixed, then same problem shows up again if you pass in a relative path as <code>base</code> because <code>detail::canonical()</code> immediately calls <code>absolute()</code>, which in turn calls <code>current_path()</code>. </p> <p> It's easy to fix by simply calling the no except version of <code>current_path()</code> in both places (although, since <code>absolute()</code> doesn't take an <code>error_code</code>, it can get a bit wordy): </p> <p> operations.hpp: </p> <pre class="wiki"> inline path canonical(const path&amp; p, system::error_code&amp; ec) { path base = detail::current_path(&amp;ec); if (ec) return path(); return detail::canonical(p, base, &amp;ec); } </pre><p> operations.cpp </p> <pre class="wiki"> BOOST_FILESYSTEM_DECL path canonical(const path&amp; p, const path&amp; base, system::error_code* ec) { path source(p); if (!p.is_absolute()) { path absBase(base); if (!absBase.is_absolute()) { path curr = current_path(ec); if (ec &amp;&amp; *ec) return path(); absBase = absolute(base, curr); } source = absolute(p, absBase); } </pre> </description> <category>Ticket</category> </item> </channel> </rss>