php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #13524 session_unset() with no registered vars causes segfault w/save_handler=user
Submitted: 2001-10-02 20:05 UTC Modified: 2001-12-19 22:50 UTC
From: christopher dot k dot hall at mail dot sprint dot com Assigned:
Status: Not a bug Package: Session related
PHP Version: 4.0.5 OS: linux 2.2.19 redhat
Private report: No CVE-ID: None
 [2001-10-02 20:05 UTC] christopher dot k dot hall at mail dot sprint dot com
when using session_unset() with no registered vars in the session, i get an apache segfault.  i only experience this when using my own session handlers (sessions.save_handler = user in php.ini).  when using files, i don't get segfault.

here are scripts i used to cause this error:

---sessions.lib-------

<?php

// $Id$

/*
*	session table schema
*
*	create table SOLR_SESSIONS (
*	session_id			char(32) not null,
*	session_data		text not null,
*	session_expiration	int(11) unsigned not null,
*	primary key (session_id));
*
*/

// PEAR db abstraction
require_once("DB.php");

function on_session_start($save_path, $session_name) {

	global $dbh;
	
	return TRUE;
	// does nothing since we already have a db connection

}

function on_session_end() {
	
	global $dbh;
	
	return TRUE;
	// does nothing
}

function on_session_read($key) {
	
	global $dbh;
	
	$sql = "SELECT session_data FROM SOLR_SESSIONS WHERE session_id = '$key' and session_expiration > UNIX_TIMESTAMP(NOW())";
	
	$result = $dbh->query($sql);
	
	if(DB::isError($result)) {
		return "";
	}
	
	$row = $result->fetchRow(DB_FETCHMODE_ASSOC);
	return $row["session_data"];
}

function on_session_write($key, $val) {
	
	global $dbh;
	
	$insert_sql = "INSERT INTO SOLR_SESSIONS values ('$key', '$val', UNIX_TIMESTAMP()+3600)";
	$update_sql = "UPDATE SOLR_SESSIONS SET session_data = '$val', session_expiration = UNIX_TIMESTAMP()+3600, WHERE session_id = '$key'";
	
	if(DB::isError($dbh->query($insert_sql))) {
		$dbh->query($update_sql);
	}
}

function on_session_destroy($key) {
	
	global $dbh;
	
	$sql = "DELETE FROM SOLR_SESSIONS WHERE session_id = '$key'";

	$dbh->query($sql);
}

function on_session_gc($max_lifetime) {
	
	global $dbh;
	
	$sql = "DELETE FROM SOLR_SESSIONS WHERE session_expiration < UNIX_TIMESTAMP(NOW())";
	
	$dbh->query($sql);
}

?>


---testsessions.php-------

<?php

// testsessions.php

/*
*	session table schema
*
*	create table SOLR_SESSIONS (
*	session_id			char(32) not null,
*	session_data		text not null,
*	session_expiration	int(11) unsigned not null,
*	primary key (session_id));
*
*/

error_reporting(E_ALL);

require_once("DB.php");
require_once("libs/sessions.lib");

session_set_save_handler("on_session_start", "on_session_end",
						"on_session_read", "on_session_write",
						"on_session_destroy", "on_session_gc");


$dbh = DB::connect("mysql://solr:ziggurat-keep@localhost/SOLR");
if(DB::isError($dbh)) {
	die($dbh->get_error());
}

session_start();

if(session_is_registered("someval")) {
	echo "someval=".$someval."<br>\n";
} else {
	// if you comment session_unset(), it works fine.
	session_unset();
	session_destroy();
	
	//header("Location: testsessions2.php");
	
	echo "someval not registered<br>\n";
	echo "<a href=\"testsessions2.php\">go here to register someval</a>\n";

}

?>

---testsessions2.php-------

<?php

// testsessions2.php

error_reporting(E_ALL);

require_once("DB.php");
require_once("libs/sessions.lib");

session_set_save_handler("on_session_start", "on_session_end",
						"on_session_read", "on_session_write",
						"on_session_destroy", "on_session_gc");


$dbh = DB::connect("mysql://solr:ziggurat-keep@localhost/SOLR");
if(DB::isError($dbh)) {
	die($dbh->get_error());
}

