dmitry Thu Nov 22 13:33:54 2007 UTC
Modified files:
/TSRM tsrm_config_common.h tsrm_virtual_cwd.c
/ZendEngine2 zend.h zend_API.c zend_compile.h zend_execute.c
zend_strtod.c zend_vm_execute.h zend_vm_execute.skl
/ZendEngine2/tests bug43128.phpt
/php-src/ext/interbase ibase_query.c
/php-src/ext/reflection php_reflection.c
/php-src/main main.c
Log:
Fixed bug #43128 (Very long class name causes segfault)
http://cvs.php.net/viewvc.cgi/TSRM/tsrm_config_common.h?r1=1.19&r2=1.20&diff_format=u
Index: TSRM/tsrm_config_common.h
diff -u TSRM/tsrm_config_common.h:1.19 TSRM/tsrm_config_common.h:1.20
--- TSRM/tsrm_config_common.h:1.19 Thu Feb 15 19:11:29 2007
+++ TSRM/tsrm_config_common.h Thu Nov 22 13:33:53 2007
@@ -52,9 +52,17 @@
#endif
#if (HAVE_ALLOCA || (defined (__GNUC__) && __GNUC__ >= 2))
-# define tsrm_do_alloca(p) alloca(p)
-# define tsrm_free_alloca(p)
+# define TSRM_ALLOCA_MAX_SIZE 4096
+# define TSRM_ALLOCA_FLAG(name) \
+ int name;
+# define tsrm_do_alloca_ex(size, limit, use_heap) \
+ ((use_heap = ((size) > (limit))) ? malloc(size) : alloca(size))
+# define tsrm_do_alloca(size, use_heap) \
+ tsrm_do_alloca_ex(size, TSRM_ALLOCA_MAX_SIZE, use_heap)
+# define tsrm_free_alloca(p, use_heap) \
+ do { if (use_heap) free(p); } while (0)
#else
+# define TSRM_ALLOCA_FLAG(name)
# define tsrm_do_alloca(p) malloc(p)
# define tsrm_free_alloca(p) free(p)
#endif
http://cvs.php.net/viewvc.cgi/TSRM/tsrm_virtual_cwd.c?r1=1.117&r2=1.118&diff_format=u
Index: TSRM/tsrm_virtual_cwd.c
diff -u TSRM/tsrm_virtual_cwd.c:1.117 TSRM/tsrm_virtual_cwd.c:1.118
--- TSRM/tsrm_virtual_cwd.c:1.117 Tue Nov 13 09:47:19 2007
+++ TSRM/tsrm_virtual_cwd.c Thu Nov 22 13:33:53 2007
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: tsrm_virtual_cwd.c,v 1.117 2007/11/13 09:47:19 dmitry Exp $ */
+/* $Id: tsrm_virtual_cwd.c,v 1.118 2007/11/22 13:33:53 dmitry Exp $ */
#include <sys/types.h>
#include <sys/stat.h>
@@ -777,6 +777,7 @@
int length = strlen(path);
char *temp;
int retval;
+ TSRM_ALLOCA_FLAG(use_heap)
if (length == 0) {
return 1; /* Can't cd to empty string */
@@ -793,14 +794,14 @@
if (length == COPY_WHEN_ABSOLUTE(path) && IS_ABSOLUTE_PATH(path,
length+1)) { /* Also use trailing slash if this is absolute */
length++;
}
- temp = (char *) tsrm_do_alloca(length+1);
+ temp = (char *) tsrm_do_alloca(length+1, use_heap);
memcpy(temp, path, length);
temp[length] = 0;
#if VIRTUAL_CWD_DEBUG
fprintf (stderr, "Changing directory to %s\n", temp);
#endif
retval = p_chdir(temp TSRMLS_CC);
- tsrm_free_alloca(temp);
+ tsrm_free_alloca(temp, use_heap);
return retval;
}
/* }}} */
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend.h?r1=1.344&r2=1.345&diff_format=u
Index: ZendEngine2/zend.h
diff -u ZendEngine2/zend.h:1.344 ZendEngine2/zend.h:1.345
--- ZendEngine2/zend.h:1.344 Wed Nov 21 14:55:51 2007
+++ ZendEngine2/zend.h Thu Nov 22 13:33:53 2007
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: zend.h,v 1.344 2007/11/21 14:55:51 dmitry Exp $ */
+/* $Id: zend.h,v 1.345 2007/11/22 13:33:53 dmitry Exp $ */
#ifndef ZEND_H
#define ZEND_H
@@ -178,11 +178,19 @@
#endif
#if (HAVE_ALLOCA || (defined (__GNUC__) && __GNUC__ >= 2)) && !(defined(ZTS)
&& defined(ZEND_WIN32)) && !(defined(ZTS) && defined(NETWARE)) &&
!(defined(ZTS) && defined(HPUX)) && !defined(DARWIN)
-# define do_alloca(p) alloca(p)
-# define free_alloca(p)
+# define ZEND_ALLOCA_MAX_SIZE (32 * 1024)
+# define ALLOCA_FLAG(name) \
+ zend_bool name;
+# define do_alloca_ex(size, limit, use_heap) \
+ ((use_heap = (UNEXPECTED((size) > (limit)))) ? emalloc(size) :
alloca(size))
+# define do_alloca(size, use_heap) \
+ do_alloca_ex(size, ZEND_ALLOCA_MAX_SIZE, use_heap)
+# define free_alloca(p, use_heap) \
+ do { if (UNEXPECTED(use_heap)) efree(p); } while (0)
#else
+# define ALLOCA_FLAG(name)
# define do_alloca(p) emalloc(p)
-# define free_alloca(p) efree(p)
+# define free_alloca(p) efree(p)
#endif
#if ZEND_DEBUG
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_API.c?r1=1.448&r2=1.449&diff_format=u
Index: ZendEngine2/zend_API.c
diff -u ZendEngine2/zend_API.c:1.448 ZendEngine2/zend_API.c:1.449
--- ZendEngine2/zend_API.c:1.448 Thu Nov 1 13:30:15 2007
+++ ZendEngine2/zend_API.c Thu Nov 22 13:33:53 2007
@@ -18,7 +18,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: zend_API.c,v 1.448 2007/11/01 13:30:15 jani Exp $ */
+/* $Id: zend_API.c,v 1.449 2007/11/22 13:33:53 dmitry Exp $ */
#include "zend.h"
#include "zend_execute.h"
@@ -2195,11 +2195,10 @@
}
}
fname_len = strlen(ptr->fname);
- lowercase_name = do_alloca(fname_len+1);
- zend_str_tolower_copy(lowercase_name, ptr->fname, fname_len);
+ lowercase_name = zend_str_tolower_dup(ptr->fname, fname_len);
if (zend_ascii_hash_add(target_function_table, lowercase_name,
fname_len+1, &function, sizeof(zend_function), (void**)®_function) ==
FAILURE) {
unload=1;
- free_alloca(lowercase_name);
+ efree(lowercase_name);
break;
}
if (scope) {
@@ -2245,7 +2244,7 @@
}
ptr++;
count++;
- free_alloca(lowercase_name);
+ efree(lowercase_name);
}
if (unload) { /* before unloading, display all remaining bad function
in the module */
if (scope) {
@@ -3270,11 +3269,12 @@
if (UG(unicode)) {
zstr uname;
int ret;
+ ALLOCA_FLAG(use_heap)
- uname.u = do_alloca(UBYTES(name_length+1));
+ uname.u = do_alloca(UBYTES(name_length+1), use_heap);
u_charsToUChars(name, uname.u, name_length+1);
ret = zend_u_declare_property_ex(ce, IS_UNICODE, uname,
name_length, property, access_type, doc_comment, doc_comment_len TSRMLS_CC);
- free_alloca(uname.u);
+ free_alloca(uname.u, use_heap);
return ret;
} else {
return zend_u_declare_property_ex(ce, IS_STRING, ZSTR(name),
name_length, property, access_type, doc_comment, doc_comment_len TSRMLS_CC);
@@ -3293,11 +3293,12 @@
if (UG(unicode)) {
zstr uname;
int ret;
+ ALLOCA_FLAG(use_heap)
- uname.u = do_alloca(UBYTES(name_length+1));
+ uname.u = do_alloca(UBYTES(name_length+1), use_heap);
u_charsToUChars(name, uname.u, name_length+1);
ret = zend_u_declare_property_ex(ce, IS_UNICODE, uname,
name_length, property, access_type, NULL_ZSTR, 0 TSRMLS_CC);
- free_alloca(uname.u);
+ free_alloca(uname.u, use_heap);
return ret;
} else {
return zend_u_declare_property_ex(ce, IS_STRING, ZSTR(name),
name_length, property, access_type, NULL_ZSTR, 0 TSRMLS_CC);
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_compile.h?r1=1.369&r2=1.370&diff_format=u
Index: ZendEngine2/zend_compile.h
diff -u ZendEngine2/zend_compile.h:1.369 ZendEngine2/zend_compile.h:1.370
--- ZendEngine2/zend_compile.h:1.369 Tue Nov 20 08:53:17 2007
+++ ZendEngine2/zend_compile.h Thu Nov 22 13:33:53 2007
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: zend_compile.h,v 1.369 2007/11/20 08:53:17 dmitry Exp $ */
+/* $Id: zend_compile.h,v 1.370 2007/11/22 13:33:53 dmitry Exp $ */
#ifndef ZEND_COMPILE_H
#define ZEND_COMPILE_H
@@ -304,6 +304,7 @@
union _temp_variable *Ts;
zval ***CVs;
zend_bool original_in_execution;
+ ALLOCA_FLAG(use_heap)
HashTable *symbol_table;
struct _zend_execute_data *prev_execute_data;
zval *old_error_reporting;
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_execute.c?r1=1.774&r2=1.775&diff_format=u
Index: ZendEngine2/zend_execute.c
diff -u ZendEngine2/zend_execute.c:1.774 ZendEngine2/zend_execute.c:1.775
--- ZendEngine2/zend_execute.c:1.774 Wed Nov 21 12:28:30 2007
+++ ZendEngine2/zend_execute.c Thu Nov 22 13:33:53 2007
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: zend_execute.c,v 1.774 2007/11/21 12:28:30 dmitry Exp $ */
+/* $Id: zend_execute.c,v 1.775 2007/11/22 13:33:53 dmitry Exp $ */
#define ZEND_INTENSIVE_DEBUGGING 0
@@ -1447,12 +1447,7 @@
}
#define ZEND_VM_EXIT_FROM_EXECUTE_LOOP() \
- free_alloca(EX(CVs)); \
- if (EX(op_array)->T < TEMP_VAR_STACK_LIMIT) { \
- free_alloca(EX(Ts)); \
- } else { \
- efree(EX(Ts)); \
- } \
+ free_alloca(EX(CVs), EX(use_heap)); \
EG(in_execution) = EX(original_in_execution); \
EG(current_execute_data) = EX(prev_execute_data); \
EG(opline_ptr) = NULL;
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_strtod.c?r1=1.35&r2=1.36&diff_format=u
Index: ZendEngine2/zend_strtod.c
diff -u ZendEngine2/zend_strtod.c:1.35 ZendEngine2/zend_strtod.c:1.36
--- ZendEngine2/zend_strtod.c:1.35 Tue Sep 4 18:46:07 2007
+++ ZendEngine2/zend_strtod.c Thu Nov 22 13:33:53 2007
@@ -89,7 +89,7 @@
* directly -- and assumed always to succeed.
*/
-/* $Id: zend_strtod.c,v 1.35 2007/09/04 18:46:07 tony2001 Exp $ */
+/* $Id: zend_strtod.c,v 1.36 2007/11/22 13:33:53 dmitry Exp $ */
#include <zend.h>
#include <unicode/utypes.h>
@@ -2603,6 +2603,7 @@
const UChar *u = nptr, *nstart;
UChar c = *u;
int any = 0;
+ ALLOCA_FLAG(use_heap)
while (u_isspace(c)) {
c = *++u;
@@ -2653,7 +2654,7 @@
if (length < sizeof(buf)) {
numbuf = buf;
} else {
- numbuf = (char *) do_alloca(length + 1);
+ numbuf = (char *) do_alloca(length + 1, use_heap);
}
bufpos = numbuf;
@@ -2666,7 +2667,7 @@
value = zend_strtod(numbuf, NULL);
if (numbuf != buf) {
- free_alloca(numbuf);
+ free_alloca(numbuf, use_heap);
}
if (endptr != NULL) {
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_vm_execute.h?r1=1.205&r2=1.206&diff_format=u
Index: ZendEngine2/zend_vm_execute.h
diff -u ZendEngine2/zend_vm_execute.h:1.205 ZendEngine2/zend_vm_execute.h:1.206
--- ZendEngine2/zend_vm_execute.h:1.205 Thu Nov 22 09:03:11 2007
+++ ZendEngine2/zend_vm_execute.h Thu Nov 22 13:33:53 2007
@@ -45,12 +45,13 @@
EX(called_scope) = NULL;
EX(object) = NULL;
EX(old_error_reporting) = NULL;
- if (op_array->T < TEMP_VAR_STACK_LIMIT) {
- EX(Ts) = (temp_variable *) do_alloca(sizeof(temp_variable) *
op_array->T);
+ if (EXPECTED(op_array->T < TEMP_VAR_STACK_LIMIT && op_array->last_var <
TEMP_VAR_STACK_LIMIT)) {
+ EX(CVs) = (zval***)do_alloca(sizeof(zval**) *
op_array->last_var + sizeof(temp_variable) * op_array->T, EX(use_heap));
} else {
- EX(Ts) = (temp_variable *) safe_emalloc(sizeof(temp_variable),
op_array->T, 0);
+ EX(use_heap) = 1;
+ EX(CVs) = (zval***)safe_emalloc(sizeof(temp_variable),
op_array->T, sizeof(zval**) * op_array->last_var);
}
- EX(CVs) = (zval***)do_alloca(sizeof(zval**) * op_array->last_var);
+ EX(Ts) = (temp_variable *)(EX(CVs) + op_array->last_var);
memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var);
EX(op_array) = op_array;
EX(original_in_execution) = EG(in_execution);
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_vm_execute.skl?r1=1.10&r2=1.11&diff_format=u
Index: ZendEngine2/zend_vm_execute.skl
diff -u ZendEngine2/zend_vm_execute.skl:1.10
ZendEngine2/zend_vm_execute.skl:1.11
--- ZendEngine2/zend_vm_execute.skl:1.10 Tue Nov 20 09:51:43 2007
+++ ZendEngine2/zend_vm_execute.skl Thu Nov 22 13:33:53 2007
@@ -16,12 +16,13 @@
EX(called_scope) = NULL;
EX(object) = NULL;
EX(old_error_reporting) = NULL;
- if (op_array->T < TEMP_VAR_STACK_LIMIT) {
- EX(Ts) = (temp_variable *) do_alloca(sizeof(temp_variable) *
op_array->T);
+ if (EXPECTED(op_array->T < TEMP_VAR_STACK_LIMIT && op_array->last_var <
TEMP_VAR_STACK_LIMIT)) {
+ EX(CVs) = (zval***)do_alloca(sizeof(zval**) *
op_array->last_var + sizeof(temp_variable) * op_array->T, EX(use_heap));
} else {
- EX(Ts) = (temp_variable *) safe_emalloc(sizeof(temp_variable),
op_array->T, 0);
+ EX(use_heap) = 1;
+ EX(CVs) = (zval***)safe_emalloc(sizeof(temp_variable),
op_array->T, sizeof(zval**) * op_array->last_var);
}
- EX(CVs) = (zval***)do_alloca(sizeof(zval**) * op_array->last_var);
+ EX(Ts) = (temp_variable *)(EX(CVs) + op_array->last_var);
memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var);
EX(op_array) = op_array;
EX(original_in_execution) = EG(in_execution);
http://cvs.php.net/viewvc.cgi/ZendEngine2/tests/bug43128.phpt?r1=1.1&r2=1.2&diff_format=u
Index: ZendEngine2/tests/bug43128.phpt
diff -u /dev/null ZendEngine2/tests/bug43128.phpt:1.2
--- /dev/null Thu Nov 22 13:33:54 2007
+++ ZendEngine2/tests/bug43128.phpt Thu Nov 22 13:33:53 2007
@@ -0,0 +1,17 @@
+--TEST--
+Bug #43128 Very long class name causes segfault
+--FILE--
+<?php
+
+$a = str_repeat("a", 10 * 1024 * 1024);
+
+eval("class $a {}");
+
+# call_user_func($a); // Warning
+# $a->$a(); // Fatal error
+
+if ($a instanceof $a); // Segmentation fault
+new $a; // Segmentation fault
+echo "ok\n";
+--EXPECT--
+ok
http://cvs.php.net/viewvc.cgi/php-src/ext/interbase/ibase_query.c?r1=1.34&r2=1.35&diff_format=u
Index: php-src/ext/interbase/ibase_query.c
diff -u php-src/ext/interbase/ibase_query.c:1.34
php-src/ext/interbase/ibase_query.c:1.35
--- php-src/ext/interbase/ibase_query.c:1.34 Thu Nov 8 19:41:57 2007
+++ php-src/ext/interbase/ibase_query.c Thu Nov 22 13:33:53 2007
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: ibase_query.c,v 1.34 2007/11/08 19:41:57 lwe Exp $ */
+/* $Id: ibase_query.c,v 1.35 2007/11/22 13:33:53 dmitry Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -1836,6 +1836,7 @@
zval *query, ***args = NULL;
ibase_query *ib_query;
ibase_result *result = NULL;
+ ALLOCA_FLAG(use_heap)
RESET_ERRMSG;
@@ -1859,7 +1860,7 @@
}
} else if (bind_n > 0) { /* have variables to bind */
- args = (zval ***) do_alloca(ZEND_NUM_ARGS() *
sizeof(zval **));
+ args = (zval ***) do_alloca(ZEND_NUM_ARGS() *
sizeof(zval **), use_heap);
if (FAILURE ==
zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args)) {
break;
@@ -1900,7 +1901,7 @@
} while (0);
if (args) {
- free_alloca(args);
+ free_alloca(args, use_heap);
}
}
/* }}} */
http://cvs.php.net/viewvc.cgi/php-src/ext/reflection/php_reflection.c?r1=1.287&r2=1.288&diff_format=u
Index: php-src/ext/reflection/php_reflection.c
diff -u php-src/ext/reflection/php_reflection.c:1.287
php-src/ext/reflection/php_reflection.c:1.288
--- php-src/ext/reflection/php_reflection.c:1.287 Sun Oct 28 13:44:09 2007
+++ php-src/ext/reflection/php_reflection.c Thu Nov 22 13:33:53 2007
@@ -20,7 +20,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_reflection.c,v 1.287 2007/10/28 13:44:09 iliaa Exp $ */
+/* $Id: php_reflection.c,v 1.288 2007/11/22 13:33:53 dmitry Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -1065,14 +1065,15 @@
int name_len = strlen(name_str);
char *lcname;
struct _zend_module_entry *module;
+ ALLOCA_FLAG(use_heap)
- lcname = do_alloca(name_len + 1);
+ lcname = do_alloca(name_len + 1, use_heap);
zend_str_tolower_copy(lcname, name_str, name_len);
if (zend_hash_find(&module_registry, lcname, name_len + 1, (void
**)&module) == FAILURE) {
- free_alloca(lcname);
+ free_alloca(lcname, use_heap);
return;
}
- free_alloca(lcname);
+ free_alloca(lcname, use_heap);
reflection_instantiate(reflection_extension_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object
TSRMLS_CC);
@@ -4240,6 +4241,7 @@
zend_module_entry *module;
char *name_str;
int name_len;
+ ALLOCA_FLAG(use_heap)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str,
&name_len) == FAILURE) {
return;
@@ -4250,15 +4252,15 @@
if (intern == NULL) {
return;
}
- lcname = do_alloca(name_len + 1);
+ lcname = do_alloca(name_len + 1, use_heap);
zend_str_tolower_copy(lcname, name_str, name_len);
if (zend_hash_find(&module_registry, lcname, name_len + 1, (void
**)&module) == FAILURE) {
- free_alloca(lcname);
+ free_alloca(lcname, use_heap);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Extension %s does not exist", name_str);
return;
}
- free_alloca(lcname);
+ free_alloca(lcname, use_heap);
MAKE_STD_ZVAL(name);
ZVAL_ASCII_STRING(name, module->name, 1);
zend_ascii_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"),
(void **) &name, sizeof(zval *), NULL);
@@ -5026,7 +5028,7 @@
php_info_print_table_start();
php_info_print_table_header(2, "Reflection", "enabled");
- php_info_print_table_row(2, "Version", "$Id: php_reflection.c,v 1.287
2007/10/28 13:44:09 iliaa Exp $");
+ php_info_print_table_row(2, "Version", "$Id: php_reflection.c,v 1.288
2007/11/22 13:33:53 dmitry Exp $");
php_info_print_table_end();
} /* }}} */
http://cvs.php.net/viewvc.cgi/php-src/main/main.c?r1=1.752&r2=1.753&diff_format=u
Index: php-src/main/main.c
diff -u php-src/main/main.c:1.752 php-src/main/main.c:1.753
--- php-src/main/main.c:1.752 Thu Oct 18 13:12:01 2007
+++ php-src/main/main.c Thu Nov 22 13:33:53 2007
@@ -18,7 +18,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: main.c,v 1.752 2007/10/18 13:12:01 dmitry Exp $ */
+/* $Id: main.c,v 1.753 2007/11/22 13:33:53 dmitry Exp $ */
/* {{{ includes
*/
@@ -2090,6 +2090,7 @@
int old_cwd_fd = -1;
#else
char *old_cwd;
+ ALLOCA_FLAG(use_heap)
#endif
int retval = 0;
@@ -2100,7 +2101,7 @@
}
#ifndef HAVE_BROKEN_GETCWD
# define OLD_CWD_SIZE 4096
- old_cwd = do_alloca(OLD_CWD_SIZE);
+ old_cwd = do_alloca(OLD_CWD_SIZE, use_heap);
old_cwd[0] = '\0';
#endif
@@ -2177,7 +2178,7 @@
if (old_cwd[0] != '\0') {
VCWD_CHDIR(old_cwd);
}
- free_alloca(old_cwd);
+ free_alloca(old_cwd, use_heap);
#endif
return retval;
}
@@ -2188,10 +2189,11 @@
PHPAPI int php_execute_simple_script(zend_file_handle *primary_file, zval
**ret TSRMLS_DC)
{
char *old_cwd;
+ ALLOCA_FLAG(use_heap)
EG(exit_status) = 0;
#define OLD_CWD_SIZE 4096
- old_cwd = do_alloca(OLD_CWD_SIZE);
+ old_cwd = do_alloca(OLD_CWD_SIZE, use_heap);
old_cwd[0] = '\0';
zend_try {
@@ -2212,7 +2214,7 @@
VCWD_CHDIR(old_cwd);
}
- free_alloca(old_cwd);
+ free_alloca(old_cwd, use_heap);
return EG(exit_status);
}
/* }}} */
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php