Segmentationfault in PHP extension

From: Date: Wed, 08 Sep 2004 14:42:59 +0000
Subject: Segmentationfault in PHP extension
Groups: php.internals 
Request: Send a blank email to internals+get-12649@lists.php.net to get a copy of this message
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)

« previous php.internals (#12649) next »