From:             paul dot robinson at groupbc dot com
Operating system: Linux (RHEL 4)
PHP version:      5.0.4
PHP Bug Type:     MSSQL related
Bug description:  NULL valued output parameters from stored procedures contain 
corrupt data

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

-- 
Edit bug report at http://bugs.php.net/?id=33965&edit=1
-- 
Try a CVS snapshot (php4):   http://bugs.php.net/fix.php?id=33965&r=trysnapshot4
Try a CVS snapshot (php5.0): 
http://bugs.php.net/fix.php?id=33965&r=trysnapshot50
Try a CVS snapshot (php5.1): 
http://bugs.php.net/fix.php?id=33965&r=trysnapshot51
Fixed in CVS:                http://bugs.php.net/fix.php?id=33965&r=fixedcvs
Fixed in release:            http://bugs.php.net/fix.php?id=33965&r=alreadyfixed
Need backtrace:              http://bugs.php.net/fix.php?id=33965&r=needtrace
Need Reproduce Script:       http://bugs.php.net/fix.php?id=33965&r=needscript
Try newer version:           http://bugs.php.net/fix.php?id=33965&r=oldversion
Not developer issue:         http://bugs.php.net/fix.php?id=33965&r=support
Expected behavior:           http://bugs.php.net/fix.php?id=33965&r=notwrong
Not enough info:             
http://bugs.php.net/fix.php?id=33965&r=notenoughinfo
Submitted twice:             
http://bugs.php.net/fix.php?id=33965&r=submittedtwice
register_globals:            http://bugs.php.net/fix.php?id=33965&r=globals
PHP 3 support discontinued:  http://bugs.php.net/fix.php?id=33965&r=php3
Daylight Savings:            http://bugs.php.net/fix.php?id=33965&r=dst
IIS Stability:               http://bugs.php.net/fix.php?id=33965&r=isapi
Install GNU Sed:             http://bugs.php.net/fix.php?id=33965&r=gnused
Floating point limitations:  http://bugs.php.net/fix.php?id=33965&r=float
No Zend Extensions:          http://bugs.php.net/fix.php?id=33965&r=nozend
MySQL Configuration Error:   http://bugs.php.net/fix.php?id=33965&r=mysqlcfg

Reply via email to