[ previous ] [ next ] [ threads ]
 To :  yate@v...
 From :  Alexander Kovalenko <alexander.kovalenko@g...>
 Subject :  Memory corruption in extmodule.yate
 Date :  Mon, 14 Jun 2010 15:17:25 +0300
Greetings.

There is bug in extmodule.yate when something opens and closes socket 
very fast. It seems this bug causes access violation error in free() and 
malloc() calls in different places in application. Also sometimes 
extmodule may hang in ExtModReceiver::start().
Steps to reproduce in Windows:
1) Install Microsoft Application Verifier
2) Add yate-qt4.exe as application to verify
3) Configure extmodule to listen to some port. Run yate-qt4.exe
4) Run "nmap -sT -O  -p "
Result: application will crash and Application Verifier will report 
"First chance access violation for current stack trace" error. This 
problem exists either in Yate-2.2.0-1 or in Yate-3.0.0-alpha3.
When port extmodule listens to is opened, ExtModReceiver::start() is 
called. ExtModReceiver::start() runs new ExtThread. When ExtThread is 
finished it deletes instance of ExtModReceiver. If port is closed very 
fast this ExtThread may delete ExtModReceiver before 
ExtModReceiver::start() will be finished. In this case 
ExtModReceiver::start() tries to access memory which has been already 
deleted.
There is a workaround in the attachment. This is patch against 
yate-2.2.0-1.tar.gz. It just adds Thread::sleep(1) to give 
ExtModReceiver::start() time to finish. I know this is not the best 
solution but it seems to work. Maybe somebody will suggest better variant.
Also Thread::check(false) was added to ExtModReceiver::run() to get rid 
of "Could not kill %p but seems OK to delete it (library bug?)" message.

WBR, Alexander Kovalenko, www.ardas.dp.ua



diff -crB yate-2.2.0-1/modules/extmodule.cpp yate-2.2.0-1-patched/modules/extmodule.cpp
*** yate-2.2.0-1/modules/extmodule.cpp	Mon Mar  8 10:17:51 2010
--- yate-2.2.0-1-patched/modules/extmodule.cpp	Mon Jun 14 08:40:56 2010
***************
*** 1059,1064 ****
--- 1059,1067 ----
      bool invalid = true;
      DDebug(DebugAll,"ExtModReceiver::run() entering loop [%p]",this);
      for (;;) {
+ 	if (Thread::check(false)) {
+ 	    break;
+ 	}
  	use();
  	lock();
  	int readsize = m_in ? m_in->readData(buffer+posinbuf,sizeof(buffer)-posinbuf-1) : 0;
***************
*** 1073,1080 ****
  	    if (invalid)
  		Debug("ExtModule",DebugWarn,"Never got anything valid from '%s' '%s'",
  		m_script.c_str(),m_args.safe());
! 	    if (m_chan && m_chan->running())
! 		Thread::sleep(1);
  	    break;
  	}
  	else if (readsize < 0) {
--- 1076,1083 ----
  	    if (invalid)
  		Debug("ExtModule",DebugWarn,"Never got anything valid from '%s' '%s'",
  		m_script.c_str(),m_args.safe());
! 	    //give ExtModReceiver::start() time to quit
! 	    Thread::sleep(1);
  	    break;
  	}
  	else if (readsize < 0) {
***************
*** 1085,1090 ****
--- 1088,1095 ----
  		continue;
  	    }
  	    Debug("ExtModule",DebugWarn,"Read error %d on %p [%p]",errno,m_in,this);
+ 	    //give ExtModReceiver::start() time to quit
+ 	    Thread::sleep(1);
  	    break;
  	}
  	XDebug(DebugAll,"ExtModReceiver::run() read %d",readsize);