diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
index 2dcb6673..2e10b05b 100644
--- a/.github/workflows/build-and-test.yml
+++ b/.github/workflows/build-and-test.yml
@@ -1,3 +1,5 @@
+
+name: Test on Ubuntu
on: [push, pull_request]
jobs:
@@ -7,13 +9,10 @@ jobs:
strategy:
fail-fast: false
matrix:
- php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2']
+ php: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
experimental: [false]
include:
- - php: '8.2'
- awesome: true
- experimental: true
- - php: '8.3'
+ - php: '8.4'
experimental: true
steps:
- name: Checkout
@@ -29,20 +28,8 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install cmake memcached libsasl2-dev sasl2-bin zlib1g-dev
- - if: ${{ ! matrix.awesome }}
- name: Install libmemcached-dev (from distro)
+ - name: Install libmemcached-dev
run: sudo apt-get install libmemcached-dev
- - if: ${{ matrix.awesome }}
- name: Install libmemcached-awesome (from source)
- run: |
- curl -sL -o libmemcached.tgz https://github.com/awesomized/libmemcached/archive/refs/tags/1.1.3.tar.gz
- mkdir libmemcached
- tar --strip-components=1 -xf libmemcached.tgz -C libmemcached
- mkdir build-libmemcached
- cd build-libmemcached
- cmake -D ENABLE_HASH_HSIEH=ON -D ENABLE_SASL=ON ../libmemcached
- make
- sudo make install
- name: Start memcached daemons
run: |
export SASL_CONF_PATH="/tmp/sasl2"
@@ -83,7 +70,7 @@ jobs:
define ("MEMC_SASL_SERVER_HOST", "127.0.0.1");
define ("MEMC_SASL_SERVER_PORT", 11212);
-
+
define ('MEMC_SASL_USER', 'memcached');
define ('MEMC_SASL_PASS', 'test');
EOF
diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml
index a7aa8577..15dba3f2 100644
--- a/.github/workflows/build-windows.yml
+++ b/.github/workflows/build-windows.yml
@@ -7,23 +7,30 @@ jobs:
shell: cmd
strategy:
matrix:
- version: ['7.4', '8.0', '8.1']
+ version: ['8.3', '8.4']
arch: [x64, x86]
ts: [nts, zts]
+ exclude:
+ - { version: '8.4', arch: x64, ts: zts }
+ - { version: '8.4', arch: x86, ts: nts }
+ - { version: '8.4', arch: x86, ts: zts }
runs-on: windows-latest
steps:
- name: Checkout memcached
uses: actions/checkout@v4
- name: Setup PHP
id: setup-php
- uses: cmb69/setup-php-sdk@v0.7
+ uses: php/setup-php-sdk@v0.10
with:
version: ${{matrix.version}}
arch: ${{matrix.arch}}
ts: ${{matrix.ts}}
deps: zlib
+ cache: true
- name: Fetch libmemcached
- run: curl -OLs https://windows.php.net/downloads/pecl/deps/libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip && 7z x libmemcached-1.1.1-${{steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip -o..\deps
+ run: |
+ set MEMCACHED_FILENAME=libmemcached-1.1.4-${{steps.setup-php.outputs.vs == 'vs17' && 'vs16' || steps.setup-php.outputs.vs}}-${{matrix.arch}}.zip
+ curl -OLs https://downloads.php.net/~windows/pecl/deps/%MEMCACHED_FILENAME% && 7z x %MEMCACHED_FILENAME% -o..\deps
- name: Enable Developer Command Prompt
uses: ilammy/msvc-dev-cmd@v1
with:
diff --git a/README.markdown b/README.markdown
index b17b7e55..38dbd5bc 100644
--- a/README.markdown
+++ b/README.markdown
@@ -1,6 +1,6 @@
Build Status
------------
-[](https://travis-ci.org/php-memcached-dev/php-memcached)
+
Description
-----------
@@ -23,7 +23,7 @@ Dependencies
------------
php-memcached 3.x:
-* Supports PHP 7.0 - 8.2 or higher.
+* Supports PHP 7.0 - 8.3 or higher.
* Requires libmemcached 1.x or higher.
* Optionally supports igbinary 2.0 or higher.
* Optionally supports msgpack 2.0 or higher.
diff --git a/composer.json b/composer.json
new file mode 100644
index 00000000..3356c89d
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,68 @@
+{
+ "name": "php-memcached/php-memcached",
+ "type": "php-ext",
+ "license": "PHP-3.01",
+ "description": "memcached extension based on libmemcached library ",
+ "require": {
+ "php": ">= 7.0.0"
+ },
+ "suggest": {
+ "ext-igbinary": "igbinary is a faster and more compact binary serializer for PHP data structures.",
+ "ext-msgpack": "msgpack is a faster and more compact data structure representation that is interoperable with msgpack implementations for other languages."
+ },
+ "php-ext": {
+ "extension-name": "memcached",
+ "configure-options": [
+ {
+ "name": "enable-memcached",
+ "description": "Enable memcached support"
+ },
+ {
+ "name": "with-libmemcached-dir",
+ "description": "Set the path to libmemcached install prefix.",
+ "needs-value": true
+ },
+ {
+ "name": "enable-memcached-session",
+ "description": "Enable memcached session handler support"
+ },
+ {
+ "name": "enable-memcached-igbinary",
+ "description": "Enable memcached igbinary serializer support"
+ },
+ {
+ "name": "enable-memcached-json",
+ "description": "Enable memcached json serializer support"
+ },
+ {
+ "name": "enable-memcached-msgpack",
+ "description": "Enable memcached msgpack serializer support"
+ },
+ {
+ "name": "enable-memcached-sasl",
+ "description": "Enable memcached sasl support"
+ },
+ {
+ "name": "enable-memcached-protocol",
+ "description": "Enable memcached protocol support"
+ },
+ {
+ "name": "with-system-fastlz",
+ "description": "Use system FastLZ library"
+ },
+ {
+ "name": "with-zstd",
+ "description": "Use system zstd library"
+ },
+ {
+ "name": "with-zlib-dir",
+ "description": "Set the path to ZLIB install prefix.",
+ "needs-value": true
+ },
+ {
+ "name": "enable-debug",
+ "description": "Compile with debugging symbols"
+ }
+ ]
+ }
+}
diff --git a/package.xml b/package.xml
index 6a14b96c..5565863e 100644
--- a/package.xml
+++ b/package.xml
@@ -33,19 +33,24 @@ http://pear.php.net/dtd/package-2.0.xsd">
remi@php.net
yes
- 2022-03-24
+
+ Michael Wallner
+ mike
+ mike@php.net
+ yes
+
+ 2024-10-17
- 3.2.1dev
- 3.2.0
+ 3.3.1dev
+ 3.3.0
- stable
+ beta
stable
PHP
-- mark password as a sensitive param for PHP 8.2
-- Fix #523 Incorrect PHP reflection type for Memcached::cas $cas_token
+-
@@ -216,6 +221,31 @@ http://pear.php.net/dtd/package-2.0.xsd">
+
+ 2024-10-17
+
+ 3.3.0
+ 3.3.0
+
+
+ stable
+ stable
+
+ PHP
+
+- Add #515 option to locally enforce payload size limit
+- Add #539 zstd support
+- Add #540 compression_level option
+- Mark password as a sensitive param for PHP 8.2
+- Upgrade Windows libmemcached to v1.1.4
+- Fix Windows PHP 8 compatibility
+- Fix #518 Windows msgpack support
+- Fix #522 signed integer overflow
+- Fix #523 incorrect PHP reflection type for Memcached::cas $cas_token
+- Fix #546 don't check key automatically, unless client-side verify_key is enabled
+- Fix #555 incompatible pointer types (32-bit)
+
+
2022-03-24
diff --git a/php_memcached.c b/php_memcached.c
index 00d5e3d4..b78eb82a 100644
--- a/php_memcached.c
+++ b/php_memcached.c
@@ -231,24 +231,43 @@ zend_bool s_memc_valid_key_binary(zend_string *key)
}
static
-zend_bool s_memc_valid_key_ascii(zend_string *key)
+uint32_t s_memc_object_key_max_length(php_memc_object_t *intern) {
+ memcached_return retval;
+ char *result;
+
+ result = memcached_callback_get(intern->memc, MEMCACHED_CALLBACK_PREFIX_KEY, &retval);
+ if (retval == MEMCACHED_SUCCESS && result) {
+ return MEMC_OBJECT_KEY_MAX_LENGTH - strlen(result);
+ } else {
+ return MEMC_OBJECT_KEY_MAX_LENGTH;
+ }
+}
+
+zend_bool s_memc_valid_key_ascii(zend_string *key, uint64_t verify_key)
{
const char *str = ZSTR_VAL(key);
size_t i, len = ZSTR_LEN(key);
- for (i = 0; i < len; i++) {
- if (!isgraph(str[i]) || isspace(str[i]))
- return 0;
+ if (verify_key) {
+ for (i = 0; i < len; i++) {
+ if (!isgraph(str[i]) || isspace(str[i]))
+ return 0;
+ }
+ } else { /* if key verification is disabled, only check for spaces to avoid injection issues */
+ for (i = 0; i < len; i++) {
+ if (isspace(str[i]))
+ return 0;
+ }
}
return 1;
}
#define MEMC_CHECK_KEY(intern, key) \
if (UNEXPECTED(ZSTR_LEN(key) == 0 || \
- ZSTR_LEN(key) > MEMC_OBJECT_KEY_MAX_LENGTH || \
+ ZSTR_LEN(key) > s_memc_object_key_max_length(intern) || \
(memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) \
? !s_memc_valid_key_binary(key) \
- : !s_memc_valid_key_ascii(key) \
+ : !s_memc_valid_key_ascii(key, memcached_behavior_get(intern->memc, MEMCACHED_BEHAVIOR_VERIFY_KEY)) \
))) { \
intern->rescode = MEMCACHED_BAD_KEY_PROVIDED; \
RETURN_FALSE; \
@@ -342,7 +361,7 @@ PHP_INI_MH(OnUpdateSessionPrefixString)
php_error_docref(NULL, E_WARNING, "memcached.sess_prefix too long (max: %d)", MEMCACHED_MAX_KEY - 1);
return FAILURE;
}
- if (!s_memc_valid_key_ascii(new_value)) {
+ if (!s_memc_valid_key_ascii(new_value, 1)) {
php_error_docref(NULL, E_WARNING, "memcached.sess_prefix cannot contain whitespace or control characters");
return FAILURE;
}
@@ -933,7 +952,7 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_lon
case COMPRESSION_TYPE_ZLIB:
{
- compressed_size = buffer_size;
+ unsigned long cs = compressed_size = buffer_size;
if (compression_level < 0) {
compression_level = 0;
@@ -941,9 +960,10 @@ zend_bool s_compress_value (php_memc_compression_type compression_type, zend_lon
compression_level = 9;
}
- int status = compress2((Bytef *) buffer, &compressed_size, (Bytef *) ZSTR_VAL(payload), ZSTR_LEN(payload), compression_level);
+ int status = compress2((Bytef *) buffer, &cs, (Bytef *) ZSTR_VAL(payload), ZSTR_LEN(payload), compression_level);
if (status == Z_OK) {
+ compressed_size = cs;
compress_status = 1;
compression_type_flag = MEMC_VAL_COMPRESSION_ZLIB;
}
@@ -3751,7 +3771,10 @@ zend_string *s_decompress_value (const char *payload, size_t payload_len, uint32
decompress_status = ((length = fastlz_decompress(payload, payload_len, &buffer->val, buffer->len)) > 0);
}
else if (is_zlib) {
- decompress_status = (uncompress((Bytef *) buffer->val, &buffer->len, (Bytef *)payload, payload_len) == Z_OK);
+ unsigned long ds = buffer->len;
+
+ decompress_status = (uncompress((Bytef *) buffer->val, &ds, (Bytef *)payload, payload_len) == Z_OK);
+ buffer->len = ds;
}
ZSTR_VAL(buffer)[stored_length] = '\0';
@@ -3938,7 +3961,7 @@ zend_class_entry *php_memc_get_exception_base(int root)
}
}
- return zend_exception_get_default();
+ return zend_ce_exception;
}
diff --git a/php_memcached.h b/php_memcached.h
index e966d19d..dfd19185 100644
--- a/php_memcached.h
+++ b/php_memcached.h
@@ -30,7 +30,7 @@
# include "config.h"
#endif
-#define PHP_MEMCACHED_VERSION "3.2.1-dev"
+#define PHP_MEMCACHED_VERSION "3.3.1dev"
#if defined(PHP_WIN32) && defined(MEMCACHED_EXPORTS)
#define PHP_MEMCACHED_API __declspec(dllexport)
diff --git a/php_memcached_private.h b/php_memcached_private.h
index 2c22ecba..b7d2a5e1 100644
--- a/php_memcached_private.h
+++ b/php_memcached_private.h
@@ -43,7 +43,11 @@
#include
#include
#include
+#if PHP_VERSION_ID < 70200
#include
+#else
+#include
+#endif
#include
#include
diff --git a/tests/cas_invalid_key.phpt b/tests/cas_invalid_key.phpt
index b8a815dc..9cb7293c 100644
--- a/tests/cas_invalid_key.phpt
+++ b/tests/cas_invalid_key.phpt
@@ -5,7 +5,10 @@ Memcached::cas() with strange key
--FILE--
false,
+ Memcached::OPT_VERIFY_KEY => true
+));
error_reporting(0);
var_dump($m->cas(0, '', true, 10));
diff --git a/tests/delete_bykey.phpt b/tests/delete_bykey.phpt
index 929ffbc1..6aa589c5 100644
--- a/tests/delete_bykey.phpt
+++ b/tests/delete_bykey.phpt
@@ -5,7 +5,10 @@ Memcached::deleteByKey()
--FILE--
false,
+ Memcached::OPT_VERIFY_KEY => true
+));
$m->setByKey('keffe', 'eisaleeoo', "foo");
var_dump($m->getByKey('keffe', 'eisaleeoo'));
diff --git a/tests/get.phpt b/tests/get.phpt
index 71889064..722308f0 100644
--- a/tests/get.phpt
+++ b/tests/get.phpt
@@ -5,7 +5,10 @@ Memcached::get()
--FILE--
false,
+ Memcached::OPT_VERIFY_KEY => true
+));
$m->delete('foo');
diff --git a/tests/keys_ascii.phpt b/tests/keys_ascii.phpt
index f7e98894..e7846e99 100644
--- a/tests/keys_ascii.phpt
+++ b/tests/keys_ascii.phpt
@@ -8,11 +8,8 @@ Test valid and invalid keys - ascii
include dirname (__FILE__) . '/config.inc';
$ascii = memc_get_instance (array (
Memcached::OPT_BINARY_PROTOCOL => false,
- Memcached::OPT_VERIFY_KEY => false
+ Memcached::OPT_VERIFY_KEY => true
));
-// libmemcached can verify keys, but these are tests are for our own
-// function s_memc_valid_key_ascii, so explicitly disable the checks
-// that libmemcached can perform.
echo 'ASCII: SPACES' . PHP_EOL;
var_dump ($ascii->set ('ascii key with spaces', 'this is a test'));