]> granicus.if.org Git - php/commitdiff
Implemented Bug #17860 Suggestion: auto detect whether session changed
authorYasuo Ohgaki <yohgaki@php.net>
Sat, 10 Aug 2013 04:56:32 +0000 (13:56 +0900)
committerYasuo Ohgaki <yohgaki@php.net>
Sat, 10 Aug 2013 04:56:32 +0000 (13:56 +0900)
NEWS
ext/session/php_session.h
ext/session/session.c
ext/session/tests/session_set_save_handler_basic.phpt
ext/session/tests/session_set_save_handler_class_003.phpt
ext/session/tests/session_set_save_handler_class_007.phpt
ext/session/tests/session_set_save_handler_closures.phpt
ext/session/tests/session_set_save_handler_write_short_circuit.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index f9cb504aa24a295bbf416e652479113f6755d231..b444b448a19365170081ef2abab60ed2a276c9d7 100644 (file)
--- 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
index e8e79f0fa69e4580dfa3366b2997c7da17e095ca..ba3420eceefdeb9e06c761e87f691b25035219d3 100644 (file)
@@ -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;
index 278f954bdfee5649d508e7af175016de9edb2fa1..24299b732ac52b64ef56cc019c6a1c97d597c0dd 100644 (file)
@@ -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);
index 3897ba9a92752d623464dfbcc54b1fb317890e02..e8496e8afb72e4782afa5ffaafabb5e28f55e9f9 100644 (file)
@@ -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]
index e9a3cc2febab46ecc5122fa5d28a01af99d02301..29b38468512632f0afc3868a1b1b36e0d8dc37b7 100644 (file)
@@ -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"
index 7344ae1ef30b2778f17ffb701df249c29866f235..55f722515ea6f03ee35881ea3dfc4448f333f9df 100644 (file)
@@ -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
index 21b2c68737099f6397c721acd4fb3e979fabd18f..1251886b011f9765ab7df5c4b1ffb6502f3b8931 100644 (file)
@@ -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 (file)
index 0000000..02ca182
--- /dev/null
@@ -0,0 +1,104 @@
+--TEST--
+Test session_set_save_handler() function : test write short circuit
+--INI--
+session.save_path=
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(callback $open, callback $close, callback $read, callback $write, callback $destroy, callback $gc)
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() : test write short circuit ***\n";
+
+require_once "save_handler.inc";
+$path = dirname(__FILE__);
+session_save_path($path);
+session_set_save_handler("open", "close", "read", "write", "destroy", "gc");
+
+session_start();
+$session_id = session_id();
+$_SESSION["Blah"] = "Hello World!";
+$_SESSION["Foo"] = FALSE;
+$_SESSION["Guff"] = 1234567890;
+var_dump($_SESSION);
+
+session_write_close();
+session_unset();
+var_dump($_SESSION);
+
+echo "Starting session again..!\n";
+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();
+
+echo "Starting session again..!\n";
+session_id($session_id);
+session_set_save_handler("open", "close", "read", "write", "destroy", "gc");
+session_start();
+var_dump($_SESSION);
+// $_SESSION should be the same and should skip write()
+session_write_close();
+
+ob_end_flush();
+?>
+--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