session_start();

$someval = 1;
session_register("someval");

echo "someval now registered as ".$someval."<br>\n";
echo "<a href=\"testsessions.php\">go here to see</a>\n";

?>

here is the backtrace:

(gdb) run -X -f /usr/local/apache/conf/httpd.conf
Starting program: /usr/local/apache/bin/httpd -X -f /usr/local/apache/conf/httpd.c
onf

Program received signal SIGSEGV, Segmentation fault.
0x40380ed9 in php_if_session_unset (ht=0, return_value=0x81e8554, this_ptr=0x0,
    return_value_used=0) at session.c:1402
1402            zend_hash_clean(Z_ARRVAL_P(PS(http_session_vars)));
(gdb) bt
#0  0x40380ed9 in php_if_session_unset (ht=0, return_value=0x81e8554,
    this_ptr=0x0, return_value_used=0) at session.c:1402
#1  0x409ddf84 in zend_reverse_table ()
   from /usr/local/apache/libexec/ZendOptimizer.so
#2  0x409e901d in zend_oe () from /usr/local/apache/libexec/ZendOptimizer.so
#3  0x40332785 in zend_execute_scripts (type=8, file_count=3) at zend.c:743
#4  0x40343cc7 in php_execute_script (primary_file=0xbffff790) at main.c:1209
#5  0x403405c2 in apache_php_module_main (r=0x8150b5c, display_source_mode=0)
    at sapi_apache.c:89
#6  0x40340f1d in send_php (r=0x8150b5c, display_source_mode=0, filename=0x0)
    at mod_php4.c:521
#7  0x40340f52 in send_parsed_php (r=0x8150b5c) at mod_php4.c:532
#8  0x805443f in ap_invoke_handler ()
#9  0x80681d3 in process_request_internal ()
#10 0x8068234 in ap_process_request ()
#11 0x805f6d5 in child_main ()
#12 0x805f880 in make_child ()
#13 0x805f9f4 in startup_children ()
#14 0x8060043 in standalone_main ()
#15 0x806085f in main ()
#16 0x40149b5c in __libc_start_main (main=0x80604c8 <main>, argc=4,
    ubp_av=0xbffffa44, init=0x804ea70 <_init>, fini=0x80954ac <_fini>,
    rtld_fini=0x4000d634 <_dl_fini>, stack_end=0xbffffa3c)
    at ../sysdeps/generic/libc-start.c:129
(gdb)

hope this helps

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2001-10-02 20:09 UTC] rasmus@php.net
Your  write, destroy and gc functions need to return true on success.  Shouldn't cause a segfault of course, but try fixing that and also try a recent version of PHP.
 [2001-10-02 20:31 UTC] christopher dot k dot hall at mail dot sprint dot com
added the NECESSARY returns on all the handler functions and now it appears to work fine.

sorry for the inconvenience...
 [2001-10-03 05:35 UTC] jeroen@php.net
Reopening. PHP should never segfault.

Tried to reproduce with current CVS, but that didn't work.

Can you please try to reproduce it with a snapshot from http://snaps.php.net?
 [2001-10-04 11:18 UTC] christopher dot k dot hall at mail dot sprint dot com
unfortunately i cannot as i do not have control over install of php in my company.

however, as a side note, i switched from using user defined session handling to mm which was already compiled into php on our server.  i changed session.save_handler = mm, restarted apache,  removed the calls to session_set_save_handler() from the code, and when i tried the scripts (just removed all code that was no longer necessary) below, i got another segfault.

here's the configuration we have for php (i didn't include this last time, sorry)

--cache-file=/dev/null
--with-config-file-path=/usr/local/apache/conf 
--with-apxs=/usr/local/apache/bin/apxs
--enable-trans-sid
--with-imap
--enable-ftp
--enable-track-vars
--with-mysql=/usr/local/mysql
--enable-libgcc
--disable-debug
--with-db
--verbose
--with-gdbm
--with-ndbm
--with-db2
--with-gd=shared
--with-dom
--with-ttf
--with-xml
--with-zlib
--with-mhash
--prefix=/usr/local/php
--with-regex=system
--enable-memory-limit
--enable-calendar
--enable-sysvsem
--enable-sysvshm
--with-bz2
--with-gettext
--with-jpeg-dir=/usr
--with-xpm-dir=/usr/X11R6
--with-ldap
--with-mcal=/usr/local/src/libmcal
--with-mm=/usr/local/mm
--enable-exif
--with-pcre-regex=/usr/local/lib
--with-sablot=/usr
--with-expat=/usr
--without-pgsql
--enable-yp
--enable-shmop
--with-snmp
--enable-sockets
--enable-dba
--with-kerberos=/usr/kerberos
--with-imap-ssl
--with-pspell=/usr

