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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: christopher dot k dot hall at mail dot sprint dot com
New email:
PHP Version: OS:

 

 [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

Pull Requests

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-2025 The PHP Group
All rights reserved.
Last updated: Tue May 06 23:01:28 2025 UTC