php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #23142 datalen parameter is not correctly set when calling stored procedures
Submitted: 2003-04-09 17:50 UTC Modified: 2003-05-03 06:53 UTC
From: arnarb at oddi dot is Assigned:
Status: Not a bug Package: MSSQL related
PHP Version: 4CVS.. OS: Linux 2.4.18
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: arnarb at oddi dot is
New email:
PHP Version: OS:

 

 [2003-04-09 17:50 UTC] arnarb at oddi dot is
When calling a stored procedure on MS-SQL Server 7.0 and 2000 via the mssql_init, mssql_bind and mssql_execute functions, the size of parameters is always set to -1. This causes the FreeTDS library to segfault in a memcpy.

I'm running php 4.3.1 on an apache 1.2.24 linked with FreeTDS 0.61.

This is easily fixed on one line in ext/mssql/php_mssql.c by changing line 1966 (in the 4.3.1 release) from
  datalen = -1;
to
  datalen = tds_get_size_by_type(type);

I checked tis file in the CVS repository and the latest revision still contains this bug. This seems to fix the problem for me but I haven't tested it thoroughly and I since I'm not familiar enough with the code I don't know if it breaks anything else.

Steps to reproduce:
This assumes that the default "pubs" demo database is set up the sql server. Run the following script:

($link = mssql_connect("test", "sa", "supervisor")) || die("1");;
mssql_select_db("pubs", $link) || die("2");
print(mssql_get_last_message());

$stmt = mssql_init("byroyalty", $link);
$p = 50;
mssql_bind($stmt, "@percentage", $p, SQLINT2);
$result = mssql_execute($stmt);

print(mssql_get_last_message());
print("<table border=1>\n");
while ($line = mssql_fetch_array($result)) {
   print("\t<tr>\n");
   foreach ($line as $field) {
      print("\t\t<td>$field</td>\n");
   }
   print("\t</tr>\n");
}

?>

Follwing is some output from gdb including a backtrace:

arnarb@kassi:~/public_html/mssqltests$ gdb php            
GNU gdb 5.2
(gdb) run < test1.php
Starting program: /usr/bin/php < test1.php

Program received signal SIGSEGV, Segmentation fault.
0x406d8e37 in memcpy (dstpp=0x83f7634, srcpp=0x83e3984, len=4294967295) at ../sysdeps/generic/memcpy.c:55
55      ../sysdeps/generic/memcpy.c: No such file or directory.
        in ../sysdeps/generic/memcpy.c
(gdb) bt
#0  0x406d8e37 in memcpy (dstpp=0x83f7634, srcpp=0x83e3984, len=4294967295) at ../sysdeps/generic/memcpy.c:55
#1  0x404a8f1d in param_row_alloc (params=0x83f7600, curcol=0x83f74b8, value=0x83e3984, size=-1) at rpc.c:217
#2  0x404a9022 in param_info_alloc (rpc=0x83e43a0) at rpc.c:261
#3  0x404a8e8b in dbrpcsend (dbproc=0x83e3b10) at rpc.c:192
#4  0x08106f1b in zif_mssql_execute (ht=1, return_value=0x83e3964, this_ptr=0x0, return_value_used=1)
    at /usr/src/php-4.3.1/ext/mssql/php_mssql.c:2044
#5  0x081f5803 in execute (op_array=0x83df7b4) at /usr/src/php-4.3.1/Zend/zend_execute.c:1598
#6  0x081e3f0e in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /usr/src/php-4.3.1/Zend/zend.c:864
#7  0x081bc68a in php_execute_script (primary_file=0xbffff788) at /usr/src/php-4.3.1/main/main.c:1573
#8  0x08206dfc in main (argc=1, argv=0xbffff804) at /usr/src/php-4.3.1/sapi/cli/php_cli.c:746
#9  0x4067b17d in __libc_start_main (main=0x820644c <main>, argc=1, ubp_av=0xbffff804, init=0x8081e2c <_init>, 
    fini=0x82581d0 <_fini>, rtld_fini=0x4000a534 <_dl_fini>, stack_end=0xbffff7fc)
    at ../sysdeps/generic/libc-start.c:129
(gdb) p params
No symbol "params" in current context.
(gdb) select 1
(gdb) p params
$1 = (TDSPARAMINFO *) 0x83f7600
(gdb) p *params
$2 = {num_cols = 1, columns = 0x83e45e0, row_size = 8, null_info_size = 4, current_row = 0x83f7630 "", 
  rows_exist = 0, row_count = 0, computeid = 0, more_results = 0 '\0', bycolumns = 0x0, by_cols = 0}
