[Libreoffice-commits] core.git: Branch 'feature/cib_contract891' - 4 commits - include/o3tl shell/source

Stephan Bergmann (via logerrit) logerrit at kemper.freedesktop.org
Wed Sep 30 12:53:06 UTC 2020


 include/o3tl/runtimetooustring.hxx   |   48 +++++++++++++
 shell/source/unix/exec/shellexec.cxx |   38 ++++++++++
 shell/source/win32/SysShExec.cxx     |  125 ++++++++++++++++++++++++++++++++++-
 3 files changed, 208 insertions(+), 3 deletions(-)

New commits:
commit cf8942d297a99e0d1c39535531e178cbfa2f29af
Author:     Stephan Bergmann <sbergman at redhat.com>
AuthorDate: Wed Jan 15 17:16:02 2020 +0100
Commit:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
CommitDate: Wed Sep 30 14:43:29 2020 +0200

    Remove a fragment from a file URL early on
    
    ...as ShellExecuteExW would ignore it anyway
    
    Change-Id: I969db094bb7d2ea230ac8c36eb23d71a90fbe466
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86868
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <sbergman at redhat.com>
    (cherry picked from commit 14b36a16b225bf7c988f118d499a7287c47cd83e)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86877
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
    (cherry picked from commit 51da0d22ff42b20ab38130b7874651ef136ecceb)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/88208
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    Tested-by: Michael Stahl <michael.stahl at cib.de>

diff --git a/shell/source/win32/SysShExec.cxx b/shell/source/win32/SysShExec.cxx
index 374ddad1a691..6f3b0d578323 100644
--- a/shell/source/win32/SysShExec.cxx
+++ b/shell/source/win32/SysShExec.cxx
@@ -296,6 +296,7 @@ void SAL_CALL CSysShExec::execute( const OUString& aCommand, const OUString& aPa
             static_cast< XSystemShellExecute* >( this ),
             3 );
 
