FAQ
Hello,

i try to write an extension for PHP. But I have problems managing the
memory correctly.

Every time I try to run the attached script, I get segmentation errors,
after the script is finished. I could not work out what the problem is.
I guess I am using one of the Zend/PHP API functions wrongly, but even
studying the source of the API functions didn’t help me to find my
memory problem.
I think I am freeing some memory which I shouldn’t free, ore I pass a
zval structure without increasing the refcount where I should do so,..

I hope someone of you more experienced PHP programmers has the time to
have a look at my code, I don’t know where to look anymore.

Thx
Jan Gerritsen


This is the relevant Code of my extension, the PHP script i use for
testing is below. The function which get called first is
PHP_FUNCTION(url_quote_data).



static void url_quote_string_wrapper(char * src_str, int src_str_leng,
char ** quoted_str, int * quoted_str_leng)
{

// allocate temp_buffer, O(src_str_leng) == 3 * src_str_leng
char * buffer =
(char *) emalloc( sizeof(char) * (src_str_leng * 3 + 1) );

// Quote special chars
int src_count, dest_count;
for(src_count = dest_count=0; src_count<src_str_leng; ++src_count)
{
switch(src_str[src_count])
{
case '"' :
buffer[dest_count++] = '%';
buffer[dest_count++] = '2';
buffer[dest_count++] = '2';
break;
case '\'' :
buffer[dest_count++] = '%';
buffer[dest_count++] = '2';
buffer[dest_count++] = '7';
break;
case '.' :
buffer[dest_count++] = '%';
buffer[dest_count++] = '2';
buffer[dest_count++] = 'E';
break;
case '/' :
buffer[dest_count++] = '%';
buffer[dest_count++] = '2';
buffer[dest_count++] = 'F';
break;
case '\\' :
buffer[dest_count++] = '%';
buffer[dest_count++] = '5';
buffer[dest_count++] = 'C';
break;
default :
buffer[dest_count++] = src_str[src_count];
break;
}
}

// Terminate buffer string
buffer[dest_count] = 0;

// Save buffer
(*quoted_str) = (char*) safe_estrndup(buffer, dest_count);
(*quoted_str_leng) = dest_count;

// Free temporary used memory
efree(buffer);
}


static void url_quote_data_wrapper(HashTable *src_ht,
HashTable *dest_ht,
void (*quote_function)(char *, int, char **, int *))

static int rec_counter = 0;

zval **src_ht_entry;

/* Get start postion of the array */
HashPosition pos;
zend_hash_internal_pointer_reset_ex(src_ht, &pos);

/* For each element of the array */
while ( zend_hash_get_current_data_ex(src_ht,
(void **)&src_ht_entry, &pos) == SUCCESS)
{
/*
Quote array key
*/
char *key_str = NULL;
uint key_str_len = 0;
ulong key_num = 0;
int quoted_key_str_leng = 0;
char * quoted_key_str = NULL;
switch (zend_hash_get_current_key_ex(src_ht,
&key_str, &key_str_len, &key_num, 0, &pos))
{
case HASH_KEY_IS_STRING:
quote_function(key_str, key_str_len,
&quoted_key_str, &quoted_key_str_leng);
key_str = NULL;
key_str_len = 0;
break;

case HASH_KEY_IS_LONG:
key_str = (char *) emalloc(255);
snprintf(key_str, 255, "%d", key_num);
key_str_len = strlen(key_str) + 1;

quote_function(key_str, key_str_len,
&quoted_key_str, &quoted_key_str_leng);
efree(key_str);
key_str = NULL;
key_str_len = 0;
break;

default:
continue;
break;
}

/*
Quote array data
*/
zval *quoted_data;
if( (*src_ht_entry)->type == IS_ARRAY )
{
/* It is an array, start recursiv call */
MAKE_STD_ZVAL(quoted_data);
array_init(quoted_data);
rec_counter++;
url_quote_data_wrapper(Z_ARRVAL_PP(src_ht_entry),
Z_ARRVAL_P(quoted_data), quote_function);
rec_counter--;

}
else
{
/* Convert data to string and quote it */

SEPARATE_ZVAL(src_ht_entry);
convert_to_string_ex(src_ht_entry);

int data_buffer_used;
char * data_buffer;
quote_function(Z_STRVAL_PP(src_ht_entry),
Z_STRLEN_PP(src_ht_entry), &data_buffer,
&data_buffer_used);

MAKE_STD_ZVAL(quoted_data);
ZVAL_STRINGL(quoted_data, data_buffer, data_buffer_used, 0);
zval_dtor(*src_ht_entry); // delete seperated zval
}

/*
Add data to array
*/
quoted_data->refcount++;
if( zend_hash_add(dest_ht, quoted_key_str, quoted_key_str_leng,
&quoted_data, sizeof(zval*), NULL) == FAILURE )
{
zend_error(E_ERROR, "Update of ht failed");
}
efree(quoted_key_str);

// Step forward in array
zend_hash_move_forward_ex(src_ht, &pos);
}
}


