php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #20738 MSSQL Crashes in PEAR DB and ADOdb
Submitted: 2002-11-30 12:38 UTC Modified: 2002-12-09 06:25 UTC
From: heyjohnlim at yahoo dot com Assigned:
Status: Closed Package: MSSQL related
PHP Version: 4.3.0RC2 OS: Win2000, IIS-CGI
Private report: No CVE-ID: None
 [2002-11-30 12:38 UTC] heyjohnlim at yahoo dot com
When doing testing with ADOdb and PEAR DB, the following scripts crash PHP (when the delete statement is executed) with an illegal memory reference at 0xffffffff. I tried to duplicate the problem with native mssql functions, but could not.

While tracing through in ADOdb, I found that the crash occurs during the PHP return statement, and not within mssql code. Perhaps some form of subtle stack/data corruption.

Thanks, John Lim

Other useful info
=================
MSSQL 2000 (MSDE)
PEAR DB from PHP 4.23
ADOdb 2.50


SCRIPT
======

<?php
error_reporting(E_ALL);
ini_set('mssql.datetimeconvert',0); 

function tmssql()
{
	print "<h3>mssql</h3>";
	$db = mssql_connect('JAGUAR\vsdotnet','adodb','natsoft') or die('No Connection');
	mssql_select_db('northwind',$db);
	
	$rs = mssql_query('select getdate() as date',$db);
	$o = mssql_fetch_row($rs);
	print_r($o);
	mssql_free_result($rs);
	
	print "<p>Delete</p>"; flush();
	$rs2 = mssql_query('delete from adoxyz',$db);
	$p = mssql_num_rows($rs2);
	mssql_free_result($rs2);

}

function tpear()
{
include_once('DB.php');

	print "<h3>PEAR</h3>";
	$username = 'adodb';
	$password = 'natsoft';
	$hostname = 'JAGUAR\vsdotnet';
	$databasename = 'northwind';
	
	$dsn = "mssql://$username:$password@$hostname/$databasename";
	$conn = &DB::connect($dsn);
	print "date=".$conn->GetOne('select getdate()')."<br>";
	@$conn->query('create table tester (id integer)');
	print "<p>Delete</p>"; flush();
	$rs = $conn->query('delete from tester');
/*** CRASH IN QUERY ABOVE ****/
	print "date=".$conn->GetOne('select getdate()')."<br>";
}

function tadodb()
{
include_once('../adodb.inc.php');

	print "<h3>ADOdb</h3>";
	$conn = NewADOConnection('mssql');
	$conn->Connect('JAGUAR\vsdotnet','adodb','natsoft','northwind');
//	$conn->debug=1;
	print "date=".$conn->GetOne('select getdate()')."<br>";
	$conn->Execute('create table tester (id integer)');
	print "<p>Delete</p>"; flush();
	$rs = $conn->Execute('delete from tester');
/*** CRASH IN EXECUTE ABOVE ****/
	print "date=".$conn->GetOne('select getdate()')."<br>";
}
?>
<a href=tmssql.php?do=tmssql>Test mssql</a>
<a href=tmssql.php?do=tpear>Test pear</a>
<a href=tmssql.php?do=tadodb>Test adodb</a>
<?php
if (!empty($_GET['do'])) {
	$do = $_GET['do'];
	$do();
}
?>

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2002-11-30 20:53 UTC] kalowsky@php.net
any chance you can cut your test script down to just a single line or two to prove this?
 [2002-12-01 02:01 UTC] heyjohnlim at yahoo dot com
Hi,

Just change the user id's and database in the scripts to match your mssql database and run the scripts. The script is self contained otherwise. I was only able to duplicate the problem with ADOdb and PEAR DB. Straight mssql_* works fine. So a one-liner is a bit difficult.

Regards, John
 [2002-12-01 02:01 UTC] heyjohnlim at yahoo dot com
Hi,

Just change the user id's and database in the scripts to match your mssql database and run the scripts. The script is self contained otherwise. I was only able to duplicate the problem with ADOdb and PEAR DB. Straight mssql_* works fine. So a one-liner is a bit difficult.

Regards, John
 [2002-12-01 23:46 UTC] heyjohnlim at yahoo dot com
This seems to be the problem  - i suspect.

Testing my existing SQL Server based sites with 4.3.0RC2 resulted in
many memory access violations and crashes.  I believe that I have
tracked these down to two different changes made to the MSSQL extension
since 4.2.3:

1) In version 1.82 of php_mssql.c there were 6 mallocs that were
changed from "emalloc(res_length + 1);" to "emalloc(res_length);".  I
believe, however, that the code that uses those memory blocks in at
least four of the cases required that extra space.  This is the code as
it is now for two of the changes in 4.3.0RC2:

res_buf = (unsigned char *) emalloc(res_length);
bin = ((DBBINARY *)dbdata(mssql_ptr->link, offset));
memcpy(res_buf, bin, res_length);
res_buf[res_length] = '\0';

It's the setting of res_buf[res_length] illegal, as that would be
beyond the bounds of emalloc(res_length)?  Also this code (appearing in
two of the changes):

res_length = 19;
res_buf = (unsigned char *) emalloc(res_length);
sprintf(res_buf, "%d-%02d-%02d %02d:%02d:%02d" ,  . . .

Since the length of the character string is going to be 19 characters,
isn't the sprintf going to write an ASCIIZ ending beyond the size of
res_buf?

Does the way emalloc() works take care of these problems?  Adding the
"+ 1" back to these four emalloc() calls stopped one set of crashes.

2) In version 1.83 of php_mssql.c the mssql_query() function was
altered from:

if ((num_fields = dbnumcols(mssql_ptr->link)) <= 0) {
RETURN_TRUE;
}

to:

if ((num_fields = dbnumcols(mssql_ptr->link)) <= 0 &&
!dbdataready(mssql_ptr->link)) {
RETURN_TRUE;
}

The CVS comment indicates that this change was for "fixing the
mssql_query to handle multiple results correct if the first result does
not return any data."  If I now call mssql_query() with a query that
doesn't return any values (like a SQL-T EXEC call), however, PHP will
crash (removing the new dbdataready() check eliminates the crash).

Michael Sisolak
msisolak@yahoo.com
 [2002-12-08 10:34 UTC] sniper@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php4-latest.tar.gz
 
For Windows:
 
  http://snaps.php.net/win32/php4-win32-latest.zip


 [2002-12-09 06:25 UTC] heyjohnlim at yahoo dot com
Beautiful - works nicely now!
 [2002-12-09 06:25 UTC] heyjohnlim at yahoo dot com
Closing
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 13:01:28 2024 UTC