TIP: Click on subject to list as thread! ANSI
echo: os2prog
to: all
from: Mario Semo
date: 1996-10-23 23:08:16
subject: crazy iclui bug

Hello all,

ICLUI BUG: the IFOnt Private Class IFontPrivateData does not initialize
the 'refs' member on copyConstructor. (at least in CTO<=304. not checked
in cto305. in windows version (VACPP/NT fixed, but in the sources shipped
in vacpp/NT in the __OS2__ part also NOT fixed). 

effects: random traps in iclui when many fonts are used. (reason :
iprivatefontdata contains the elements referenced in IFont. and when refs
has a value < 0, the pointers are free'd but still used in IFont).

the copy constructor is used in

 > IFont& IFont :: copyPrivate( )
 > {
 >  if ( ppd->refCount() > 1 )
 >  {
 >    IFontPrivateData* newppd = new IFontPrivateData( *ppd );

and copyPrivate is used whenever something is modified in IFont.

eq:

 > IFont& IFont :: setDirection( Direction lFontDir )
 > {
 >    copyPrivate();
 >    switch (lFontDir) {
 >       case leftToRight:

problem in fixing this problem:

We are using CTO303, since CTO-GA is too buggy for us (a lot of the
problems i reported against VACPP GA are fixed in CTO303) and CTO305 is
again too buggy for us.

on the other side, there is no Source code available for CTO303. ICLUI
source is ONLY available for VACPP GA (CTS-GA) and CTO304 (== CTS304).

since IFonts are used inside ICLUI itself, we want a fix which fixes
the problem on EVERY usage of IFont. so, there are just 2 ways:

 .) recompile source - No way
 .) patch the dll.

ok, here's my analysis and the method for how to patch ICLUI DLL cppoou3.dll
to remove a VERY VERY CRITICAL OCL bug!

first take a look about the buggy copy constructor:

 > IFontPrivateData::IFontPrivateData( const IFontPrivateData& fpd )
 > {
 >   flClStyles     = fpd.flClStyles;
 >   lClLCId        = 0;
 >   lClFontDir     = fpd.lClFontDir;
 >   pntClAngle     = fpd.pntClAngle;
 >   pntClShear     = fpd.pntClShear;
 >   fxClPointSize  = fpd.fxClPointSize;
 >   fxClHeight     = fpd.fxClHeight;
 >   fxClWidth      = fpd.fxClWidth;
 >   plClCharWidths = 0;

as we can see the programmer of this source code does NOT have a good
understanding of C++. this gives us a chance for hacking. (thx IBM).

what we can see is, that the elements are initialized via ASSIGMENT and
not via INITIALIZATION. this means, that elements which are itself
classObjects are INITIALIZED via defaultConstructor and then
reassigned a value here. (but as we all know, there is no need to
think when we write code. iclui is fast enough .....).

so, lets take a look at IPrivateFontData of there is any member which is
a non standard type:


 > class IFontPrivateData : public IBase {
 > ....
 > unsigned long
 >    flClStyles;          0
 >
 > struct _FONTMETRICS
 >    *pfontmetCl;         4
 >
 > struct _FATTRS
 >    *pfattrsCl;          8
 >
 > IPoint
 >    pntClAngle,         12        0x0c,0x10
 >    pntClShear;         20        0x14,0x18
 >
 > long
 >    *plClCharWidths,    28
 >    fxClPointSize,      32
 >    fxClHeight,         36
 >    fxClWidth,          40
 >    lClFontDir,         44
 >    lClLCId;            48        0x30
 > unsigned long
 >    refs;               52        0x34   NOT INITALIZED

found it! IPoint pntClAngle and pntClShear.

next : IFont changed between VACPP-GA and CTC304 only (!) in the addition
of a new textWidth member function with a IBidi parameter. so, lets
compile ifont and lets generate an assmbler file to see whats going on:

 epm: I:\ibmcppsrc\iocsrc\cppoou3 >cc -m -a /I..\include ifont.cpp
 icc -Fd+ -Sm -Ss+ -Si+ -Q+ -Wall+cls-gnr-lan-par-ppt-vft-inl-ppc-use-
    -W3  -Tl30 -Gm+ -Fa /I..\include ifont.cpp

when you compare the IFontPrivateData copy-constructor here (in the
generated .asm file) and in the cppoou3.dll you will see they are
equivalent!

so, lets take a look at the .asm code:

 > ; 94 IFontPrivateData::IFontPrivateData( const IFontPrivateData& fpd )
 >         align 04h
 >
 >         public __ct__16IFontPrivateDataFRC16IFontPrivateData
 > __ct__16IFontPrivateDataFRC16IFontPrivateData   proc
 >         push    ebx
 >
 > ; 30   : coordCl1( 0 ), coordCl2( 0 )
 >         !!!!!!  this is the default constructor of IPoint
 >         !!!!!!    pntClAngle,         12        0x0c,0x10
 >         mov     dword ptr [eax+0ch],0h
 >         mov     dword ptr [eax+010h],0h
 >
 > ; 99
 >         !!!!!!  ebx=edx+12
 >         lea     ebx,[edx+0ch]
 >
 >         !!!!!!  this is the default constructor of IPoint
 >         !!!!!!   pntClShear;         20        0x14,0x18
 > ; 30   : coordCl1( 0 ), coordCl2( 0 )
 >         mov     dword ptr [eax+014h],0h
 >         mov     dword ptr [eax+018h],0h
 >
 >
 >  !!!!! so, as expected, the 2 default constructors for the 2 IPoint members
 >  !!!!! are called. the real initialization of the 2 ipoint members should
 >  !!!!! happen a bit later.
 >
 > ; 96   flClStyles     = fpd.flClStyles;
 >         mov     ecx,[edx]
 >         mov     [eax],ecx
 >
 > ; 97   lClLCId        = 0;
 >         mov     dword ptr [eax+030h],0h
 >
 > ; 98   lClFontDir     = fpd.lClFontDir;
 >         mov     ecx,[edx+02ch]
 >
 > ; 94 IFontPrivateData::IFontPrivateData( const IFontPrivateData& fpd )
 >         push    edi
 >
 > ; 98   lClFontDir     = fpd.lClFontDir;
 >         mov     [eax+02ch],ecx
 >
 >         !!!!!
 >         !!!!! and here pntAngle is re-initialized via ass-operator
 >         !!!!! thx IBM that you are not initializing class members via
 >         !!!!! initLists ....
 >         !!!!!    IFontPrivateData(xx) : a(xx_1), a(xx_2) , ... {}
 >         !!!!!      result in constructors only
 >         !!!!! vs IFontPrivateData(xx) { a=xx_1; b=xx_2; ....}
 >         !!!!!      result in def. constructors + assOperators
 >         !!!!!
 >
 > ; 99   pntClAngle     = fpd.pntClAngle;
 >         lea     ecx,[eax+0ch]
 >         mov     edi,[ebx]
 >         mov     [ecx],edi
 >         mov     edi,[ebx+04h]
 >
 >         !!!!! eax = &fbd.pntClShear
 > ; 100   pntClShear     = fpd.pntClShear;
 >         lea     ebx,[edx+014h]
 >
 > ; 99   pntClAngle     = fpd.pntClAngle;
 >         mov     [ecx+04h],edi
 >
 >         !!!!! ecx = &pntClShear
 > ; 100   pntClShear     = fpd.pntClShear;
 >         lea     ecx,[eax+014h]
 >
 > ; 94 IFontPrivateData::IFontPrivateData( const IFontPrivateData& fpd )
 >         push    esi
 >
 >         !!!!! the same stuff as above. here we have the assigment Op
 >         !!!!! part for the 2nd IPoint
 > ; 100   pntClShear     = fpd.pntClShear;
 >         mov     edi,[ebx]
 >         mov     [ecx],edi
 >         mov     edi,[ebx+04h]
 >         mov     [ecx+04h],edi
 >
 > ; 101   fxClPointSize  = fpd.fxClPointSize;

ok, so we only have to find this routine in the cppoou3.dll and then we
can patch it. we have enough place to play around, since all the following
4 statements are without effect:

 >         mov     dword ptr [eax+0ch],0h
 >         mov     dword ptr [eax+010h],0h
 >         mov     dword ptr [eax+014h],0h
 >         mov     dword ptr [eax+018h],0h

best is the patch the first one to

 >         mov     dword ptr [eax+34h],0h

 so, lets find the start of the code in the dll. since neither ipmd not
 icc helps us really here (they don't display the hex values for
 statement) i'm using microsSofts masm 6.0b for this.

 lets write a mini .cpp file to generate the assembler file layout
 and then write in the first 10 statements of the above code and let masm
 generate a source listing. this looks like:

                                         public func__Fv
  0000                           func__Fv        proc
  0000  53                               push    ebx
  0001  C7 40 0C 00000000                mov     dword ptr [eax+0ch],0h
  0008  C7 40 10 00000000                mov     dword ptr [eax+010h],0h
  000F  8D 5A 0C                         lea     ebx,[edx+0ch]
  0012  C7 40 14 00000000                mov     dword ptr [eax+014h],0h
  0019  C7 40 18 00000000                mov     dword ptr [eax+018h],0h
  0020  8B 0A                            mov     ecx,[edx]
  0022  89 08                            mov     [eax],ecx
  0024  C7 40 30 00000000                mov     dword ptr [eax+030h],0h
  002B  C7 40 34 00000000                mov     dword ptr [eax+034h],0h
  0032  C3                               ret
  0033                           func__Fv        endp
  0033                           CODE32  ends

 (xx.cpp == void func() { }, icc /Fa xx.cpp and then just insert the
 asm statements. for assembling i've used: 'ml /Fl xx.asm'.

 so, lets search for c7400c00000000c74010000000. (therefore i've used
 an hex editor). this string is only once in the DLL. (at
 decimal offset 702852). then chance 0c to 34 (which is the offset of
 the refs member) and you are a lucky guy again.



 WARPED!, Mario

--- Msgedsq/2 2.2e
* Origin: LC/32 Development Team-Vienna-Austria (2:310/14.11)
SEEN-BY: 50/99 270/101 620/243 625/160 711/401 409 410 413 430 808 809 934
SEEN-BY: 711/955 712/407 515 624 628 713/317 800/1
@PATH: 310/14 1 24/999 888 396/1 270/101 712/515 711/808 934

SOURCE: echomail via fidonet.ozzmosis.com

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.