ForwardInfo crashes on multiple entries

Mar 8, 2013 at 8:07 AM
Edited Mar 8, 2013 at 8:14 AM
Hello there,

i encountered a problem with having multiple forwarding entries on an address.
Location: TapiAddress.cs, ForwardingInformation
Line: Marshal.Copy(_rawBuffer, pos + _las.dwForwardOffset, pLpe, size);

if there are multiple forward entries set on this address, the last run through the entries raises an exception (Index and count must refer to a location within the buffer) at the given line.

i also did check the "GatherAddressStatus()" method, but there my knowledge about the structs ends...

system: windows x64 (yes, i target the code to x86, everything else works perfectly)

has anyone an idea?

thanks in advance,
Wolfgang
Mar 8, 2013 at 9:16 AM
Update after additional debugging:

after the line mentioned above, there is another line, which constructs a managed object "lfw":

Marshal.PtrToStructure(pLpe, lfw);

this object lfw (LINEFORWARD) then has very high values in the members "dwCallerAddressType" and "dwDestAddressOffset" (3145777). this is what makes the "out of range exception".

still need help on that,
rgds
Wolfgang
Developer
Mar 11, 2013 at 3:24 PM
Hello Wolfgang,
can you details more/better the scenario and the usage of the API you're doing?
For example, are you executing concurrent operations ?

At first glance, this issue smells like a bug similar to 11472. But to be sure, I need some more details about your app.

Marco.
Mar 11, 2013 at 3:36 PM
Hi Marco,

this is the code part of my application which tries to read all the forwardEntries out of the collection:

foreach (TapiAddress ta in line.Addresses)
                {
                    RaiseLogMessage("checking address " + ta.Address + " for: " + extension);                        

                    ForwardInfo f = ta.Status.ForwardingInformation.Where(ff => ff.ForwardMode == ForwardingMode.Unconditional).FirstOrDefault();

                    if (f != null)
                    {
                        RaiseLogMessage("Forwarding for " + extension + " on " + f.ForwardMode.ToString() + " to " + f.DestinationAddress + " found");
                        if (f.DestinationAddress.Length > 0 )
                        {
                            number = f.DestinationAddress;                                
                        }
                    }
                }

in the linq query i run into the exception, coming from this part of the tapiAddress.cs of the atapi source:
   public ForwardInfo[] ForwardingInformation
    {
        get
        {
            var fwdInfo = new ForwardInfo[_las.dwForwardNumEntries];
            if (_las.dwForwardNumEntries > 0)
            {
                for (int i = 0; i < _las.dwForwardNumEntries; i++)
                {
                    var lfw = new LINEFORWARD();
                    int size = Marshal.SizeOf(lfw); //WF found out that this should be 24, at least the _rawBuffer has the forward elements in 24 byte packets. maybe x64 problem with sizeOf
                    int pos = i * size; 
                    IntPtr pLpe = Marshal.AllocHGlobal(size);                        
                    Marshal.Copy(_rawBuffer, pos + _las.dwForwardOffset, pLpe, size);
                    Marshal.PtrToStructure(pLpe, lfw);
                    Marshal.FreeHGlobal(pLpe);

                    fwdInfo[i] = new ForwardInfo(
                        (ForwardingMode)lfw.dwForwardMode, 
                        (AddressType)lfw.dwCallerAddressType, 
                        (lfw.dwCallerAddressOffset > 0) ?
                            NativeMethods.GetString(_rawBuffer, lfw.dwCallerAddressOffset, lfw.dwCallerAddressSize, _stringFormat) : string.Empty,
                        lfw.dwDestCountryCode,
                        (AddressType)lfw.dwDestAddressType,
                        (lfw.dwDestAddressOffset > 0) ?
                            NativeMethods.GetString(_rawBuffer, lfw.dwDestAddressOffset, lfw.dwDestAddressSize, _stringFormat) : string.Empty);

                    //WF workaround, if multiple forward entries are set
                    var fwdInfoWF = new ForwardInfo[1];
                    fwdInfoWF[0] = fwdInfo[0];
                    fwdInfo = fwdInfoWF;
                    break;
                    //end workaround
                }
            }
            return fwdInfo;
        }
    }
you can see the //WF comments where i did the Workaround to just return the first forwardEntry element.

the Problem i could see is that when checking the _rawBuffer Content that all the forwardEntries have a size of 24 Bytes. the struct "LINEFORWARD" initialized into the variable "lfw" returns a sizeOf of 32 Bytes. therefore the Iteration through the _rawBuffer gets confused.

is it clear enough now for you?

to reproduce the issue it should be rather easy to set more than one forwarding entry on an address and then call the address.Status.ForwardingInformation array.

rgds and if you need any further Information, don't hesitate to email me (wf at voxtron dot de)

Wolfgang