(gdb) p *curcol
$3 = {column_type = 52, column_type_save = 52, column_usertype = 0, column_flags = 0, column_size = 2, 
  column_varint_size = 0 '\0', column_prec = 0 '\0', column_scale = 0 '\0', column_namelen = 0 '\0', 
  column_name = "@percentage", '\0' <repeats 244 times>, column_offset = 4, column_nullable = 0, 
  column_writeable = 0, column_identity = 0, column_unicodedata = 0, column_output = 0, 
  column_collation = "\0\0\0\0", column_operator = 0 '\0', column_operand = 0, column_cur_size = -1, 
  column_bindtype = 0, column_bindfmt = 0, column_bindlen = 0, column_nullbind = 0x0, column_varaddr = 0x0, 
  column_lenbind = 0x0, column_textpos = 0, column_text_sqlgetdatapos = 0}
(gdb) p params->current_row
$4 = (unsigned char *) 0x83f7630 ""
(gdb) p *value
Attempt to dereference a generic pointer.
(gdb) p value
$5 = (void *) 0x83e3984
(gdb) p (int) *value
Attempt to dereference a generic pointer.
(gdb) p *((int*) value)
$6 = 50
(gdb) p size
$7 = -1
(gdb) select 2
(gdb) p *p
$8 = {next = 0x0, name = 0x83e45d0 "@percentage", status = 0 '\0', type = 52, maxlen = -1, datalen = -1, 
  value = 0x83e3984 "2"}
(gdb) p ((int*) p->value)
$9 = (int *) 0x83e3984
(gdb) p *((int*) p->value)
$10 = 50
(gdb) select 4
(gdb) p mssql_statement
Attempt to use a type name as an expression
(gdb) p statement      
$11 = (mssql_statement *) 0x83e39dc
(gdb) p *statement
$12 = {id = 2, link = 0x83dfbd4, binds = 0x83e44c4, executed = 0}
(gdb) p statement->binds
$13 = (HashTable *) 0x83e44c4
(gdb) p *(statement->binds)
$14 = {nTableSize = 16, nTableMask = 15, nNumOfElements = 1, nNextFreeElement = 0, 
  pInternalPointer = 0x83e457c, pListHead = 0x83e457c, pListTail = 0x83e457c, arBuckets = 0x83e452c, 
  pDestructor = 0x810224c <_mssql_bind_hash_dtor>, persistent = 0 '\0', nApplyCount = 0 '\0', 
  bApplyProtection = 1 '\001'}
(gdb) p mssql_ptr
$15 = (mssql_link *) 0x83dfbd4
(gdb) p *mssql_ptr
$16 = {login = 0x83d8f90, link = 0x83e3b10, valid = 1}
(gdb) p *(mssql_ptr->link)
$17 = {tds_socket = 0x83e4238, row_buf = {buffering_on = 1, first_in_buf = 0, next_row = 1, newest = -1, 
    oldest = 0, elcount = 2, element_size = 0, rows_in_buf = 0, rows = 0x0}, noautofree = 0, more_results = 1, 
  empty_result = 0, user_data = 0x0, dbbuf = 0x0, dbbufsz = 0, text_size = 0, text_sent = 0, 
  bcp_hostfile = 0x0, bcp_errorfile = 0x0, bcp_tablename = 0x0, bcp_insert_stmt = 0x0, bcp_direction = 0, 
  bcp_colcount = 0, host_colcount = 0, bcp_columns = 0x0, host_columns = 0x0, firstrow = 0, lastrow = 0, 
  maxerrs = 0, bcpbatch = 0, sendrow_init = 0, var_cols = 0, typeinfo = {precision = 0, scale = 0}, 
  avail_flag = 0 '\0', dbopts = 0x83e3bf8, dboptcmd = 0x0, bcp = {hint = 0x0}, rpc = 0x83e43a0, 
  envchange_rcv = 1, dbcurdb = "pubs", '\0' <repeats 26 times>, servcharset = "iso_1", '\0' <repeats 25 times>}
(gdb) p *(mssql_ptr->link->rpc)
$18 = {next = 0x0, name = 0x83e43b8 "byroyalty", options = 0, param_list = 0x83e45b0}
(gdb) p *(mssql_ptr->link->rpc->param_list)
$19 = {next = 0x0, name = 0x83e45d0 "@percentage", status = 0 '\0', type = 52, maxlen = -1, datalen = -1, 
  value = 0x83e3984 "2"}

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2003-04-23 08:59 UTC] arnarb at oddi dot is
The bug is still present in the latest snapshot (as of April 23, 2003).
 [2003-05-03 06:53 UTC] arnarb at oddi dot is
This seems to be a bug in FreeTDS. Both the MSSQL and Sybase documentation state that for variables of fixed length, datalen _should_ be set to -1.

Sorry for the inconvenience.
 
PHP Copyright © 2001-2022 The PHP Group
All rights reserved.
Last updated: Tue May 17 03:03:35 2022 UTC