here's the gdb/bt:

(gdb) run -X -f /usr/local/apache/conf/httpd.conf
Starting program: /usr/local/apache/bin/httpd -X - f /usr/local/apache/conf/httpd.conf

Program received signal SIGSEGV, Segmentation fault.
0x40380ed9 in php_if_session_unset (ht=0, return_value=0x80bf37c, this_ptr=0x0,
    return_value_used=0) at session.c:1402
1402            zend_hash_clean(Z_ARRVAL_P(PS(http_session_vars)));
(gdb) bt
#0  0x40380ed9 in php_if_session_unset (ht=0, return_value=0x80bf37c,
    this_ptr=0x0, return_value_used=0) at session.c:1402
#1  0x409ddf84 in zend_reverse_table ()
   from /usr/local/apache/libexec/ZendOptimizer.so
#2  0x409e901d in zend_oe () from /usr/local/apache/libexec/ZendOptimizer.so
#3  0x40332785 in zend_execute_scripts (type=8, file_count=3) at zend.c:743
#4  0x40343cc7 in php_execute_script (primary_file=0xbffff780) at main.c:1209
#5  0x403405c2 in apache_php_module_main (r=0x8150fac, display_source_mode=0)
    at sapi_apache.c:89
#6  0x40340f1d in send_php (r=0x8150fac, display_source_mode=0, filename=0x0)
    at mod_php4.c:521
#7  0x40340f52 in send_parsed_php (r=0x8150fac) at mod_php4.c:532
#8  0x805443f in ap_invoke_handler ()
#9  0x80681d3 in process_request_internal ()
#10 0x8068234 in ap_process_request ()
#11 0x805f6d5 in child_main ()
#12 0x805f880 in make_child ()
#13 0x805f9f4 in startup_children ()
#14 0x8060043 in standalone_main ()
#15 0x806085f in main ()
#16 0x40149b5c in __libc_start_main (main=0x80604c8 <main>, argc=4,
    ubp_av=0xbffffa34, init=0x804ea70 <_init>, fini=0x80954ac <_fini>,
    rtld_fini=0x4000d634 <_dl_fini>, stack_end=0xbffffa2c)
    at ../sysdeps/generic/libc-start.c:129

here's the code i used to test it:

----start testsessions.php----

<?php

// testsessions.php

error_reporting(E_ALL);

session_start();

if(session_is_registered("someval")) {
	echo "someval=".$someval."<br>\n";
} else {
	// if you comment session_unset(), it works fine.
	session_unset();
	session_destroy();
	
	echo "someval not registered<br>\n";
	echo "<a href=\"testsessions2.php\">go here to register someval</a>\n";

}

?>

----end testsessions.php----

----start testsessions2.php----

<?php

// testsessions2.php

error_reporting(E_ALL);

session_start();

$someval = 3;
session_register("someval");

echo "someval now registered as ".$someval."<br>\n";
echo "<a href=\"testsessions.php\">go here to see</a>\n";

?>

----end testsessions2.php----

looks like the same bug to me...

 [2001-10-04 11:21 UTC] christopher dot k dot hall at mail dot sprint dot com
sorry, i meant to add, you will want to load testsessions.php in your browser first.
 [2001-10-04 12:03 UTC] christopher dot k dot hall at mail dot sprint dot com
sorry, i meant to add, you will want to load testsessions.php in your browser first.
 [2001-12-19 22:50 UTC] yohgaki@php.net
Your session save handler has bugs.
Search zend.com code exchange for PosrgreSQL session save handler as an example. (Under HTTP category)

--
Yasuo Ohgaki
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 21:01:27 2024 UTC