php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #29583 [PATCH] com_dotnet crashes when trying to strlen
Submitted: 2004-08-09 11:54 UTC Modified: 2005-04-18 18:23 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (100.0%)
From: edwin at rabbito dot org Assigned: wez
Status: Closed Package: COM related
PHP Version: 5CVS-2005-02-15 OS: Windows
Private report: No CVE-ID:
 [2004-08-09 11:54 UTC] edwin at rabbito dot org
Description:
------------
When trying to retrieve a date field from an Access 97 database, the actual data returned is different from PHP4 (PHP 4 returns a timestamp, whereas PHP 5 returns a date, ie) 02/04/04 instead of a timestamp). By calling the code (as attached) in PHP5, PHP does not return error gracefully, but crashes.

(seems to be something that is not yet fixed in bug#29392)

Reproduce code:
---------------
   $security="C:\access97.mdw";
   $user="access";
   $password="access";
   $dsn="Driver={Microsoft Access Driver (*.mdb)}; DBQ=$database;SystemDB=$security;Uid=$user;Pwd=$password";

   $db = new COM("ADODB.Connection");
   $db->open($dsn);

   $query="SELECT DateField1 FROM [Table1];";
   $rs = $db->execute($query);
   if (!$rs->EOF()) {
     echo strlen($rs->Fields(0)->Value);
   }


Expected result:
----------------
Either an error should be returned due to invalid type ($rs->Fields(0)->Value in date type), or the actual length the the date string.

Actual result:
--------------
PHP crashed

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2004-08-09 12:44 UTC] wez@php.net
Crash or exception?
Paste the output you see from the CLI here please.
 [2004-08-10 03:22 UTC] edwin at rabbito dot org
There is no output from the CLI, apart from the Dr. Watson exception dialog:

An application error has occurred and an application error log is being generated. 

php.exe

Exception: access violation (0xc0000005), Address: 0x1008a9de.
 [2004-09-02 21:00 UTC] msisolak at yahoo dot com
I've dug into the COM error reported here and believe I have discovered the issue.  The problem is that com_object_cast() (in com_handlers.c) assumes that the readobj and writeobj parameters will never be the same object.  That appears to work fine, except when the type conversion request comes from the convert_object_to_type() macro (zend_operators.c, line 264).  In this case readobj == writeobj and we end up with an access violation.  Since _convert_to_string() uses convert_object_to_type(), and _convert_to_string() is used when you try to strlen() an object, com_object_cast() fails in the code from this bug report.

Based on using sxe_object_cast() from the SimpleXML extension as a example, I think that the freeing of the writeobj needs to be the last thing done in the function rather than the first.  The attached patch uses that function as a model to move the zval_dtor() call to the end.  I also feel that the ZVAL_NULL(writeobj) should move after the CDNO_FETCH(readobj).  It seems to work as is, but only becuase CDNO_FETCH() isn't checking that what is passed to it is really an object.

I've played with this patch some and it seems to be holding, but I'm looking at this with limited understanding of how the objects are really being passed around so there may be an interaction here I'm not seeing.  With the patch applied, this PHP code:

echo strlen($rs->Fields(0)->Value), "\n";
echo date("F j, Y", variant_date_to_timestamp($rs->Fields(0)->Value)), "\n";
echo date("F j, Y", variant_date_to_timestamp($rs->Fields(0))), "\n";
echo $rs->Fields(0)->Value, "\n";
echo $rs->Fields(0), "\n";

returns correct values in all five cases (for my test database):

8
January 1, 2001
January 1, 2001
1/1/2001
1/1/2001



--- php-5.0.1\ext\com_dotnet\com_handlers.c	Wed Jul 28 19:48:26 2004
+++ com_handlers.c	Thu Aug 19 15:18:45 2004
@@ -521,17 +521,17 @@
 
 static int com_object_cast(zval *readobj, zval *writeobj, int type, 
int should_free TSRMLS_DC)
 {
+	zval free_obj;
 	php_com_dotnet_object *obj;
 	VARIANT v;
 	VARTYPE vt = VT_EMPTY;
 
 	if (should_free) {
-		zval_dtor(writeobj);
+		free_obj = *writeobj;
 	}
 
-	ZVAL_NULL(writeobj);
-
 	obj = CDNO_FETCH(readobj);
+	ZVAL_NULL(writeobj);
 	VariantInit(&v);
 
 	if (V_VT(&obj->v) == VT_DISPATCH) {
@@ -569,6 +569,9 @@
 
 	php_com_zval_from_variant(writeobj, &v, obj->code_page TSRMLS_CC);
 	VariantClear(&v);
+	if (should_free) {
+		zval_dtor(&free_obj);
+	}
 	return SUCCESS;
 }
 [2005-02-15 15:23 UTC] edwin at rabbito dot org
Works after applying "msisolak at yahoo dot com"'s patch on latest CVS
 [2005-03-25 01:24 UTC] sniper@php.net
Wez, there's even a patch in this one..

 [2005-03-25 01:26 UTC] sniper@php.net
See also bug #31636

 [2005-04-18 18:23 UTC] wez@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.

Committed at last.
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Mon Apr 21 10:02:10 2014 UTC