+    OUString preprocessed_command(aCommand);
     if ((nFlags & URIS_ONLY) != 0)
     {
         css::uno::Reference< css::uri::XUriReference > uri(
@@ -310,8 +311,10 @@ void SAL_CALL CSysShExec::execute( const OUString& aCommand, const OUString& aPa
                 static_cast< cppu::OWeakObject * >(this), 0);
         }
         if (uri->getScheme().equalsIgnoreAsciiCase("file")) {
+            // ShellExecuteExW appears to ignore the fragment of a file URL anyway, so remove it:
+            uri->clearFragment();
+            preprocessed_command = uri->getUriReference();
             OUString pathname;
-            uri->clearFragment(); // getSystemPathFromFileURL fails for URLs with fragment
             auto const e1
                 = osl::FileBase::getSystemPathFromFileURL(uri->getUriReference(), pathname);
             if (e1 != osl::FileBase::E_None) {
@@ -415,7 +418,6 @@ void SAL_CALL CSysShExec::execute( const OUString& aCommand, const OUString& aPa
         and names no existing file (remember the jump mark
         sign '#' is a valid file name character we remove
         the jump mark, else ShellExecuteEx fails */
-    OUString preprocessed_command(aCommand);
     if (is_system_path(preprocessed_command))
     {
         if (has_jump_mark(preprocessed_command) && !is_existing_file(preprocessed_command))
commit 349e8b35b1068927fac364a5ede8888605bf3dfc
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Thu Aug 1 10:52:12 2019 +0200
Commit:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
CommitDate: Wed Sep 30 14:43:23 2020 +0200

    tdf#126641: don't fail on file URLs with fragment
    
    This only fixes part that the URL refuses to open the target file.
    Honoring fragment isn't fixed here, since it's the system call to
    ShellExecuteExW that in this case internally converts the file URL
    into a system path, and strips the fragment from it.
    
    Regression from commit d59ec4cd1660410fa1b18c50d2d83b1417a82ddc.
    
    Change-Id: I6c9ed27e9a5bd7f2780dd3be96f816a6e825e043
    Reviewed-on: https://gerrit.libreoffice.org/76778
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
    (cherry picked from commit 2207269a84c7c9920af3385b837ce67978c720b4)
    Reviewed-on: https://gerrit.libreoffice.org/76848
    Reviewed-by: Stephan Bergmann <sbergman at redhat.com>
    (cherry picked from commit dd2b7919058fc0e23a7117d39110d3ecaaad1fb2)
    Reviewed-on: https://gerrit.libreoffice.org/76881
    Reviewed-by: Michael Stahl <Michael.Stahl at cib.de>
    (cherry picked from commit 72861eaf7cf9af3e7764b13d9e74edc5548806d2)
    Reviewed-on: https://gerrit.libreoffice.org/77095
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/shell/source/win32/SysShExec.cxx b/shell/source/win32/SysShExec.cxx
index 83efeb0001bd..374ddad1a691 100644
--- a/shell/source/win32/SysShExec.cxx
+++ b/shell/source/win32/SysShExec.cxx
@@ -311,7 +311,9 @@ void SAL_CALL CSysShExec::execute( const OUString& aCommand, const OUString& aPa
         }
         if (uri->getScheme().equalsIgnoreAsciiCase("file")) {
             OUString pathname;
-            auto const e1 = osl::FileBase::getSystemPathFromFileURL(aCommand, pathname);
+            uri->clearFragment(); // getSystemPathFromFileURL fails for URLs with fragment
+            auto const e1
+                = osl::FileBase::getSystemPathFromFileURL(uri->getUriReference(), pathname);
             if (e1 != osl::FileBase::E_None) {
                 throw css::lang::IllegalArgumentException(
                     ("XSystemShellExecute.execute, getSystemPathFromFileURL <" + aCommand
commit 5e312e325e45cc3a1dc6a74aadcbb5662d3cbb1c
Author:     Stephan Bergmann <sbergman at redhat.com>
AuthorDate: Fri Mar 29 14:01:19 2019 +0100
Commit:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
CommitDate: Wed Sep 30 14:38:27 2020 +0200

    Filter out problematic file URLs
    
    (cherry picked from commit 7e50e885ebbe130debcd4278a10a4e288655fdfc)
    Conflicts:
            shell/source/win32/SysShExec.cxx
    
    Reviewed-on: https://gerrit.libreoffice.org/70188
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>
    (cherry picked from commit a35068ba25ed9da37bcb20598c9791b6979cf1ef)
    Reviewed-on: https://gerrit.libreoffice.org/71589
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    
    Conflicts:
            shell/source/unix/exec/shellexec.cxx
            shell/source/win32/SysShExec.cxx
    
    Change-Id: I87fd37e56326bef4888354b923407530c6f70760

diff --git a/shell/source/unix/exec/shellexec.cxx b/shell/source/unix/exec/shellexec.cxx
index 972957bba73b..dd0ab1a91848 100644
--- a/shell/source/unix/exec/shellexec.cxx
+++ b/shell/source/unix/exec/shellexec.cxx
@@ -41,7 +41,10 @@
 #include <errno.h>
 #include <unistd.h>
 
-//------------------------------------------------------------------------
+#if defined MACOSX
+#include <sys/stat.h>
+#endif
+
 // namespace directives
 //------------------------------------------------------------------------
 
@@ -140,6 +143,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 0d4d7793293e..83efeb0001bd 100644
--- a/shell/source/win32/SysShExec.cxx
+++ b/shell/source/win32/SysShExec.cxx
@@ -17,7 +17,11 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
+#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>
@@ -25,6 +29,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
@@ -32,6 +37,7 @@
 #endif
 #include <windows.h>
 #include <shellapi.h>
+#include <Shobjidl.h>
 #include <objbase.h>
 #if defined _MSC_VER
 #pragma warning(pop)
@@ -41,6 +47,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;
@@ -257,7 +265,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)
@@ -288,6 +309,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
commit d5d61fd80d9532e920b8818826747cfb846060ed
Author:     Stephan Bergmann <sbergman at redhat.com>
AuthorDate: Wed Nov 23 23:10:29 2016 +0100
Commit:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
CommitDate: Wed Sep 30 14:36:19 2020 +0200

    New o3tl::runtimeToOUString to convert from C++ runtime NTBS to OUString
    
    Change-Id: I613bb70b6828f615fd45af38b2d873ece55ace60
    (cherry picked from commit d689ad29c28ad7f077c2239a8fa4c2b6307a6aa1)
    Reviewed-on: https://gerrit.libreoffice.org/71591
    Reviewed-by: Michael Stahl <Michael.Stahl at cib.de>
    Tested-by: Michael Stahl <Michael.Stahl at cib.de>

diff --git a/include/o3tl/runtimetooustring.hxx b/include/o3tl/runtimetooustring.hxx
new file mode 100644
index 000000000000..7f2015805722
--- /dev/null
+++ b/include/o3tl/runtimetooustring.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_O3TL_RUNTIMETOOUSTRING_HXX
+#define INCLUDED_O3TL_RUNTIMETOOUSTRING_HXX
+
+#include <sal/config.h>
+
+#include <cassert>
+#include <cstring>
+
+#include <rtl/textcvt.h>
+#include <rtl/textenc.h>
+#include <rtl/ustring.h>
+#include <rtl/ustring.hxx>
+
+namespace o3tl {
+
+/** Convert an NTBS from the C++ runtime to an OUString.
+
+    This is used to convert an NTBS as provided by std::exception::what or
+    std::type_info::name into an OUString in a "lossless" way.  The conversion
+    is done using RTL_TEXTENCODING_ISO_8859_1, so each char in the input maps
+    to one Unicode character in the output.
+*/
+inline OUString runtimeToOUString(char const * runtimeString) {
+    OUString s;
+    bool ok = rtl_convertStringToUString(
+        &s.pData, runtimeString, std::strlen(runtimeString),
+        RTL_TEXTENCODING_ISO_8859_1,
+        (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
+         | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
+         | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR));
+    assert(ok); (void) ok;
+    return s;
+}
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */


More information about the Libreoffice-commits mailing list