<div dir="ltr"><div>hi ross,<br></div><div><br></div><div>colleague could not subscribe to the mailing list with his email address so see below for the forwarded question.<br><br></div><div>best regards,<br></div><div>gerald<br><br></div><div><div><div>------------------------------<wbr>------------------------------<wbr>------------------------------<wbr>----------------------<br><br><div>
<p class="MsoNormal">Hi,</p>
</div>
<div>
<p class="MsoNormal"> </p>
</div>
<div>
<p class="MsoNormal">three weeks ago we've started using libAsan on gcc 4.9 and we have fixed a dozen of small memory errors on our code ever since.</p>
</div>
<div>
<p class="MsoNormal">Today I'm having an error in the live555 code that came up using libAsan.</p>
</div>
<div>
<p class="MsoNormal"> </p>
</div>
<div>
<p class="MsoNormal">It seems that the taskscheduler fires up the 
destructor of SocketDescriptor after an evaluation of true on the 
fDeleteMyselfNext flag which is set implicitly by calling 
Medium::close(our_session).</p>
</div>
<div>
<p class="MsoNormal">The problem is that this event can be fired after 
the destruction of SocketDescriptor's rtpInterface, meaning that the 
global variable "rtpInterface" inside SocketDescriptor points to a 
free'd address.</p>
</div>
<div>
<p class="MsoNormal">It appears that in our code this has never caused 
any troubles but now that we use libAsan it has come to our attention 
since Asan fire a segfault when memory corruption occurs, there are no 
false positives when using libAsan.</p>
</div>
<div>
<p class="MsoNormal"> </p>
</div>
<div>
<p class="MsoNormal">An example of the output when printing a line in RTPInterface::removeStreamSock<wbr>et and in ~RTPInterface:</p>
</div>
<div>
<p class="MsoNormal">...</p>
</div>
<div>
<p class="MsoNormal">Debug: removeStreamSocket @  0xad3056c8<br>
Debug: delete RTPInterface  0xad3056c8</p>
</div>
<div>
<p class="MsoNormal">Debug: removeStreamSocket @  0xad3056c8</p>
</div>
<div>
<p class="MsoNormal">...</p>
</div>
<div>
<p class="MsoNormal"> </p>
</div>
<div>
<p class="MsoNormal">As can be seen, after the RTPInterface was delete, removeStreamSocket is being called on the same rtpInterface ptr.</p>
</div>
<div>
<p class="MsoNormal">As it happens the code inside removeStreamSocket 
using the invalid ptr doesn't do anything wrong on our side, the first 
variable being tested is always NULL, a null check prevents that the 
code continues, this however is purely a coincidence.</p>
</div>
<div>
<p class="MsoNormal"> </p>
</div>
<div>
<p class="MsoNormal">I've modified ~SocketDescriptor for debugging, lookupRTPInterface(fStreamChan<wbr>nelId) yields 0x0 so that's another way of telling that something is wrong (see code below).</p>
</div>
<div>
<p class="MsoNormal">Can someone put the same debug prints in their live555 implementation so that it can be confirmed that there is a issue?</p>
</div>
<div>
<p class="MsoNormal"> </p>
</div>
<div>
<p class="MsoNormal">Regards,</p>
</div>
<div>
<p class="MsoNormal">Frederik</p>
</div>
<div>
<p class="MsoNormal"> </p>
</div>

SocketDescriptor::~SocketDescr<wbr>iptor() {<br>
    fEnv.taskScheduler().turnOffBa<wbr>ckgroundReadHandling(fOurSocke<wbr>tNum);<br>
    removeSocketDescription(fEnv, fOurSocketNum);<br>
    <br>
    if (fSubChannelHashTable != NULL) {<br>
        // Remove knowledge of this socket from any "RTPInterface"s that are using it:<br>
        HashTable::Iterator* iter = HashTable::Iterator::create(*f<wbr>SubChannelHashTable);<br>
        RTPInterface* rtpInterface;<br>
        char const* key;<br>
        <br>
        while ((rtpInterface = (RTPInterface*)(iter->next(key<wbr>))) != NULL) {<br>
            u_int64_t streamChannelIdLong = (u_int64_t)key;<br>
            unsigned char streamChannelId = (unsigned char)streamChannelIdLong;<br>
            <br>
            auto i = lookupRTPInterface(fStreamChan<wbr>nelId);<br>
            if (i == rtpInterface)<br>
            {<br>
                rtpInterface->removeStreamSock<wbr>et(fOurSocketNum, streamChannelId);<br>
            }<br>
            else<br>
            {<br>
                qDebug() << "lookupRTPInterface(fStreamCha<wbr>nnelId)
 (" << i << ") != rtpInterface (" << rtpInterface 
<< ") @ SocketDescriptor " << this;<br>
                // prevent further errors:<br>
                fServerRequestAlternativeByteH<wbr>andler = nullptr;<br>
            }<br>
        }<br>
        delete iter;<br>
        <br>
        // Then remove the hash table entries themselves, and then remove the hash table:<br>
        while (fSubChannelHashTable->RemoveN<wbr>ext() != NULL) {}<br>
        delete fSubChannelHashTable;<br>
    }<br>
    <br>
    // Finally:<br>
    if (fServerRequestAlternativeByte<wbr>Handler != NULL) {<br>
        // Hack: Pass a special character to our alternative byte handler, to tell it that either<br>
        // - an error occurred when reading the TCP socket, or<br>
        // - no error occurred, but it needs to take over control of the TCP socket once again.<br>
        u_int8_t specialChar = fReadErrorOccurred ? 0xFF : 0xFE;<br>
        (*fServerRequestAlternativeByt<wbr>eHandler)(fServerRequestAltern<wbr>ativeByteHandlerClientData, specialChar);<br>
    }<br>
}</div></div></div></div>