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

leginee pushed a commit to branch win10-msvc-trunk
in repository https://gitbox.apache.org/repos/asf/openoffice.git

commit a1d258c26ad155e41be44bf3267158aabd4a7c9e
Author: Peter Kovacs <[email protected]>
AuthorDate: Sat Aug 29 13:54:12 2026 +0200

    svtools: the autoswap sentinels have to survive Link::Call's long return
    
    GRFMGR_AUTOSWAPSTREAM_* are not streams.  They are sentinels a swap handler
    returns in place of one, and they come back through Link::Call(), whose
    return type is long -- 32 bit on Windows x64.  
GraphicObject::GetSwapStream()
    casts that long straight back to SvStream* (grfmgr.cxx:487), so the value
    every comparison sees is the sentinel truncated to 32 bits and widened
    again.
    
    Written as (SvStream*)0xffffffffUL, _NONE is 0x00000000ffffffff, but comes
    back from that round trip as 0xffffffffffffffff and equals none of the four.
    ImplAutoSwapOutHdl() then takes it for a real stream and writes the graphic
    to address 0xffffffffffffffff -- the access violation on deleting a Gallery
    graphic.
    
    Spelling them as negative sal_IntPtr settles it in both directions: where
    long is pointer-sized the bit patterns are exactly what they were, and where
    it is not, the truncated value sign-extends back to precisely these
    constants, so the comparisons match again.
    
    On LP64 the numeric values do change -- _NONE becomes 0xffffffffffffffff
    rather than 0x00000000ffffffff.  That is harmless because the sentinels are
    only ever compared against each other and never persisted, but it does mean
    all three modules that name them -- svtools, svx and sw -- have to be built
    together, not svtools alone.
    
    The narrowing return type is the real defect and is deliberately not touched
    here: Link is a public interface used across the whole product.
    
    Co-Authored-By: Claude Opus 5 <[email protected]>
    Claude-Session: https://claude.ai/code/session_01UWgzQY2r1XwFvgeLPFWPsi
---
 main/svtools/inc/svtools/grfmgr.hxx | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/main/svtools/inc/svtools/grfmgr.hxx 
b/main/svtools/inc/svtools/grfmgr.hxx
index 9a19c20a08..b91caecb57 100644
--- a/main/svtools/inc/svtools/grfmgr.hxx
+++ b/main/svtools/inc/svtools/grfmgr.hxx
@@ -43,10 +43,20 @@
 // - AutoSwap Defines -
 // --------------------
 
-#define GRFMGR_AUTOSWAPSTREAM_LINK             ((SvStream*)0x00000000UL)
-#define GRFMGR_AUTOSWAPSTREAM_LOADED   ((SvStream*)0xfffffffdUL)
-#define GRFMGR_AUTOSWAPSTREAM_TEMP             ((SvStream*)0xfffffffeUL)
-#define GRFMGR_AUTOSWAPSTREAM_NONE             ((SvStream*)0xffffffffUL)
+/* These four are not streams: they are sentinels that a swap handler returns
+   in place of one.  The handler hands them back through Link::Call(), whose
+   return type is long -- 32 bit on Windows x64 -- so a 64-bit pointer value
+   makes the round trip only if it survives truncation to long and the cast
+   back.  Spelling the sentinels as negative sal_IntPtr does that: the bits
+   are unchanged where long is pointer-sized, and where it is not, the cast
+   back sign-extends to exactly these values, so the comparisons in
+   GraphicObject::ImplAutoSwapOutHdl()/ImplAutoSwapIn() still match.  Written
+   as 0xffffffffUL they did not, and _NONE arrived there as a stream to write
+   to. */
+#define GRFMGR_AUTOSWAPSTREAM_LINK             ((SvStream*)(sal_IntPtr) 0)
+#define GRFMGR_AUTOSWAPSTREAM_LOADED   ((SvStream*)(sal_IntPtr)-3)
+#define GRFMGR_AUTOSWAPSTREAM_TEMP             ((SvStream*)(sal_IntPtr)-2)
+#define GRFMGR_AUTOSWAPSTREAM_NONE             ((SvStream*)(sal_IntPtr)-1)
 
 // ----------------------
 // - Adjustment Defines -

Reply via email to