shell/source/unix/exec/shellexec.cxx | 36 ++++++++++ shell/source/win32/SysShExec.cxx | 117 +++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+)
New commits: commit bfa0f65f928e32aea98a0d639ef7ca7bf620fae3 Author: Stephan Bergmann <sberg...@redhat.com> AuthorDate: Fri Mar 29 14:01:19 2019 +0100 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Tue Apr 30 23:43:34 2019 +0200 Filter out problematic file URLs (cherry picked from commit 7e50e885ebbe130debcd4278a10a4e288655fdfc) Conflicts: shell/source/win32/SysShExec.cxx Change-Id: I87fd37e56326bef4888354b923407530c6f70760 Reviewed-on: https://gerrit.libreoffice.org/70188 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> Tested-by: Caolán McNamara <caol...@redhat.com> (cherry picked from commit a35068ba25ed9da37bcb20598c9791b6979cf1ef) Reviewed-on: https://gerrit.libreoffice.org/71589 Reviewed-by: Thorsten Behrens <thorsten.behr...@cib.de> Tested-by: Thorsten Behrens <thorsten.behr...@cib.de> diff --git a/shell/source/unix/exec/shellexec.cxx b/shell/source/unix/exec/shellexec.cxx index 7f12a80b76ef..857e0b1ec90c 100644 --- a/shell/source/unix/exec/shellexec.cxx +++ b/shell/source/unix/exec/shellexec.cxx @@ -42,6 +42,9 @@ #include <errno.h> #include <unistd.h> +#if defined MACOSX +#include <sys/stat.h> +#endif // namespace directives @@ -129,6 +132,39 @@ void SAL_CALL ShellExec::execute( const OUString& aCommand, const OUString& aPar } #ifdef MACOSX + if (uri->getScheme().equalsIgnoreAsciiCase("file")) { + OUString pathname; + auto const e1 = osl::FileBase::getSystemPathFromFileURL(aCommand, pathname); + if (e1 != osl::FileBase::E_None) { + throw css::lang::IllegalArgumentException( + ("XSystemShellExecute.execute, getSystemPathFromFileURL <" + aCommand + + "> failed with " + OUString::number(e1)), + {}, 0); + } + OString pathname8; + if (!pathname.convertToString( + &pathname8, RTL_TEXTENCODING_UTF8, + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR + | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))) + { + throw css::lang::IllegalArgumentException( + "XSystemShellExecute.execute, cannot convert \"" + pathname + "\" to UTF-8", {}, + 0); + } + struct stat st; + auto const e2 = stat(pathname8.getStr(), &st); + if (e2 != 0) { + auto const e3 = errno; + SAL_INFO("shell", "stat(" << pathname8 << ") failed with errno " << e3); + } + if (e2 != 0 || !S_ISREG(st.st_mode) + || (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0) + { + throw css::lang::IllegalArgumentException( + "XSystemShellExecute.execute, cannot process <" + aCommand + ">", {}, 0); + } + } + //TODO: Using open(1) with an argument that syntactically is an absolute // URI reference does not necessarily give expected results: // 1 If the given URI reference matches a supported scheme (e.g., diff --git a/shell/source/win32/SysShExec.cxx b/shell/source/win32/SysShExec.cxx index 70c694749b66..3c577df58510 100644 --- a/shell/source/win32/SysShExec.cxx +++ b/shell/source/win32/SysShExec.cxx @@ -18,8 +18,11 @@ */ #include <algorithm> +#include <cassert> #include <osl/diagnose.h> +#include <osl/process.h> +#include <sal/log.hxx> #include "SysShExec.hxx" #include <osl/file.hxx> #include <sal/macros.h> @@ -27,6 +30,7 @@ #include <com/sun/star/system/SystemShellExecuteFlags.hpp> #include <com/sun/star/uri/UriReferenceFactory.hpp> #include <cppuhelper/supportsservice.hxx> +#include <o3tl/runtimetooustring.hxx> #define WIN32_LEAN_AND_MEAN #if defined _MSC_VER @@ -34,6 +38,7 @@ #endif #include <windows.h> #include <shellapi.h> +#include <Shobjidl.h> #include <objbase.h> #if defined _MSC_VER #pragma warning(pop) @@ -43,6 +48,8 @@ // namespace directives +#include <systools/win32/comtools.hxx> + using com::sun::star::uno::Reference; using com::sun::star::uno::RuntimeException; using com::sun::star::uno::Sequence; @@ -252,6 +259,20 @@ CSysShExec::CSysShExec( const Reference< css::uno::XComponentContext >& xContext CoInitialize( NULL ); } +namespace +{ +bool checkExtension(OUString const & extension, OUString const & blacklist) { + assert(!extension.isEmpty()); + for (sal_Int32 i = 0; i != -1;) { + OUString tok = blacklist.getToken(0, ';', i); + tok.startsWith(".", &tok); + if (extension.equalsIgnoreAsciiCase(tok)) { + return false; + } + } + return true; +} +} void SAL_CALL CSysShExec::execute( const OUString& aCommand, const OUString& aParameter, sal_Int32 nFlags ) throw (IllegalArgumentException, SystemShellExecuteException, RuntimeException) @@ -281,6 +302,102 @@ void SAL_CALL CSysShExec::execute( const OUString& aCommand, const OUString& aPa + aCommand, static_cast< cppu::OWeakObject * >(this), 0); } + if (uri->getScheme().equalsIgnoreAsciiCase("file")) { + OUString pathname; + auto const e1 = osl::FileBase::getSystemPathFromFileURL(aCommand, pathname); + if (e1 != osl::FileBase::E_None) { + throw css::lang::IllegalArgumentException( + ("XSystemShellExecute.execute, getSystemPathFromFileURL <" + aCommand + + "> failed with " + OUString::number(e1)), + {}, 0); + } + for (int i = 0;; ++i) { + SHFILEINFOW info; + if (SHGetFileInfoW( + pathname.getStr(), 0, &info, sizeof info, SHGFI_EXETYPE) + != 0) + { + throw css::lang::IllegalArgumentException( + "XSystemShellExecute.execute, cannot process <" + aCommand + ">", {}, 0); + } + if (SHGetFileInfoW( + pathname.getStr(), 0, &info, sizeof info, SHGFI_ATTRIBUTES) + == 0) + { + throw css::lang::IllegalArgumentException( + "XSystemShellExecute.execute, SHGetFileInfoW(" + pathname + ") failed", {}, + 0); + } + if ((info.dwAttributes & SFGAO_LINK) == 0) { + break; + } + sal::systools::COMReference<IShellLinkW> link; + auto e2 = CoCreateInstance( + CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLinkW, + reinterpret_cast<LPVOID *>(&link)); + if (FAILED(e2)) { + throw css::lang::IllegalArgumentException( + ("XSystemShellExecute.execute, CoCreateInstance failed with " + + OUString::number(e2)), + {}, 0); + } + sal::systools::COMReference<IPersistFile> file; + try { + file = link.QueryInterface<IPersistFile>(IID_IPersistFile); + } catch(sal::systools::ComError & e3) { + throw css::lang::IllegalArgumentException( + ("XSystemShellExecute.execute, QueryInterface failed with: " + + o3tl::runtimeToOUString(e3.what())), + {}, 0); + } + e2 = file->Load(pathname.getStr(), STGM_READ); + if (FAILED(e2)) { + throw css::lang::IllegalArgumentException( + ("XSystemShellExecute.execute, IPersistFile.Load failed with " + + OUString::number(e2)), + {}, 0); + } + e2 = link->Resolve(nullptr, SLR_UPDATE | SLR_NO_UI); + if (FAILED(e2)) { + throw css::lang::IllegalArgumentException( + ("XSystemShellExecute.execute, IShellLink.Resolve failed with " + + OUString::number(e2)), + {}, 0); + } + wchar_t path[MAX_PATH]; + WIN32_FIND_DATAW wfd; + e2 = link->GetPath(path, MAX_PATH, &wfd, SLGP_RAWPATH); + if (FAILED(e2)) { + throw css::lang::IllegalArgumentException( + ("XSystemShellExecute.execute, IShellLink.GetPath failed with " + + OUString::number(e2)), + {}, 0); + } + pathname = path; + // Fail at some arbitrary nesting depth, to avoid an infinite loop: + if (i == 30) { + throw css::lang::IllegalArgumentException( + "XSystemShellExecute.execute, link depth exceeded for <" + aCommand + ">", + {}, 0); + } + } + auto const n = pathname.lastIndexOf('.'); + if (n > pathname.lastIndexOf('\\')) { + auto const ext = pathname.copy(n + 1); + OUString env; + if (osl_getEnvironment(OUString("PATHEXT").pData, &env.pData) != osl_Process_E_None) + { + SAL_INFO("shell", "osl_getEnvironment(PATHEXT) failed"); + } + if (!(checkExtension(ext, env) + && checkExtension( + ext, ".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY"))) + { + throw css::lang::IllegalArgumentException( + "XSystemShellExecute.execute, cannot process <" + aCommand + ">", {}, 0); + } + } + } } /* #i4789#; jump mark detection on system paths _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits