https://issues.apache.org/ooo/show_bug.cgi?id=121322

          Priority: P3
            Bug ID: 121322
          Assignee: [email protected]
           Summary: Data corruption in abi.cxx relating to inherited
                    structs or exceptions
          Severity: major
        Issue Type: DEFECT
    Classification: Code
                OS: Linux64
          Reporter: [email protected]
          Hardware: All
            Status: UNCONFIRMED
           Version: AOO 3.4.1
         Component: code
           Product: udk

We tried to call a method returning a struct "B" using the XInvocation2
interface.

The struct was defined in IDL as follows:
struct B : A { 
   long value;
};

A was defined that way:
struct A {
   boolean a;
   long b;
   boolean c;
};

sizeof(B) == 16 byte on x86_64.

Now we call a method defined as follows using XInvocation2:
 B aMethod();

The call stack somewhen reaches callVirtualMethod (uno2cpp.cxx), which calls
x86_64::fill_struct( pReturnTypeRef, &longs[0], ...)

At this point in time, the longs array still contains the correct values of the
struct returned by aMethod().

fill_struct(..) now calls classify_argument, which contains the following code:
* If the struct is larger than 16 bytes, pass it on the stack.  */
if ( pTypeDescr->nSize > 16 )
{
    TYPELIB_DANGER_RELEASE( pTypeDescr );
    return 0;
}

for ( int i = 0; i < words; i++ )
    classes[i] = X86_64_NO_CLASS;

const typelib_CompoundTypeDescription *pStruct = reinterpret_cast<const
typelib_CompoundTypeDescription*>( pTypeDescr );

/* Merge the fields of structure.  */
for ( sal_Int32 nMember = 0; nMember < pStruct->nMembers; ++nMember )
{
    typelib_TypeDescriptionReference *pTypeInStruct = pStruct->ppTypeRefs[
nMember ];
    rByteOffset = pStruct->pMemberOffsets[ nMember ];

    int num = classify_argument( pTypeInStruct, subclasses, rByteOffset );

    if ( num == 0 )
    {
        TYPELIB_DANGER_RELEASE( pTypeDescr );
        return 0;
    }

    for ( int i = 0; i < num; i++ )
    {
        int pos = rByteOffset / 8;
        classes[i + pos] = merge_classes( subclasses[i], classes[i + pos] );
    }
}

In the case of derived structs, pStruct->nMembers only contains the
(additional) member count of the derived struct, the member count of the base
struct is not contained. It could be accessed by recursively looking int
pStruct->pBaseTypeDescription->nMembers.

I see two possible fixes for this:
a) adapt the code to recursively look into the base type descriptions
b) enhance the > 16 bytes check to also check for inherited structs and pass
them on the stack

I'll give approach b) a try, seems to be less error prone to me.

-- 
You are receiving this mail because:
You are the assignee for the bug.

Reply via email to