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
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: 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

Pull Requests

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-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 15:01:29 2024 UTC