/* {{{ proto array url_quote_data(array array_to_quote [, bool quote])
*/
PHP_FUNCTION(url_quote_data)
{
int argument_count = ZEND_NUM_ARGS();
if( argument_count != 1 && argument_count != 2 ) {
WRONG_PARAM_COUNT;
}

zval *array_to_quote;
zend_bool quote;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b",
&array_to_quote, &quote) == FAILURE)
{
RETURN_FALSE;
}

// Check if we have to quote, or dequote the array keys and values
void (*quote_function)(char *, int, char **, int *);
if( argument_count == 2 && ! quote )
{
quote_function = url_dequote_string_wrapper;
}
else
{
quote_function = url_quote_string_wrapper;
}

// Call quote function
array_init(return_value);
url_quote_data_wrapper(Z_ARRVAL_P(array_to_quote),
Z_ARRVAL_P(return_value), quote_function);
}
/* }}} */


/*****************************************************/
PHP Script

<?php
if(!extension_loaded('url')) {
dl('url.' . PHP_SHLIB_SUFFIX);
}

$url = new URL_base();

$data = array(
"aaa\"aaa" => "aaa\"aaa'aaa.aaa/aaa\\aaa",
"aaa'aaa" => "aaa\"aaa'aaa.aaa/aaa\\aaa",
"aaa.aaa" => "aaa\"aaa'aaa.aaa/aaa\\aaa",
"aaa/aaa" => "aaa\"aaa'aaa.aaa/aaa\\aaa",
"aaa\\aaa" => "aaa\"aaa'aaa.aaa/aaa\\aaa",
"x" => array (
"aaa\"aaa'aaa.aaa/aaa\\aaa",
"aaa\"aaa'aaa.aaa/aaa\\aaa",
"aaa\"aaa'aaa.aaa/aaa\\aaa",
"aaa\"aaa'aaa.aaa/aaa\\aaa",
"aaa\"aaa'aaa.aaa/aaa\\aaa",
),
"y" => array (
array( "a", "b", "c"),
array( "a", "b", "c"),
array( "a", "b", "c"),
),
"z" => array (
array(
array( "a", "b", "c"),
array( "a", "b", "c"),
array( "a", "b", "c"),
),
array(
array( "a", "b", "c"),
array( "a", "b", "c"),
array( "a", "b", "c"),
),
),
);

echo "Call: \n";
$dequoted_data = $url->dequote_data($url->quote_data($data));


echo "\nEnd of PHP script\n";
?>
/*****************************************************/

Output:
Call:

End of PHP script
Speicherzugriffsfehler (Segmentationfault)

Search Discussions

Related Discussions

Discussion Navigation
viewthread | post
posts ‹ prev | 1 of 1 | next ›
Discussion Overview
groupphp-internals @
categoriesphp
postedSep 8, '04 at 2:43p
activeSep 8, '04 at 2:43p
posts1
users1
websitephp.net

1 user in discussion

Jan Gerritsen: 1 post

People

Translate

site design / logo © 2022 Grokbase