This is an automated email from the ASF dual-hosted git repository.

leginee pushed a commit to branch win64-bridge-backport
in repository https://gitbox.apache.org/repos/asf/openoffice.git

commit a59e4e8aabf0d4392ae6ab7078032a4b8ca5fe95
Author: Peter Kovacs <[email protected]>
AuthorDate: Mon Jul 27 07:07:08 2026 +0200

    bridges/msvc_win64: return queryInterface's Any in the hidden return buffer
    
    The Win64 call stack is "ret addr, this, [ret *], params", so a method with
    a hidden return pointer finds it at pCallStack[2] -- cpp2uno_call() reads
    pCppReturn from [2], and the queryInterface shortcut in cpp_mediate() reads
    its Type argument from [3] accordingly.
    
    That shortcut nevertheless built the returned Any at pCallStack[1] and
    returned [1] in the register slot.  [1] is `this`, so it constructed a
    24-byte Any over the proxy object and never wrote the caller's own return
    buffer.  The caller then read and destructed an uninitialised Any, faulting
    in uno_any_destruct() on a stale stack value used as a
    typelib_TypeDescription*.
    
    The x86 bridge has always used pCallStack[2] here; the Win64 port carried
    over the x86 index, where the layout puts the hidden pointer before `this`.
    
    Reproducer: any queryInterface on a raw uno_Interface proxy -- e.g. pyuno's
    Adapter::getOutIndexes() inspecting an InvocationAdapterFactory adapter,
    which crashed on every use of the Python macro organiser.
    
    Co-Authored-By: Claude Opus 5 <[email protected]>
---
 main/bridges/source/cpp_uno/msvc_win64_x86-64/cpp2uno.cxx | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/main/bridges/source/cpp_uno/msvc_win64_x86-64/cpp2uno.cxx 
b/main/bridges/source/cpp_uno/msvc_win64_x86-64/cpp2uno.cxx
index 5deb06b112..a37c37bc21 100644
--- a/main/bridges/source/cpp_uno/msvc_win64_x86-64/cpp2uno.cxx
+++ b/main/bridges/source/cpp_uno/msvc_win64_x86-64/cpp2uno.cxx
@@ -301,13 +301,18 @@ extern "C" typelib_TypeClass cpp_vtable_call(
 
                                if ( pInterface )
                                {
-                                   ::uno_any_construct( 
reinterpret_cast<uno_Any *>( pCallStack[1] ),
+                                   // pCallStack is "ret addr, this, [ret *], 
params", so the
+                                   // hidden return buffer is [2]; [1] is 
`this`.  Writing the
+                                   // Any to [1] overwrote the proxy object 
and left the
+                                   // caller's return buffer untouched, so the 
caller then
+                                   // destructed an uninitialised Any.
+                                   ::uno_any_construct( 
reinterpret_cast<uno_Any *>( pCallStack[2] ),
                                                                                
                 &pInterface, pTD, cpp_acquire );
 
                                    pInterface->release();
                                    TYPELIB_DANGER_RELEASE( pTD );
 
-                                   reinterpret_cast<void **>( pRegisterReturn 
)[0] = pCallStack[1];
+                                   reinterpret_cast<void **>( pRegisterReturn 
)[0] = pCallStack[2];
                                    eRet = typelib_TypeClass_ANY;
                                    break;
                                }

Reply via email to