163 Commits

Author SHA1 Message Date
michael-grunder 738cedd284 refactor: Modernize redis_session.c logic
* Switch to using `zend_string*` in a lot of places that were previously
  deconstructing the `zend_string` into the char and len.
* Various other minor bits of cleanup.
2026-06-11 08:02:40 -07:00
michael-grunder ae74b64be7 Fix: Protect cluster session key from length overflow
Rework `cluster_session_key` to return either a newly allocated
`zend_string*` when we have a prefix, or a cheap copy when we don't.

Previously we were using `int` to curry the length which was in theory
susceptible to overflow if `ZSTR_LEN(prefix) + keylen > INT_MAX)`.

Fixes #2866
2026-06-08 09:22:32 -07:00
michael-grunder 2c5ef19257 Introduce new RedisCmd based command construction
* Introduce a new `RedisCmd` struct to dynamically append RESP arguments
  such that we don't have to precalculate the number of arguments the
  command will have up front.

  Additionally the new `RedisCmd allows both a `void *` context pointer
  but also can attach a `void (*ctx_dtor)(void*)` destructor so we are
  still able to clean up any allocated context when commands fail.

  This moves the context cleanup out of every individual reply handler
  and into the generic processing wrappers.

* Create a small group of `resp_str` helper functions for lower level
  concatination of RESP protocol data over the wire.

* Lots of small modernization of the codebase such as using
  `zend_string*` instead of (`char *`, `size_t`) pairs.

* Greatly simplify `crosslot` handling logic
2026-06-04 12:16:35 -07:00
Ilia Alshanetsky b112875b70 session: derive lock secret from php_random_bytes_silent
generate_lock_secret derived the secret from hostname plus pid,
roughly 22 bits of guessable entropy and also readable from Redis
under <key>_LOCK. Replace with 16 bytes from php_random_bytes_silent,
hex-encoded.

Defense in depth: an attacker with write access to the Redis
instance can already bypass the lock by DELing the key, so this is
not a primary defense; worth fixing for the case where only the
lock key itself is exposed. The hostname|pid path stays as a fallback
when php_random_bytes_silent fails, so the caller always gets a
non-NULL secret.
2026-05-19 17:23:08 -07:00
michael-grunder 9a17083125 Tiny refactor of 8.6 save path compatibility
When `save_path` is a `zend_string` we don't have to calculate the
length.
2026-03-26 14:29:13 -07:00
Rasmus Lerdorf b8b765e610 Fix compilation against PHP 8.6 (session save_path is now zend_string*) 2026-03-26 09:58:02 -07:00
michael-grunder e39d9b74f4 Modernize session locking
Add support for Redis' `DELEX` and Valkey's `DELIFEQ` when deleting the
session lock key. Local testing shows about a 10-15% improvement over
the current `EVAL[SHA]` strategy.

This commit adds a new INI settingg:
```ini
redis.session.lock_release_cmd = delex|delifeq|eval
```

By default we continue to use the `EVAL` logic and if a user specifies
another mechanism but the command doesn't exist, we warn the user and
fall back to EVAL.

This commit also refactors a few functions to avoid UB and simplify key
construction.
2026-03-01 14:52:39 -08:00
michael-grunder b97951cddc Rework TLS context logic
Instead of currying around a `php_stream_context` object, just retain
the context array provided by the user itself like we do with other
connection information like host and port. This lets users reconnect in
a loop without leaking memory.

```php
$redis = new \Redis;
while (true) {
    // Previously each reconnect call would leak the
    // `php_stream_context` structure.
    $redis->connect('tls://127.0.0.1', 9999, 1, null, 0, 0, [
        'stream' => ['verify_peer' => false, 'verify_peer_name' => false],
    ]);

    $redis->ping();

    $redis->close();
}
```
2026-02-18 09:46:55 -08:00
Niels Dossche d24528e190 Replace legacy zval_dtor() alias with zval_ptr_dtor_nogc() 2025-11-16 14:07:06 -08:00
michael-grunder 025b0e9772 Prevent UB in session weighted selection
```c
int pos, i;
memcpy(&pos, key, sizeof(pos));
pos %= pool->totalWeight;
```

As unlikely as it is, this may cause UB if user's are generating their
own session IDs shorter than three bytes. This commit checks the session
id length and only copies in the bytes that we have.

Technically this could change behavior for session ID's of length 2 or
less, but this seems acceptable because currently such an ID would end
up selecing a server at random, depending on whatever bytes were past
the end of the `zend_string`.

In a future release we will fix this logic to use all of the entropy of
the session ID as well as ensure `pool->totalWeight` is > 0.
2025-11-05 13:49:20 -08:00
michael-grunder bf2047e067 Inform the user if we couldn't extract any session servers.
Add a specific warning when we can't parse any servers from
`php.session_save_path`.

PHP will then display the save path, but this will let users know there
was a problem parsing the path.

Fixes #1390

Signed-off-by: michael-grunder <michael.grunder@gmail.com>
2025-10-31 11:11:27 -07:00
michael-grunder 453c4788d6 Improve error message when picking session compression
The warning when a user picks an unsupported session compression
algorithm was pretty confusing.

The new message tells the user if the selection was invalid or only
invalid because the redis.so wasn't built with support.

Fixes #2570
2025-10-31 11:10:45 -07:00
Anton Smirnov 8dada174c4 Add an INI setting returning 5.x legacy behavior -- readonly session on lock failure 2025-07-09 20:07:57 -07:00
peter15914 43e6cab879 Fix potential NULL dereference
The return value of INI_STR() is always checked for NULL.
2025-01-02 11:34:52 -08:00
michael-grunder 085d61ecfb Create a strncmp wrapper
On some glibc implementations strncmp is a macro. This commit simply creates a
`redis_strncmp` static inline wrapper function so we can `ZEND_STRL` instead of
manually counting the length or using `sizeof(s)-1` each time.

Fixes #2565
2024-10-15 10:40:15 -07:00
Remi Collet 37cebdd70b cleanup code for unsupported versions 2024-08-05 08:58:58 -07:00
michael-grunder 3d7be35816 Consolidate failure path 2024-04-09 12:58:45 -07:00
michael-grunder 0e92616591 Fix memory leak if we fail in ps_open_redis. 2024-04-09 12:58:45 -07:00
michael-grunder 2b555c89ef Minor session compression cleanup.
* We can compress without the need for sepearate buffers.
* Allow both "" and "none" to mean "none" in terms of
  redis.session.compression.
2024-04-08 15:11:52 -07:00
bitactive da4ab0a72c Add compression support for PHP Sessions (#2473)
* Add compression support for PHP Sessions

Previously, compression was available for standard data but not for
session handling. This update enables the compression of PHP sessions,
allowing for more efficient Redis memory usage.

* Move session compress/uncompress logic to helper functions

* Change session_compress_data to always set the out arguments and adjust PS_READ_FUNC
2024-04-08 14:40:15 -07:00
Bitactive b698901818 Support for early_refresh in Redis sessions to match cluster behavior
Previously, the redis.session.early_refresh feature was implemented for
Redis Cluster, utilizing GETEX for the initial session read to minimize
the number of commands sent to the Redis server. However, this enhancement
was not applied to non-cluster sessions. This update addresses this
discrepancy, ensuring consistent behavior between Redis and Redis Cluster.
2024-03-28 13:19:47 -07:00
Viktor Szépe 37c5f8d451 Fix typos 2024-02-21 13:16:12 -08:00
thomaston a3327d9d2b Fix bug: the pipeline mode socket return an unexpected result after reconnecting (#2358)
* fix bug: the pipeline mode socket return an unexpected result after reconnecting

* fix typos: pipeline is right

---------

Co-authored-by: marcofu <marcofu@tencent.com>
2023-07-20 11:48:53 -07:00
Pavlo Yatsukhnenko 6930a81cb4 Auto-select db in redis_sock_server_open 2023-04-02 14:24:41 +03:00
zorro-fr24 b6cf6361dd Add cluster support for strict sessions and lazy write
* Add ini setting redis.session.early_refresh to allow for session TTL updates on session start ( requires redis server version 6.2 or greater )
 * Enable cluster session support for strict mode sessions ( via PS_VALIDATE_SID_FUNC )
 * Cluster sessions used to write on every session, now we only write if the session has been modified.
 * Send EXPIRE instead of SETEX if sessioh has not been changed
 * If early refresh is enabled use GETEX for initial session read
 * When strict sessions are enabled, check whether the session exists first, validate sid and regenerate if necessary
2022-12-06 10:45:52 -08:00
Michael Grunder b3ce048669 Fix non standards conforming prototypes. (#2150)
These now generate warnings with GCC 13
2022-09-14 22:54:22 -07:00
Pavlo Yatsukhnenko a471c87a3b Issue #2141
Fix segfault with session+tls
2022-08-21 14:59:39 +03:00
patricio.dorantes 2ff11df528 redis_session clean up ssl context. 2022-08-03 10:57:01 -05:00
patricio.dorantes d1bc672752 fix use after free, initialize on NULL 2022-08-02 17:36:54 -05:00
patricio.dorantes ed10f365e7 fix redis session standalone stream ssl context 2022-08-01 11:16:24 -05:00
michael-grunder 306fa25c19 Smaller default retry count
See #1908
2021-03-09 11:25:29 -08:00
Mike Griego 687a0b4050 Fail if session lock can't be acquired, more sane lock wait defaults, and add more logging. 2021-03-09 11:09:06 -08:00
Pavlo Yatsukhnenko a8daaff87a Issue #1782
Allow to specify stream context for rediscluster session handler.
2020-09-08 17:58:08 +03:00
Pavlo Yatsukhnenko b2cffffc10 Fix memory leak in rediscluster session handler 2020-08-14 16:56:32 +03:00
michael-grunder 066cff6ade Proper cleanup and conditional address deallocation.
See: #1807
2020-07-07 09:41:39 -07:00
michael-grunder 7fed60f248 We don't want to efree a zend_string 2020-07-06 13:16:30 -07:00
Michael Grunder ff2e160f40 Don't attempt to take ZSTR_VAL(NULL) (#1804)
Fixes #1798
2020-07-02 09:56:54 -07:00
Michael Grunder a311cc4ec3 Support for Redis 6 ACLs (#1791)
Add support for Redis 6 ACLs in the `Redis`, `RedisCluster`, and `RedisArray` classes.

On a related note, it adds a mechanism for users to customize how we generate persistent connection IDs such that they can be grouped in different ways depending on the specific use case required (e.g. it would allow connections to be grouped by username, or by user-defined persistent_id, or both).
2020-06-24 17:00:01 -07:00
Michael Grunder 5ca4141c72 Issue.1765 (#1774)
Various improvements and fixes to cluster slot caching.

* Improves slot caching so any unique set of seeds all hash to the same key

* Fix a couple of memory leaks.

* Fixes a segfault when executing a multiple key command such as `MGET` or `MSET` while the cluster is resharding.
2020-06-07 13:50:22 -07:00
Pavlo Yatsukhnenko 58dab5649f Store auth information in cluster->flags->auth 2020-06-05 10:27:48 +03:00
Pavlo Yatsukhnenko 35372a1f64 Authenticate in redis_sock_server_open 2020-03-30 22:34:12 +03:00
Tyson Andre 0ef488fca7 Remove "PHP Version 5" section
package.xml has a minimum version of 7.0
PHP 8.0 will probably be out in around a year.
2020-01-13 18:41:03 -05:00
michael-grunder 7a79ad9c27 Also protect against session.gc_maxlifetime <= 0
Addresses #1694
2020-01-10 09:47:58 -08:00
michael-grunder 3c48a332d2 Protect session.gc_maxlifetime from integer overflow 2020-01-10 09:47:58 -08:00
Tyson Andre f52bd8a853 Fix typos detected by codespell 2020-01-06 09:08:36 -05:00
Michael Booth 23b1a9d84c Enable slot caching for session cluster 2019-12-02 09:00:12 +00:00
Pavlo Yatsukhnenko 53a8bcc7a9 Issue #1657
Allow to specify schema for session handler.
2019-10-26 17:54:27 +03:00
Pavlo Yatsukhnenko 2bb086802e Issue #1631 2019-10-07 15:00:36 +03:00
Pavlo Yatsukhnenko 91a8e73441 Refactor redis_session
Use strpprintf instead of zend_string_alloc + memcpy.
2019-07-27 21:03:23 +03:00
Pavlo Yatsukhnenko 7d4470a735 Refactor redis_session
Remove `refresh_lock_status` helper function
2019-07-24 22:00:45 +03:00