@@ -70,9 +70,9 @@ ps_module ps_mod_redis_cluster = {
7070
7171typedef struct {
7272 zend_bool is_locked ;
73- char * session_key ;
74- char * lock_key ;
75- char * lock_secret ;
73+ zend_string * session_key ;
74+ zend_string * lock_key ;
75+ zend_string * lock_secret ;
7676} redis_session_lock_status ;
7777
7878typedef struct redis_pool_member_ {
@@ -130,12 +130,9 @@ redis_pool_free(redis_pool *pool TSRMLS_DC) {
130130 }
131131
132132 /* Cleanup after our lock */
133- if (pool -> lock_status .session_key )
134- efree (pool -> lock_status .session_key );
135- if (pool -> lock_status .lock_secret )
136- efree (pool -> lock_status .lock_secret );
137- if (pool -> lock_status .lock_key )
138- efree (pool -> lock_status .lock_key );
133+ if (pool -> lock_status .session_key ) zend_string_release (pool -> lock_status .session_key );
134+ if (pool -> lock_status .lock_secret ) zend_string_release (pool -> lock_status .lock_secret );
135+ if (pool -> lock_status .lock_key ) zend_string_release (pool -> lock_status .lock_key );
139136
140137 /* Cleanup pool itself */
141138 efree (pool );
@@ -247,7 +244,7 @@ static int set_session_lock_key(RedisSock *redis_sock, char *cmd, int cmd_len
247244static int lock_acquire (RedisSock * redis_sock , redis_session_lock_status * lock_status
248245 TSRMLS_DC )
249246{
250- char * cmd , hostname [HOST_NAME_MAX ] = {0 };
247+ char * cmd , hostname [HOST_NAME_MAX ] = {0 }, suffix [] = "_LOCK" , pid [ 32 ] ;
251248 int cmd_len , lock_wait_time , retries , i , expiry ;
252249
253250 /* Short circuit if we are already locked or not using session locks */
@@ -273,21 +270,25 @@ static int lock_acquire(RedisSock *redis_sock, redis_session_lock_status *lock_s
273270 }
274271
275272 /* Generate our qualified lock key */
276- spprintf (& lock_status -> lock_key , 0 , "%s%s" , lock_status -> session_key , "_LOCK" );
273+ lock_status -> lock_key = zend_string_alloc (ZSTR_LEN (lock_status -> session_key ) + sizeof (suffix ) - 1 , 0 );
274+ memcpy (ZSTR_VAL (lock_status -> lock_key ), ZSTR_VAL (lock_status -> session_key ), ZSTR_LEN (lock_status -> session_key ));
275+ memcpy (ZSTR_VAL (lock_status -> lock_key ) + ZSTR_LEN (lock_status -> session_key ), suffix , sizeof (suffix ) - 1 );
277276
278277 /* Calculate lock secret */
279278 gethostname (hostname , HOST_NAME_MAX );
280- spprintf (& lock_status -> lock_secret , 0 , "%s|%ld" , hostname , (long )getpid ());
279+ size_t hostname_len = strlen (hostname );
280+ size_t pid_len = snprintf (pid , sizeof (pid ), "|%ld" , (long )getpid ());
281+ lock_status -> lock_secret = zend_string_alloc (hostname_len + pid_len , 0 );
282+ memcpy (ZSTR_VAL (lock_status -> lock_secret ), hostname , hostname_len );
283+ memcpy (ZSTR_VAL (lock_status -> lock_secret ) + hostname_len , pid , pid_len );
281284
282285 if (expiry > 0 ) {
283- cmd_len = REDIS_SPPRINTF (& cmd , "SET" , "ssssd" , lock_status -> lock_key ,
284- strlen (lock_status -> lock_key ), lock_status -> lock_secret ,
285- strlen (lock_status -> lock_secret ), "NX" , 2 ,
286- "PX" , 2 , expiry * 1000 );
286+ cmd_len = REDIS_SPPRINTF (& cmd , "SET" , "SSssd" , lock_status -> lock_key ,
287+ lock_status -> lock_secret , "NX" , 2 , "PX" , 2 ,
288+ expiry * 1000 );
287289 } else {
288- cmd_len = REDIS_SPPRINTF (& cmd , "SET" , "sss" , lock_status -> lock_key ,
289- strlen (lock_status -> lock_key ), lock_status -> lock_secret ,
290- strlen (lock_status -> lock_secret ), "NX" , 2 );
290+ cmd_len = REDIS_SPPRINTF (& cmd , "SET" , "SSs" , lock_status -> lock_key ,
291+ lock_status -> lock_secret , "NX" , 2 );
291292 }
292293
293294 /* Attempt to get our lock */
@@ -310,7 +311,7 @@ static int lock_acquire(RedisSock *redis_sock, redis_session_lock_status *lock_s
310311 return lock_status -> is_locked ? SUCCESS : FAILURE ;
311312}
312313
313- #define IS_LOCK_SECRET (reply , len , secret ) (len == strlen (secret) && !strncmp(reply, secret, len))
314+ #define IS_LOCK_SECRET (reply , len , secret ) (len == ZSTR_LEN (secret) && !strncmp(reply, ZSTR_VAL( secret) , len))
314315static void refresh_lock_status (RedisSock * redis_sock , redis_session_lock_status * lock_status TSRMLS_DC )
315316{
316317 char * cmd , * reply = NULL ;
@@ -327,8 +328,7 @@ static void refresh_lock_status(RedisSock *redis_sock, redis_session_lock_status
327328 return ;
328329
329330 /* Command to get our lock key value and compare secrets */
330- cmdlen = REDIS_SPPRINTF (& cmd , "GET" , "s" , lock_status -> lock_key ,
331- strlen (lock_status -> lock_key ));
331+ cmdlen = REDIS_SPPRINTF (& cmd , "GET" , "S" , lock_status -> lock_key );
332332
333333 /* Attempt to refresh the lock */
334334 reply = redis_simple_cmd (redis_sock , cmd , cmdlen , & replylen TSRMLS_CC );
@@ -377,9 +377,8 @@ static void lock_release(RedisSock *redis_sock, redis_session_lock_status *lock_
377377 /* We first want to try EVALSHA and then fall back to EVAL */
378378 for (i = 0 ; lock_status -> is_locked && i < sizeof (kwd )/sizeof (* kwd ); i ++ ) {
379379 /* Construct our command */
380- cmdlen = REDIS_SPPRINTF (& cmd , (char * )kwd [i ], "sdss" , lua [i ], len [i ], 1 ,
381- lock_status -> lock_key , strlen (lock_status -> lock_key ),
382- lock_status -> lock_secret , strlen (lock_status -> lock_secret ));
380+ cmdlen = REDIS_SPPRINTF (& cmd , (char * )kwd [i ], "sdSS" , lua [i ], len [i ], 1 ,
381+ lock_status -> lock_key , lock_status -> lock_secret );
383382
384383 /* Send it off */
385384 reply = redis_simple_cmd (redis_sock , cmd , cmdlen , & replylen TSRMLS_CC );
@@ -538,7 +537,7 @@ PS_CLOSE_FUNC(redis)
538537 redis_pool * pool = PS_GET_MOD_DATA ();
539538
540539 if (pool ) {
541- redis_pool_member * rpm = redis_pool_get_sock (pool , pool -> lock_status .session_key TSRMLS_CC );
540+ redis_pool_member * rpm = redis_pool_get_sock (pool , ZSTR_VAL ( pool -> lock_status .session_key ) TSRMLS_CC );
542541
543542 RedisSock * redis_sock = rpm ? rpm -> redis_sock : NULL ;
544543 if (redis_sock ) {
@@ -613,18 +612,15 @@ PS_CREATE_SID_FUNC(redis)
613612 }
614613
615614#if (PHP_MAJOR_VERSION < 7 )
616- zend_string * session = redis_session_key (rpm , sid , strlen (sid ));
615+ pool -> lock_status . session_key = redis_session_key (rpm , sid , strlen (sid ));
617616#else
618- zend_string * session = redis_session_key (rpm , ZSTR_VAL (sid ), ZSTR_LEN (sid ));
617+ pool -> lock_status . session_key = redis_session_key (rpm , ZSTR_VAL (sid ), ZSTR_LEN (sid ));
619618#endif
620- pool -> lock_status .session_key = estrndup (ZSTR_VAL (session ), ZSTR_LEN (session ));
621- zend_string_release (session );
622-
623619 if (lock_acquire (redis_sock , & pool -> lock_status TSRMLS_CC ) == SUCCESS ) {
624620 return sid ;
625621 }
626622
627- efree (pool -> lock_status .session_key );
623+ zend_string_release (pool -> lock_status .session_key );
628624#if (PHP_MAJOR_VERSION < 7 )
629625 efree (sid );
630626#else
@@ -664,10 +660,8 @@ PS_READ_FUNC(redis)
664660 }
665661
666662 /* send GET command */
667- zend_string * session = redis_session_key (rpm , skey , skeylen );
668- pool -> lock_status .session_key = estrndup (ZSTR_VAL (session ), ZSTR_LEN (session ));
669- cmd_len = REDIS_SPPRINTF (& cmd , "GET" , "S" , session );
670- zend_string_release (session );
663+ pool -> lock_status .session_key = redis_session_key (rpm , skey , skeylen );
664+ cmd_len = REDIS_SPPRINTF (& cmd , "GET" , "S" , pool -> lock_status .session_key );
671665
672666 if (lock_acquire (redis_sock , & pool -> lock_status TSRMLS_CC ) != SUCCESS ) {
673667 php_error_docref (NULL TSRMLS_CC , E_NOTICE ,
@@ -734,15 +728,14 @@ PS_WRITE_FUNC(redis)
734728 zend_string * session = redis_session_key (rpm , skey , skeylen );
735729#if (PHP_MAJOR_VERSION < 7 )
736730 /* We need to check for PHP5 if the session key changes (a bug with session_regenerate_id() is causing a missing PS_CREATE_SID call)*/
737- int session_key_changed = strlen (pool -> lock_status .session_key ) != ZSTR_LEN (session ) || strncmp (pool -> lock_status .session_key , ZSTR_VAL (session ), ZSTR_LEN (session )) != 0 ;
738- if (session_key_changed ) {
739- efree (pool -> lock_status .session_key );
740- pool -> lock_status .session_key = estrndup (ZSTR_VAL (session ), ZSTR_LEN (session ));
741- }
742-
743- if (session_key_changed && lock_acquire (redis_sock , & pool -> lock_status TSRMLS_CC ) != SUCCESS ) {
744- zend_string_release (session );
745- return FAILURE ;
731+ if (!zend_string_equals (pool -> lock_status .session_key , session )) {
732+ zend_string_release (pool -> lock_status .session_key );
733+ pool -> lock_status .session_key = zend_string_init (ZSTR_VAL (session ), ZSTR_LEN (session ), 0 );
734+ if (lock_acquire (redis_sock , & pool -> lock_status TSRMLS_CC ) != SUCCESS ) {
735+ zend_string_release (pool -> lock_status .session_key );
736+ zend_string_release (session );
737+ return FAILURE ;
738+ }
746739 }
747740#endif
748741 cmd_len = REDIS_SPPRINTF (& cmd , "SETEX" , "Sds" , session , INI_INT ("session.gc_maxlifetime" ), sval , svallen );
0 commit comments