php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #4768 zend_get_parameters_ex() trashes parameters if param_count < ARG_COUNT(ht)
Submitted: 2000-06-02 09:54 UTC Modified: 2000-06-10 03:08 UTC
From: clcollie at mindspring dot com Assigned:
Status: Closed Package: Scripting Engine problem
PHP Version: 4.0 Release Candidate 2 OS: Linux (Mandrake 7.0)
Private report: No CVE-ID: None
 [2000-06-02 09:54 UTC] clcollie at mindspring dot com
Synopsis:
 it appears that zend_get_parameter_array_ex() may corrupt values if called for
param_count < ARG_COUNT(ht)

Background:
im in the process of implementing an ANSI like sscanf() and fscanf(). a common
routine, php_internal_sscanf(), is referenced by both routines to perform the
actual work. 

	PHPAPI int php_internal_sscanf(char *string,char *format, int ht,int
varstart,zval **return_value)

the prototype for (f|s)scanf() is :

	mixed sscanf($string,$format,...)
	mixed sscanf($file_handle,$format,...)

(f|s)scanf works in two modes : with and without variables passed by reference.
without variables, it returns an array of elements parsed from the literal
string. this seems to work fine (subject to further testing). when variables
are passed in, the function modifies the variables directly (as in "c"). 
this is where the issue lies. every time i pass in more than 2 variables, the
value of the first two variables are hosed.

Details:
in PHP_FUNCTION(sscanf) i do the following :

	if ((ARG_COUNT(ht) < 2) || (zend_get_parameters_ex(ht,2,&literal,&format)
== FAILURE)) {
		WRONG_PARAM_COUNT;
	}
	convert_to_string_ex( literal );
	convert_to_string_ex( format );
	php_internal_sscanf( (*literal)->value.str.val,
						 (*format)->value.str.val,
						 ht, 2, &return_value );

in php_sscanf_internal, i check the validity of format, then i grab the
all the other parameters as an array from ht :
	
	zval ***args
	args	= (zval ***)emalloc(ARG_COUNT(ht) * sizeof(zval **));
	if (zend_get_parameters_array_ex(ARG_COUNT(ht), args) == FAILURE) {
		efree(args);
		COMPLAIN_LOUDLY;      /* you get the point */
		return FAILURE
	}
i need to do things in this two-phase this way to allow the internal scanning
routine to do work for both fscanf() and scanf(). actually in my testing, it
does not even reach this far (the validation above it fails on the bogus
values).

Setup:
Linux Mandrake 7.0 running on a Pentium (classic) 166Mhz, 64M.
PHP 4.0.0
'./configure' '--with-apxs' '--enable-calendar' '--with-gd=shared' '--with-imap'
'--with-mcal=/usr/local/lib' '--with-mysql' '--with-pgsql' '--enable-trans-sid'
'--enable-wddx' '--enable-sysvshm' '--enable-sysvmem' '--with-regex=php'
'--with-gdbm' '--with-mhash' '--enable-memory_limit' '--enable-ftp'
'--with-cybercash' '--with-ldap'
thread safety disabled
allow_call_time_pass_reference on


Analysis :
as far as i can reduce it, the problem seems to be in PHP_FUNCTION(sscanf) with
the zend_get_parameters_ex() function. if only two parameters are passed in,
then all is well. if more parameters are passed than is first retrieved, then
the values assigned to the first two variables are either "", "-1", or "0" .
i verified this by inserting zend_printf() calls just as after the
convert_to_string_ex() calls to output the values of the string variables.

Postscript:
just to investigate other alternatives, i changed the prototype for php_scanf_internal to :

   PHPAPI int php_sscanf_internal(char *string,char *format,int ht,int argCount,zval ***args,
				int varStart,pval **return_value);

(note ht is needed to be able to check that all variables are passed by reference)				
i made the corresponding changes in PHP_FUNCTION(sscanf) and PHP_FUNCTION(fscanf) to read the
entire param array, getting the appropriate values from there, then passing the array
php_sscanf_internal(). from initial indications, it seems to pass values correctly, backing my
feeling that zend_get_parameters_ex() may be doing something funny.


Bottom Line:
any insight is appreciated. if this is a WAD, then it should be note in the developer
documentation to spare someone else the trouble.



clayton collie
PHP Enthusiast (PHPnut!)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2000-06-09 12:01 UTC] andi at cvs dot php dot net
I don't quite understand what you're describing. The get_parameters function doesn't have side effects and can actually be called more than once (although that is probably not the right way to do things). Are you still having this problem? Any chance you can send a small reproducing example?
 [2000-06-10 03:08 UTC] zeev at cvs dot php dot net
Calling the various zend_get_parameters() functions with param_count being smaller than arg_count, would result in the last arguments begin returned, instead of the first ones.

For example, if you only read 2 arguments out of 3 in function foo(), foo(1,2,3) would return '2' and '3', instead of '1' and '2'.

This is fixed in the latest CVS.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 20:01:28 2024 UTC