From: Yasuo Ohgaki Date: Sat, 10 Aug 2013 04:56:32 +0000 (+0900) Subject: Implemented Bug #17860 Suggestion: auto detect whether session changed X-Git-Tag: php-5.6.0alpha1~320 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=554021d21e1b2517313a377676260c188152c2eb;p=php Implemented Bug #17860 Suggestion: auto detect whether session changed --- diff --git a/NEWS b/NEWS index f9cb504aa2..b444b448a1 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,7 @@ PHP NEWS . Fixed Bug #65315 (session.hash_function silently fallback to default md5) (Yasuo) . Implemented Request #54649 (Create session_serializer_name()). (Yasuo) + . Implemented Request #17860 (Session write short circuit). (Yasuo) - mysqlnd: . Disabled flag for SP OUT variables for 5.5+ servers as they are not natively diff --git a/ext/session/php_session.h b/ext/session/php_session.h index e8e79f0fa6..ba3420ecee 100644 --- a/ext/session/php_session.h +++ b/ext/session/php_session.h @@ -180,6 +180,7 @@ typedef struct _php_ps_globals { double rfc1867_min_freq; /* session.upload_progress.min_freq */ zend_bool use_strict_mode; /* whether or not PHP accepts unknown session ids */ + char session_data_hash[16]; /* binary MD5 hash length */ } php_ps_globals; typedef php_ps_globals zend_ps_globals; diff --git a/ext/session/session.c b/ext/session/session.c index 278f954bdf..24299b732a 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -505,8 +505,17 @@ static void php_session_initialize(TSRMLS_D) /* {{{ */ */ } if (val) { + PHP_MD5_CTX context; + + /* Store read data's MD5 hash */ + PHP_MD5Init(&context); + PHP_MD5Update(&context, val, vallen); + PHP_MD5Final(PS(session_data_hash), &context); + php_session_decode(val, vallen TSRMLS_CC); efree(val); + } else { + memset(PS(session_data_hash),'\0', 16); } if (!PS(use_cookies) && PS(send_cookie)) { @@ -529,7 +538,20 @@ static void php_session_save_current_state(TSRMLS_D) /* {{{ */ val = php_session_encode(&vallen TSRMLS_CC); if (val) { - ret = PS(mod)->s_write(&PS(mod_data), PS(id), val, vallen TSRMLS_CC); + PHP_MD5_CTX context; + unsigned char digest[16]; + char md5_hash[33]; + + /* Generate data's MD5 hash */ + PHP_MD5Init(&context); + PHP_MD5Update(&context, val, vallen); + PHP_MD5Final(digest, &context); + /* Write only when save is required */ + if (memcmp(digest, PS(session_data_hash), 16)) { + ret = PS(mod)->s_write(&PS(mod_data), PS(id), val, vallen TSRMLS_CC); + } else { + ret = SUCCESS; + } efree(val); } else { ret = PS(mod)->s_write(&PS(mod_data), PS(id), "", 0 TSRMLS_CC); diff --git a/ext/session/tests/session_set_save_handler_basic.phpt b/ext/session/tests/session_set_save_handler_basic.phpt index 3897ba9a92..e8496e8afb 100644 --- a/ext/session/tests/session_set_save_handler_basic.phpt +++ b/ext/session/tests/session_set_save_handler_basic.phpt @@ -43,6 +43,7 @@ session_id($session_id); session_set_save_handler("open", "close", "read", "write", "destroy", "gc"); session_start(); var_dump($_SESSION); +$_SESSION['Bar'] = 'Foo'; session_write_close(); ob_end_flush(); @@ -91,5 +92,5 @@ array(3) { ["Guff"]=> int(1234567890) } -Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;] +Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;Bar|s:3:"Foo";] Close [%s,PHPSESSID] diff --git a/ext/session/tests/session_set_save_handler_class_003.phpt b/ext/session/tests/session_set_save_handler_class_003.phpt index e9a3cc2feb..29b3846851 100644 --- a/ext/session/tests/session_set_save_handler_class_003.phpt +++ b/ext/session/tests/session_set_save_handler_class_003.phpt @@ -58,6 +58,7 @@ session_set_save_handler($handler); session_start(); +$_SESSION['bar'] = 'hello'; session_write_close(); session_unset(); @@ -71,8 +72,10 @@ array(1) { } int(4) string(%d) "%s" -array(1) { +array(2) { ["foo"]=> string(5) "hello" + ["bar"]=> + string(5) "hello" } string(3) "hai" diff --git a/ext/session/tests/session_set_save_handler_class_007.phpt b/ext/session/tests/session_set_save_handler_class_007.phpt index 7344ae1ef3..55f722515e 100644 --- a/ext/session/tests/session_set_save_handler_class_007.phpt +++ b/ext/session/tests/session_set_save_handler_class_007.phpt @@ -56,6 +56,7 @@ $handler = new MySession(2); session_set_save_handler($handler); session_start(); +$_SESSION['abc'] = 'xyz'; // implicit close (called by shutdown function) echo "done\n"; ob_end_flush(); @@ -69,6 +70,6 @@ ob_end_flush(); (#2) constructor called (#1) destructor called done -(#2) writing %s = foo|s:3:"bar"; +(#2) writing %s = foo|s:3:"bar";abc|s:3:"xyz"; (#2) closing %s (#2) destructor called diff --git a/ext/session/tests/session_set_save_handler_closures.phpt b/ext/session/tests/session_set_save_handler_closures.phpt index 21b2c68737..1251886b01 100644 --- a/ext/session/tests/session_set_save_handler_closures.phpt +++ b/ext/session/tests/session_set_save_handler_closures.phpt @@ -42,6 +42,7 @@ echo "Starting session again..!\n"; session_id($session_id); session_set_save_handler($open_closure, $close_closure, $read_closure, $write_closure, $destroy_closure, $gc_closure); session_start(); +$_SESSION['Bar'] = 'Foo'; var_dump($_SESSION); session_write_close(); @@ -83,13 +84,15 @@ array(3) { Starting session again..! Open [%s,PHPSESSID] Read [%s,%s] -array(3) { +array(4) { ["Blah"]=> string(12) "Hello World!" ["Foo"]=> bool(false) ["Guff"]=> int(1234567890) + ["Bar"]=> + string(3) "Foo" } -Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;] +Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;Bar|s:3:"Foo";] Close [%s,PHPSESSID] diff --git a/ext/session/tests/session_set_save_handler_write_short_circuit.phpt b/ext/session/tests/session_set_save_handler_write_short_circuit.phpt new file mode 100644 index 0000000000..02ca182ec6 --- /dev/null +++ b/ext/session/tests/session_set_save_handler_write_short_circuit.phpt @@ -0,0 +1,104 @@ +--TEST-- +Test session_set_save_handler() function : test write short circuit +--INI-- +session.save_path= +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +*** Testing session_set_save_handler() : test write short circuit *** + +Open [%s,PHPSESSID] +Read [%s,%s] +array(3) { + ["Blah"]=> + string(12) "Hello World!" + ["Foo"]=> + bool(false) + ["Guff"]=> + int(1234567890) +} +Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;] +Close [%s,PHPSESSID] +array(3) { + ["Blah"]=> + string(12) "Hello World!" + ["Foo"]=> + bool(false) + ["Guff"]=> + int(1234567890) +} +Starting session again..! +Open [%s,PHPSESSID] +Read [%s,%s] +array(3) { + ["Blah"]=> + string(12) "Hello World!" + ["Foo"]=> + bool(false) + ["Guff"]=> + int(1234567890) +} +Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;Bar|s:3:"Foo";] +Close [%s,PHPSESSID] +Starting session again..! +Open [%s,PHPSESSID] +Read [%s,%s] +array(4) { + ["Blah"]=> + string(12) "Hello World!" + ["Foo"]=> + bool(false) + ["Guff"]=> + int(1234567890) + ["Bar"]=> + string(3) "Foo" +} +Close [%s,PHPSESSID] \ No newline at end of file