php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #33965 [PATCH] NULL valued output parameter from stored procedures contain corrupt data
Submitted: 2005-08-02 14:01 UTC Modified: 2005-08-06 07:48 UTC
Votes:1
Avg. Score:1.0 ± 0.0
Reproduced:0 of 1 (0.0%)
From: paul dot robinson at groupbc dot com Assigned: fmk (profile)
Status: Closed Package: MSSQL related
PHP Version: 5CVS-2005-08-06 OS: Linux (RHEL 4)
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: paul dot robinson at groupbc dot com
New email:
PHP Version: OS:

 

 [2005-08-02 14:01 UTC] paul dot robinson at groupbc dot com
Description:
------------
MS SQL Server 2000, FreeTDS 0.63
Output parameters from a stored procedure call contain corrupt data when the result should be NULL. Its particularly noticable for variable length strings as output looks as though it just reads from a random pointer until it find a \0 !

No test is done on whether the output is NULL or not.

Diff below shows proposed change to fix this.
NOTE: This calls a function dbretisnull that is not currently implemented in the FreeTDS package but has been submitted as a proposed change.

19c19
< /* $Id: php_mssql.c,v 1.137.2.9 2005/04/12 17:46:06 fmk Exp $ */
---
> /* $Id: php_mssql.c,v 1.137.2.8 2005/02/25 23:25:33 fmk Exp $ */
324,326d323
< #ifndef HAVE_FREETDS
<       dbwinexit();
< #else
328d324
< #endif
978c974
<       int i, num_rets, type;
---
>       int i, num_rets, type, is_null;
992,1019c988,1022
<                                       switch (type) {
<                                               case SQLBIT:
<                                               case SQLINT1:
<                                               case SQLINT2:
<                                               case SQLINT4:
<                                                       convert_to_long_ex(&bind->zval);
<                                                       /* FIXME this works only on little endian machine !!! */
<                                                       Z_LVAL_P(bind->zval) = *((int *)(dbretdata(mssql_ptr->link,i)));
<                                                       break;
< 
<                                               case SQLFLT4:
<                                               case SQLFLT8:
<                                               case SQLFLTN:
<                                               case SQLMONEY4:
<                                               case SQLMONEY:
<                                               case SQLMONEYN:
<                                                       convert_to_double_ex(&bind->zval);
<                                                       Z_DVAL_P(bind->zval) = *((double *)(dbretdata(mssql_ptr->link,i)));
<                                                       break;
< 
<                                               case SQLCHAR:
<                                               case SQLVARCHAR:
<                                               case SQLTEXT:
<                                                       convert_to_string_ex(&bind->zval);
<                                                       Z_STRLEN_P(bind->zval) = dbretlen(mssql_ptr->link,i);
<                                                       Z_STRVAL_P(bind->zval) = estrndup(dbretdata(mssql_ptr->link,i),Z_STRLEN_P(bind->zval));
<                                                       break;
<                                               /* TODO binary */
---
>                                       /* Test column value for null flag and set value as required */
>                                       is_null = dbretisnull(mssql_ptr->link, i);
>                                       if (is_null) {
>                                               ZVAL_NULL(bind->zval);
>                                       }
>                                       else {
>                                               switch (type) {
>                                                       case SQLBIT:
>                                                       case SQLINT1:
>                                                       case SQLINT2:
>                                                       case SQLINT4:
>                                                               convert_to_long_ex(&bind->zval);
>                                                               /* FIXME this works only on little endian machine !!! */
>                                                               Z_LVAL_P(bind->zval) = *((int *)(dbretdata(mssql_ptr->link,i)));
>                                                               break;
> 
>                                                       case SQLFLT4:
>                                                       case SQLFLT8:
>                                                       case SQLFLTN:
>                                                       case SQLMONEY4:
>                                                       case SQLMONEY:
>                                                       case SQLMONEYN:
>                                                               convert_to_double_ex(&bind->zval);
>                                                               Z_DVAL_P(bind->zval) = *((double *)(dbretdata(mssql_ptr->link,i)));
>                                                               break;
> 
>                                                       case SQLCHAR:
>                                                       case SQLVARCHAR:
>                                                       case SQLTEXT:
>                                                               convert_to_string_ex(&bind->zval);
>                                                               Z_STRLEN_P(bind->zval) = dbretlen(mssql_ptr->link,i);
>                                                               Z_STRVAL_P(bind->zval) = estrndup(dbretdata(mssql_ptr->link,i),Z_STRLEN_P(bind->zval));
>                                                               break;
>                                                       /* TODO binary */
>                                               }

Reproduce code:
---------------
function if_null($out) {
	if(is_null($out)) {	return 'null';	}
	else {	return $out; }
}
$int0out =-1;
$varchar0out = -1;
$conn = mssql_connect (DBSERVER, USER, PASS);
mssql_select_db(DBDATABASE, $conn)
$query = mssql_init('usp_output_test', $conn);
mssql_bind($query, "@int0out", $int0out, SQLINT4, true, false);
mssql_bind($query, "@varchar0out", $varchar0out, SQLVARCHAR, true, false, 10);
$myset = mssql_execute($query);
if($line = mssql_fetch_array($myset)) {
	print "there was a result set!";
}
else {
	print "no resultset";
}
print if_null($int0out). " --int0out output</br>";
print if_null($varchar0out). " --varchar0out output</br>";		


Expected result:
----------------
null --int0out output
null --varchar0out output

Actual result:
--------------
null --int0out output
82$&#9508;,&#9565;d&#9829;n&#9555; --varchar0out output

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-08-02 18:34 UTC] sniper@php.net
Please try using this CVS snapshot:

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


 [2005-08-02 18:50 UTC] paul dot robinson at groupbc dot com
Patches suggested are against Snapshot: php5-STABLE-200508021038.tar.gz

Although I haven't actually built an example using that snapshot today I have looked at the code which since it is unchanged would seem to exhibit the same problem.
 [2005-08-02 19:12 UTC] sniper@php.net
Provide patches in unified diff format (diff -u) and against PHP CVS HEAD (we're not likely to release any 5.0.x versions anymore). Put the diffs somewhere were people can download it and put the URLs here.




 [2005-08-05 16:57 UTC] paul dot robinson at groupbc dot com
Patch against php_mssql.c CVS version 1.149 can be found here:
http://cobweb.businesscollaborator.com/pdr/33965.patch

Rationale behind the patch was discussed here:
http://lists.ibiblio.org/pipermail/freetds/2005q3/018851.html
This has been verified to work with FreeTDS releases _after_ 0.63.
Without this patch output parameters that should be null will simply read random data.
 [2005-08-06 01:30 UTC] sniper@php.net
Frank, can you check this out?

 [2005-08-06 07:48 UTC] fmk@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.


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Dec 22 02:01:28 2024 UTC