Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package memcached for openSUSE:Factory 
checked in at 2026-08-04 21:29:57
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/memcached (Old)
 and      /work/SRC/openSUSE:Factory/.memcached.new.16738 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "memcached"

Tue Aug  4 21:29:57 2026 rev:76 rq:1369291 version:1.6.45

Changes:
--------
--- /work/SRC/openSUSE:Factory/memcached/memcached.changes      2026-07-09 
22:18:11.195691713 +0200
+++ /work/SRC/openSUSE:Factory/.memcached.new.16738/memcached.changes   
2026-08-04 21:30:06.215111555 +0200
@@ -1,0 +2,34 @@
+Mon Aug  3 13:22:24 UTC 2026 - Petr Gajdos <[email protected]>
+
+- update to 1.6.45:
+  * proxy: extra warning for user config error
+  * proto: convert more strto calls
+  * proto: meta preparse F flag fix
+  * proxy: fix res:line() returning wrong response
+  * proxy: fix overread of spaces for large gets
+  * ascii: safely convert flag args to numerics
+  * ascii: fix unlocked refcount-- on error path
+  * proxy: key filter null byte written to wrong place
+  * proxy: fix detail len clamp in request logging
+  * proxy: enforce minimum rate limit
+  * ascii: fix refcount leak on ms parse error
+  * proxy: reserve enough log space for proxy BE_EVENT
+  * network: fix segfault on OOM during net read
+  * proxy: fix missing default handler in resnull
+  * stats: cap stats prefix count at 2^16
+  * binprot: GETK against extstore internal miss can hang worker
+  * proxy: fix memory leak after failed request render
+  * proxy: fix underflow in key hash filters
+  * logger: closed worker fix again
+  * ascii: fix crash with invalid automove windows
+  * proxy: fix footgun when excessive backend labels
+  * slabs: fix off by one in slab picker loop
+  * ascii: fix potential overrun when given all spaces
+  * proxy: fix mutator crash in flagcopyall
+  * restart: avoid runaway read with corrupt file
+  * proxy: fix ring hash default mode
+  * tls: uninitialized string can be used in error
+  * proxy: fix off by one in request_append
+  * logger: fix use-after-free of closed watcher
+
+-------------------------------------------------------------------
@@ -4 +38 @@
-- update to 1.6.44:
+- update to 1.6.44: [bsc#1270716]

Old:
----
  memcached-1.6.44.tar.gz

New:
----
  memcached-1.6.45.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ memcached.spec ++++++
--- /var/tmp/diff_new_pack.dHiHVm/_old  2026-08-04 21:30:07.175144863 +0200
+++ /var/tmp/diff_new_pack.dHiHVm/_new  2026-08-04 21:30:07.179145002 +0200
@@ -42,7 +42,7 @@
 %endif
 %endif
 Name:           memcached
-Version:        1.6.44
+Version:        1.6.45
 Release:        0
 Summary:        A high-performance, distributed memory object caching system
 License:        BSD-3-Clause

++++++ memcached-1.6.44.tar.gz -> memcached-1.6.45.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/configure 
new/memcached-1.6.45/configure
--- old/memcached-1.6.44/configure      2026-07-07 06:24:04.000000000 +0200
+++ new/memcached-1.6.45/configure      2026-07-10 06:35:10.000000000 +0200
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.72 for memcached 1.6.44.
+# Generated by GNU Autoconf 2.72 for memcached 1.6.45.
 #
 # Report bugs to <[email protected]>.
 #
@@ -604,8 +604,8 @@
 # Identity of this package.
 PACKAGE_NAME='memcached'
 PACKAGE_TARNAME='memcached'
-PACKAGE_VERSION='1.6.44'
-PACKAGE_STRING='memcached 1.6.44'
+PACKAGE_VERSION='1.6.45'
+PACKAGE_STRING='memcached 1.6.45'
 PACKAGE_BUGREPORT='[email protected]'
 PACKAGE_URL=''
 
@@ -1383,7 +1383,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-'configure' configures memcached 1.6.44 to adapt to many kinds of systems.
+'configure' configures memcached 1.6.45 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1454,7 +1454,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of memcached 1.6.44:";;
+     short | recursive ) echo "Configuration of memcached 1.6.45:";;
    esac
   cat <<\_ACEOF
 
@@ -1579,7 +1579,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-memcached configure 1.6.44
+memcached configure 1.6.45
 generated by GNU Autoconf 2.72
 
 Copyright (C) 2023 Free Software Foundation, Inc.
@@ -2194,7 +2194,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by memcached $as_me 1.6.44, which was
+It was created by memcached $as_me 1.6.45, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   $ $0$ac_configure_args_raw
@@ -3745,7 +3745,7 @@
 
 # Define the identity of the package.
  PACKAGE='memcached'
- VERSION='1.6.44'
+ VERSION='1.6.45'
 
 
 printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -9429,7 +9429,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by memcached $as_me 1.6.44, which was
+This file was extended by memcached $as_me 1.6.45, which was
 generated by GNU Autoconf 2.72.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -9497,7 +9497,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-memcached config.status 1.6.44
+memcached config.status 1.6.45
 configured by $0, generated by GNU Autoconf 2.72,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/doc/Makefile 
new/memcached-1.6.45/doc/Makefile
--- old/memcached-1.6.44/doc/Makefile   2026-07-07 06:24:07.000000000 +0200
+++ new/memcached-1.6.45/doc/Makefile   2026-07-10 06:35:12.000000000 +0200
@@ -194,10 +194,10 @@
 PACKAGE = memcached
 PACKAGE_BUGREPORT = [email protected]
 PACKAGE_NAME = memcached
-PACKAGE_STRING = memcached 1.6.44
+PACKAGE_STRING = memcached 1.6.45
 PACKAGE_TARNAME = memcached
 PACKAGE_URL = 
-PACKAGE_VERSION = 1.6.44
+PACKAGE_VERSION = 1.6.45
 PATH_SEPARATOR = :
 PKG_CONFIG = /usr/bin/pkg-config
 PKG_CONFIG_LIBDIR = 
@@ -208,7 +208,7 @@
 SET_MAKE = 
 SHELL = /bin/bash
 STRIP = 
-VERSION = 1.6.44
+VERSION = 1.6.45
 XML2RFC = no
 XSLTPROC = no
 abs_builddir = /home/dormando/p/code/memcached/doc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/logger.c 
new/memcached-1.6.45/logger.c
--- old/memcached-1.6.44/logger.c       2026-05-18 23:43:09.000000000 +0200
+++ new/memcached-1.6.45/logger.c       2026-07-10 06:32:06.000000000 +0200
@@ -379,6 +379,7 @@
     }
     if (dlen > 150) {
         dlen = 150;
+        le->dlen = dlen;
     }
     // be_namelen and be_portlen can't be longer than 255+6
     le->reqlen = reqlen;
@@ -550,7 +551,7 @@
     [LOGGER_PROXY_USER] = {512, LOG_PROXYUSER, _logger_log_text, 
_logger_parse_text,
         "type=proxy_user msg=%s"
     },
-    [LOGGER_PROXY_BE_ERROR] = {512, LOG_PROXYEVENTS, _logger_log_proxy_errbe, 
_logger_parse_prx_errbe,
+    [LOGGER_PROXY_BE_ERROR] = {1024, LOG_PROXYEVENTS, _logger_log_proxy_errbe, 
_logger_parse_prx_errbe,
         NULL
     },
 
@@ -687,9 +688,17 @@
                 (skip_scr = (char *) bipbuf_request(w->buf, scratch_len + 
128)) == NULL) {
             if (logger_thread_poll_watchers(0, x) <= 0) {
                 L_DEBUG("LOGGER: Watcher had no free space for line of size 
(%d)\n", scratch_len + 128);
+                // Oddity; poll_watchers can free *w, recheck it.
+                if (watchers[x] == NULL) {
+                    break;
+                }
                 w->failed_flush = true;
             }
         }
+        // See oddity note above.
+        if (watchers[x] == NULL) {
+            continue;
+        }
 
         if (w->failed_flush) {
             L_DEBUG("LOGGER: Fast skipped for watcher [%d] due to 
failed_flush\n", w->sfd);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/memcached.c 
new/memcached-1.6.45/memcached.c
--- old/memcached-1.6.44/memcached.c    2026-07-07 05:19:47.000000000 +0200
+++ new/memcached-1.6.45/memcached.c    2026-07-10 06:32:06.000000000 +0200
@@ -2456,9 +2456,13 @@
                     fprintf(stderr, "Couldn't realloc input buffer\n");
                 }
                 c->rbytes = 0; /* ignore what we read */
-                out_of_memory(c, "SERVER_ERROR out of memory reading request");
-                c->close_after_write = true;
-                return READ_MEMORY_ERROR;
+                if (!resp_start(c)) {
+                    return READ_ERROR;
+                } else {
+                    out_of_memory(c, "SERVER_ERROR out of memory reading 
request");
+                    c->close_after_write = true;
+                    return READ_MEMORY_ERROR;
+                }
             }
             c->rcurr = c->rbuf = new_rbuf;
             c->rsize *= 2;
@@ -5279,8 +5283,8 @@
                     goto error;
                 }
                 settings.slab_automove_window = atoi(subopts_value);
-                if (settings.slab_automove_window < 3) {
-                    fprintf(stderr, "slab_automove_window must be > 2\n");
+                if (settings.slab_automove_window < 3 || 
settings.slab_automove_window > 1800) {
+                    fprintf(stderr, "slab_automove_window must be > 2 and < 
1800\n");
                     goto error;
                 }
                 break;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/memcached.spec 
new/memcached-1.6.45/memcached.spec
--- old/memcached-1.6.44/memcached.spec 2026-07-07 06:24:04.000000000 +0200
+++ new/memcached-1.6.45/memcached.spec 2026-07-10 06:35:09.000000000 +0200
@@ -27,7 +27,7 @@
 %endif
 
 Name:           memcached
-Version:        1.6.44
+Version:        1.6.45
 Release:        1%{?dist}
 Summary:        High Performance, Distributed Memory Object Cache
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/proto_parser.c 
new/memcached-1.6.45/proto_parser.c
--- old/memcached-1.6.44/proto_parser.c 2026-07-03 02:30:18.000000000 +0200
+++ new/memcached-1.6.45/proto_parser.c 2026-07-10 06:32:06.000000000 +0200
@@ -333,15 +333,6 @@
  * PARSER UTIL CODE
  */
 
-// TODO:
-// - the safe_strto calls in here are still "string-y" - they're going to
-// parse until a space or newline. This is perfectly safe for any time we're
-// in this code; since we can't get here without a \n or a space (ie;
-// non-digit)
-// - I'm not converting these to tokto*'s right now, because what they're
-// pulling the flag while in a loop. So we need yet another interface (or
-// refactor of existing interface). This code is safe, just not consistent.
-
 int mc_prcmp(mcp_parser_t *pr, int token, const char *s) {
     int len = 0;
     const char *t = mcmc_token_get(pr->request, &pr->tok, token, &len);
@@ -421,7 +412,7 @@
 
 bool mc_parse_exptime(mc_resp *resp, mcp_parser_t *pr, int token, rel_time_t 
*exptime) {
     int32_t exptime_int = 0;
-    if (!safe_strtol(&pr->request[pr->tok.tokens[1]], &exptime_int)) {
+    if (mcmc_token_get_32(pr->request, &pr->tok, token, &exptime_int) != 
MCMC_OK) {
         pout_string(resp, "CLIENT_ERROR invalid exptime argument");
         return false;
     }
@@ -521,30 +512,30 @@
             case 'N':
                 of->locked = 1;
                 of->vivify = 1;
-                if (!safe_strtol(&pr->request[pr->tok.tokens[i]+1], &tmp_int)) 
{
+                if (mcmc_token_get_flag_arg_32(pr->request, &pr->tok, i, 
&tmp_int) == MCMC_OK) {
+                    of->autoviv_exptime = 
realtime(EXPTIME_TO_POSITIVE_TIME(tmp_int));
+                } else {
                     *errstr = "CLIENT_ERROR bad token in command line format";
                     of->has_error = 1;
-                } else {
-                    of->autoviv_exptime = 
realtime(EXPTIME_TO_POSITIVE_TIME(tmp_int));
                 }
                 break;
             case 'T':
                 of->locked = 1;
-                if (!safe_strtol(&pr->request[pr->tok.tokens[i]+1], &tmp_int)) 
{
-                    *errstr = "CLIENT_ERROR bad token in command line format";
-                    of->has_error = 1;
-                } else {
+                if (mcmc_token_get_flag_arg_32(pr->request, &pr->tok, i, 
&tmp_int) == MCMC_OK) {
                     of->exptime = realtime(EXPTIME_TO_POSITIVE_TIME(tmp_int));
                     of->new_ttl = true;
+                } else {
+                    *errstr = "CLIENT_ERROR bad token in command line format";
+                    of->has_error = 1;
                 }
                 break;
             case 'R':
                 of->locked = 1;
-                if (!safe_strtol(&pr->request[pr->tok.tokens[i]+1], &tmp_int)) 
{
+                if (mcmc_token_get_flag_arg_32(pr->request, &pr->tok, i, 
&tmp_int) == MCMC_OK) {
+                    of->recache_time = 
realtime(EXPTIME_TO_POSITIVE_TIME(tmp_int));
+                } else {
                     *errstr = "CLIENT_ERROR bad token in command line format";
                     of->has_error = 1;
-                } else {
-                    of->recache_time = 
realtime(EXPTIME_TO_POSITIVE_TIME(tmp_int));
                 }
                 break;
             case 'l':
@@ -578,24 +569,28 @@
                 break;
             // mset-related.
             case 'F':
-                if (!safe_strtoflags(&pr->request[pr->tok.tokens[i]+1], 
&of->client_flags)) {
+#ifdef LARGE_CLIENT_FLAGS
+                if (mcmc_token_get_flag_arg_u64(pr->request, &pr->tok, i, 
&of->client_flags) != MCMC_OK) {
+#else
+                if (mcmc_token_get_flag_arg_u32(pr->request, &pr->tok, i, 
&of->client_flags) != MCMC_OK) {
+#endif
                     of->has_error = true;
                 }
                 break;
             case 'C': // mset, mdelete, marithmetic
-                if (!safe_strtoull(&pr->request[pr->tok.tokens[i]+1], 
&of->req_cas_id)) {
-                    *errstr = "CLIENT_ERROR bad token in command line format";
-                    of->has_error = true;
-                } else {
+                if (mcmc_token_get_flag_arg_u64(pr->request, &pr->tok, i, 
&of->req_cas_id) == MCMC_OK) {
                     of->has_cas = true;
+                } else {
+                    *errstr = "CLIENT_ERROR bad token in command line format";
+                    of->has_error = 1;
                 }
                 break;
             case 'E': // ms, md, ma
-                if (!safe_strtoull(&pr->request[pr->tok.tokens[i]+1], 
&of->cas_id_in)) {
-                    *errstr = "CLIENT_ERROR bad token in command line format";
-                    of->has_error = true;
-                } else {
+                if (mcmc_token_get_flag_arg_u64(pr->request, &pr->tok, i, 
&of->cas_id_in) == MCMC_OK) {
                     of->has_cas_in = true;
+                } else {
+                    *errstr = "CLIENT_ERROR bad token in command line format";
+                    of->has_error = 1;
                 }
                 break;
             case 'M': // mset and marithmetic mode switch
@@ -604,13 +599,13 @@
                 of->mode = pr->request[pr->tok.tokens[i]+1];
                 break;
             case 'J': // marithmetic initial value
-                if (!safe_strtoull(&pr->request[pr->tok.tokens[i]+1], 
&of->initial)) {
+                if (mcmc_token_get_flag_arg_u64(pr->request, &pr->tok, i, 
&of->initial) != MCMC_OK) {
                     *errstr = "CLIENT_ERROR invalid numeric initial value";
                     of->has_error = 1;
                 }
                 break;
             case 'D': // marithmetic delta value
-                if (!safe_strtoull(&pr->request[pr->tok.tokens[i]+1], 
&of->delta)) {
+                if (mcmc_token_get_flag_arg_u64(pr->request, &pr->tok, i, 
&of->delta) != MCMC_OK) {
                     *errstr = "CLIENT_ERROR invalid numeric delta value";
                     of->has_error = 1;
                 }
@@ -769,7 +764,7 @@
 
     // does cas value exist?
     if (handle_cas) {
-        if (!safe_strtoull(&pr->request[pr->tok.tokens[5]], &req_cas_id)) {
+        if (mcmc_token_get_u64(pr->request, &pr->tok, 5, &req_cas_id) != 
MCMC_OK) {
             pout_string(resp, "CLIENT_ERROR bad command line format");
             return NULL;
         }
@@ -871,7 +866,7 @@
         return;
     }
 
-    if (!safe_strtoull(&pr->request[pr->tok.tokens[2]], &delta)) {
+    if (mcmc_token_get_u64(pr->request, &pr->tok, 2, &delta) != MCMC_OK) {
         pout_string(resp, "CLIENT_ERROR invalid numeric delta argument");
         return;
     }
@@ -961,7 +956,7 @@
         return;
     }
 
-    if (!safe_strtol(&pr->request[pr->tok.tokens[2]], &exptime_int)) {
+    if (mcmc_token_get_32(pr->request, &pr->tok, 2, &exptime_int) != MCMC_OK) {
         pout_string(resp, "CLIENT_ERROR invalid exptime argument");
         return;
     }
@@ -1282,9 +1277,11 @@
     return;
 error:
     if (it) {
-        do_item_remove(it);
         if (of.locked) {
+            do_item_remove(it);
             item_unlock(hv);
+        } else {
+            item_remove(it);
         }
     }
     pout_errstring(resp, errstr);
@@ -1466,6 +1463,7 @@
           break;
         default:
           pout_errstring(resp, "SERVER_ERROR Unhandled storage type.");
+          item_remove(it);
           return;
 
     }
@@ -1517,9 +1515,8 @@
 
     return;
 error:
-    // Note: no errors possible after the item was successfully allocated.
-    // So we're just looking at dumping error codes and returning.
     pout_errstring(resp, errstr);
+    item_remove(it);
 }
 
 void process_mdelete_cmd(LIBEVENT_THREAD *t, mcp_parser_t *pr, mc_resp *resp) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/proto_proxy.c 
new/memcached-1.6.45/proto_proxy.c
--- old/memcached-1.6.44/proto_proxy.c  2026-03-05 00:05:05.000000000 +0100
+++ new/memcached-1.6.45/proto_proxy.c  2026-07-10 06:32:06.000000000 +0200
@@ -616,7 +616,8 @@
              * large multiget, if not we should just nuke the connection.
              */
             char *ptr = c->rcurr;
-            while (*ptr == ' ') { /* ignore leading whitespaces */
+            char *end = c->rcurr + c->rbytes-6;
+            while (*ptr == ' ' && ptr != end) { /* ignore leading whitespaces 
*/
                 ++ptr;
             }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/proto_text.c 
new/memcached-1.6.45/proto_text.c
--- old/memcached-1.6.44/proto_text.c   2026-07-07 06:16:48.000000000 +0200
+++ new/memcached-1.6.45/proto_text.c   2026-07-10 06:32:06.000000000 +0200
@@ -368,7 +368,8 @@
              * large multiget, if not we should just nuke the connection.
              */
             char *ptr = c->rcurr;
-            while (*ptr == ' ') { /* ignore leading whitespaces */
+            char *end = c->rcurr + c->rbytes-6;
+            while (*ptr == ' ' && ptr != end) { /* ignore leading whitespaces 
*/
                 ++ptr;
             }
 
@@ -931,6 +932,10 @@
             out_string(c, "CLIENT_ERROR bad command line format");
             return;
         }
+        if (level < 3 || level > 1800) {
+            out_string(c, "CLIENT_ERROR automove window too low or too high");
+            return;
+        }
 
         settings.slab_automove_window = level;
         settings.slab_automove_version++;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/proxy_lua.c 
new/memcached-1.6.45/proxy_lua.c
--- old/memcached-1.6.44/proxy_lua.c    2026-05-18 23:43:09.000000000 +0200
+++ new/memcached-1.6.45/proxy_lua.c    2026-07-10 06:32:06.000000000 +0200
@@ -750,7 +750,7 @@
         size_t remain = klen - (t1 - key);
         // must be at least one character inbetween the tags to hash.
         if (remain > 1) {
-            const char *t2 = memchr(t1, conf[1], remain);
+            const char *t2 = memchr(t1+1, conf[1], remain-1);
 
             if (t2) {
                 *newlen = t2 - t1 - 1;
@@ -940,6 +940,9 @@
         luaL_checktype(L, -1, LUA_TSTRING);
         size_t len = 0;
         const char *bepfx = lua_tolstring(L, -1, &len);
+        if (len > MAX_LABELLEN-1) {
+            len = MAX_LABELLEN-1;
+        }
         memcpy(p->beprefix, bepfx, len);
         p->beprefix[len+1] = '\0';
         lua_pop(L, 1); // pop beprefix string.
@@ -989,7 +992,7 @@
             }
 
             memcpy(p->key_filter_conf, conf, len);
-            p->key_filter_conf[len+1] = '\0';
+            p->key_filter_conf[len] = '\0';
         } else {
             proxy_lua_error(L, "hash filter requires 'filter_conf' string");
         }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/proxy_mutator.c 
new/memcached-1.6.45/proxy_mutator.c
--- old/memcached-1.6.44/proxy_mutator.c        2026-05-19 00:12:18.000000000 
+0200
+++ new/memcached-1.6.45/proxy_mutator.c        2026-07-10 06:32:06.000000000 
+0200
@@ -489,6 +489,8 @@
         case CMD_DELETE:
             p->src = "NOT_FOUND";
             break;
+        default:
+            return -1;
     }
     p->slen = strlen(p->src);
 
@@ -823,7 +825,7 @@
                     return -1;
                 }
                 int tlen = 0;
-                if (mcmc_token_has_flag_bit(&srs->tok, c->bit) == MCMC_OK) {
+                if (mcmc_token_has_flag_bit(&srq->pr.tok, c->bit) == MCMC_OK) {
                     const char *tok = mcmc_token_get_flag(srq->pr.request, 
&srq->pr.tok, c->f, &tlen);
                     p->slen = 1;
                     if (tok && tlen > 0) {
@@ -1118,6 +1120,9 @@
     if (size != mut->aused) {
         proxy_lua_error(L, "mutator failed to properly initialize, memory not 
filled correctly");
     }
+    if (scount == 0) {
+        proxy_lua_error(L, "mutator failed to initialize, no steps given");
+    }
     mut->scount = scount;
 
     return 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/proxy_network.c 
new/memcached-1.6.45/proxy_network.c
--- old/memcached-1.6.44/proxy_network.c        2026-07-07 06:16:48.000000000 
+0200
+++ new/memcached-1.6.45/proxy_network.c        2026-07-10 06:32:06.000000000 
+0200
@@ -601,6 +601,16 @@
                 }
             }
 
+            // TODO: mcmc's parser needs to use offsets into a string instead
+            // of pointers. Then all we do is swap the buffer pointer. In the
+            // meantime this is the smallest possible change to fix the issue
+            // of res:line() and similar returning the wrong buffer for
+            // pipelined requests, in cases where the result hasn't been
+            // reparsed before requesting the line.
+            ptrdiff_t rebase = r->buf - be->rbuf;
+            r->resp.value += rebase;
+            if (r->resp.rline) r->resp.rline += rebase;
+
             P_DEBUG("%s: r->status: %d, r->bread: %d, r->vlen: %lu\n", 
__func__, r->status, r->bread, r->resp.vlen);
             if (r->resp.vlen != r->resp.vlen_read) {
                 // shouldn't be possible to have excess in buffer
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/proxy_ratelim.c 
new/memcached-1.6.45/proxy_ratelim.c
--- old/memcached-1.6.44/proxy_ratelim.c        2025-10-22 06:59:10.000000000 
+0200
+++ new/memcached-1.6.45/proxy_ratelim.c        2026-07-10 06:32:06.000000000 
+0200
@@ -69,6 +69,12 @@
     lim->limit = _tbf_check(L, "limit");
     lim->fill_rate = _tbf_check(L, "fillrate");
     lim->tick_rate = _tbf_check(L, "tickrate");
+    if (lim->fill_rate == 0) {
+        lim->fill_rate = 1;
+    }
+    if (lim->tick_rate == 0) {
+        lim->tick_rate = 1;
+    }
 
     // seed the token bucket filter.
     lim->bucket = lim->limit;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/proxy_request.c 
new/memcached-1.6.45/proxy_request.c
--- old/memcached-1.6.44/proxy_request.c        2026-05-19 00:12:18.000000000 
+0200
+++ new/memcached-1.6.45/proxy_request.c        2026-07-10 06:32:06.000000000 
+0200
@@ -94,12 +94,12 @@
 
     memset(pr, 0, sizeof(mcp_parser_t)); // TODO: required?
     int ret = process_request(pr, rq->request, p - temp);
+    pr->vbuf = vbuf;
+    pr->vlen = vlen;
+
     if (ret != 0) {
-        // FIXME: does this leak the vbuf?
         return ret;
     }
-    pr->vbuf = vbuf;
-    pr->vlen = vlen;
     return 0;
 }
 
@@ -109,7 +109,7 @@
     char *p = (char *)pr->request + pr->reqlen - 2; // start at the \r
     assert(*p == '\r');
 
-    if (pr->reqlen + len + 2 > MCP_REQUEST_MAXLEN) {
+    if (pr->reqlen + len + 2 >= MCP_REQUEST_MAXLEN) {
         return -1;
     }
 
@@ -134,11 +134,11 @@
 
     memset(pr, 0, sizeof(mcp_parser_t)); // TODO: required?
     int ret = process_request(pr, rq->request, p - start);
+    pr->vbuf = vbuf;
+    pr->vlen = vlen;
     if (ret != 0) {
         return ret;
     }
-    pr->vbuf = vbuf;
-    pr->vlen = vlen;
 
     return 0;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/proxy_result.c 
new/memcached-1.6.45/proxy_result.c
--- old/memcached-1.6.44/proxy_result.c 2026-03-05 00:05:05.000000000 +0100
+++ new/memcached-1.6.45/proxy_result.c 2026-07-10 06:32:06.000000000 +0200
@@ -142,6 +142,10 @@
 
         free(r->buf);
         r->buf = NULL;
+        // Do some deeper cleaning: a manually closed res could still
+        // potentially be fed back into the system, causing errors.
+        r->blen = 0;
+        memset(&r->resp, 0, sizeof(r->resp));
     }
     r->tok.ntokens = 0;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/proxy_ring_hash.c 
new/memcached-1.6.45/proxy_ring_hash.c
--- old/memcached-1.6.44/proxy_ring_hash.c      2024-10-31 21:47:40.000000000 
+0100
+++ new/memcached-1.6.45/proxy_ring_hash.c      2026-07-10 06:32:06.000000000 
+0200
@@ -135,6 +135,7 @@
         size_t len = snprintf(hashstring, hashstring_size, "%s:%s-%d", 
parts[0], parts[1], k);
         kt->continuum[*cont].point = (unsigned int) XXH3_64bits(hashstring, 
len);
         kt->continuum[*cont].id = id;
+        (*cont)++;
     }
 
     free(hashstring);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/restart.c 
new/memcached-1.6.45/restart.c
--- old/memcached-1.6.44/restart.c      2026-03-05 00:05:05.000000000 +0100
+++ new/memcached-1.6.45/restart.c      2026-07-10 06:32:06.000000000 +0200
@@ -156,7 +156,8 @@
         // T for TAG, changing the callback we use.
         // K for key/value, to ship to the active callback.
         char *p = line;
-        while (*p != '\n') {
+        char *end = p + len;
+        while (*p != '\n' && p != end) {
             p++;
         }
         *p = '\0';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/slabs.c new/memcached-1.6.45/slabs.c
--- old/memcached-1.6.44/slabs.c        2026-05-19 00:12:18.000000000 +0200
+++ new/memcached-1.6.45/slabs.c        2026-07-10 06:32:06.000000000 +0200
@@ -760,9 +760,8 @@
         s_cls->slab_list[x] = s_cls->slab_list[x+1];
     }
 
-    // FIXME: it's nearly impossible for this to fail, and error handling here
-    // is gnarly since we'll have to just put the page back where we got it
-    // from.
+    // FIXME: it's nearly impossible for this to fail. If it does it can cause
+    // writing beyond the border, lost pages, etc.
     // For now we won't handle the error, and a subsequent commit should
     // remove the need to resize the slab list.
     do_grow_slab_list(did);
@@ -792,7 +791,7 @@
     int tries = MAX_NUMBER_OF_SLAB_CLASSES - POWER_SMALLEST + 1;
     for (; tries > 0; tries--) {
         cur++;
-        if (cur > MAX_NUMBER_OF_SLAB_CLASSES)
+        if (cur >= MAX_NUMBER_OF_SLAB_CLASSES)
             cur = POWER_SMALLEST;
         if (cur == did)
             continue;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/stats_prefix.c 
new/memcached-1.6.45/stats_prefix.c
--- old/memcached-1.6.44/stats_prefix.c 2024-10-31 21:47:40.000000000 +0100
+++ new/memcached-1.6.45/stats_prefix.c 2026-07-10 06:32:06.000000000 +0200
@@ -6,6 +6,8 @@
 #include <string.h>
 #include <assert.h>
 
+#define MAX_PREFIX_COUNT (1<<16)
+
 /* Hash table that uses the global hash function */
 static PREFIX_STATS *prefix_stats[PREFIX_HASH_SIZE];
 
@@ -60,6 +62,14 @@
             return pfs;
     }
 
+    // Hash table is a fixed size and there's no other way to limit memory
+    // usage. The lookup HT is a fixed size as well so this is also a
+    // performance problem. The system needs to be deprecated/removed or
+    // rewritten.
+    if (num_prefixes >= MAX_PREFIX_COUNT) {
+        return NULL;
+    }
+
     pfs = calloc(sizeof(PREFIX_STATS), 1);
     if (NULL == pfs) {
         perror("Can't allocate space for stats structure: calloc");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/storage.c 
new/memcached-1.6.45/storage.c
--- old/memcached-1.6.44/storage.c      2026-05-18 23:43:09.000000000 +0200
+++ new/memcached-1.6.45/storage.c      2026-07-10 06:32:06.000000000 +0200
@@ -204,7 +204,8 @@
                 // truncate the data response.
                 resp->iov[p->iovec_data].iov_len = 0;
                 // wipe the extlen iov... wish it was just a flat buffer.
-                resp->iov[p->iovec_data-1].iov_len = 0;
+                // this is unconditionally the second iov.
+                resp->iov[1].iov_len = 0;
                 resp->chunked_data_iov = 0;
             } else {
                 int i;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/t/getset.t 
new/memcached-1.6.45/t/getset.t
--- old/memcached-1.6.44/t/getset.t     2026-03-05 00:05:05.000000000 +0100
+++ new/memcached-1.6.45/t/getset.t     2026-07-10 06:32:06.000000000 +0200
@@ -1,7 +1,7 @@
 #!/usr/bin/env perl
 
 use strict;
-use Test::More tests => 37992;
+use Test::More tests => 37993;
 use FindBin qw($Bin);
 use lib "$Bin/lib";
 use MemcachedTest;
@@ -23,6 +23,18 @@
     is(scalar <$ns>, undef, "long ascii incr was not fine");
 };
 
+SKIP: {
+    skip "test flaky on old OS. has run on newer ones", 1;
+subtest 'oops all spaces' => sub {
+    my $ns = $server->new_sock;
+    $ns->autoflush(1);
+
+    my $spaces = ' ' x 14000;
+    syswrite($ns, $spaces);
+    is(scalar <$ns>, undef, "errored out");
+};
+};
+
 # set foo (and should get it)
 print $sock "set foo 0 0 6\r\nfooval\r\n";
 is(scalar <$sock>, "STORED\r\n", "stored foo");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/t/proxyunits.lua 
new/memcached-1.6.45/t/proxyunits.lua
--- old/memcached-1.6.44/t/proxyunits.lua       2026-05-18 23:43:09.000000000 
+0200
+++ new/memcached-1.6.45/t/proxyunits.lua       2026-07-10 06:32:06.000000000 
+0200
@@ -281,6 +281,8 @@
                         return res
                     end
                     return "ERROR unexpected line, got [" .. line .. "]\r\n"
+                elseif key == "/response/rbufline" then
+                    return "HD " .. res:line() .. "\r\n"
                 elseif key == "/response/blank" then
                     res:flag_blank("O")
                     return res
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/t/proxyunits.t 
new/memcached-1.6.45/t/proxyunits.t
--- old/memcached-1.6.44/t/proxyunits.t 2026-07-03 02:30:18.000000000 +0200
+++ new/memcached-1.6.45/t/proxyunits.t 2026-07-10 06:32:06.000000000 +0200
@@ -1079,6 +1079,19 @@
         );
     };
 
+    subtest 'response:line() under pipeline' => sub {
+        my $be = $mbe[0];
+        my $cmd = "mg /response/rbufline\r\n";
+        # pipeline two requests to the same backend
+        print $ps $cmd . $cmd;
+        is(scalar <$be>, $cmd, "be received request A");
+        is(scalar <$be>, $cmd, "be received request B");
+        print $be "HD Oa\r\nHD Ob\r\n";
+        is(scalar <$ps>, "HD Oa\r\n", "response A matches");
+        is(scalar <$ps>, "HD Ob\r\n", "response B matches");
+        check_version($ps);
+    };
+
     subtest 'response:flag_blank()' => sub {
         proxy_test(
             ps_send => "mg /response/blank f Ofoo t\r\n",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/t/slabs-mover.t 
new/memcached-1.6.45/t/slabs-mover.t
--- old/memcached-1.6.44/t/slabs-mover.t        2026-07-03 02:30:18.000000000 
+0200
+++ new/memcached-1.6.45/t/slabs-mover.t        2026-07-10 06:32:06.000000000 
+0200
@@ -15,6 +15,7 @@
 my $sock = $server->sock;
 
 {
+    subtest 'automove window' => \&test_automove_window;
     subtest 'syntax' => \&test_syntax;
     subtest 'fill and move pages' => \&test_fill;
     subtest 'chunked items' => \&test_chunked;
@@ -80,6 +81,29 @@
     return $sid;
 }
 
+# TODO: mc metric for automove runs so we can loop for that instead of blind
+# sleep.
+sub test_automove_window {
+    print $sock "slabs automove 1\r\n";
+    is(scalar <$sock>, "OK\r\n", "automover on");
+    print $sock "slabs automove window 0\r\n";
+    is(scalar <$sock>, "CLIENT_ERROR automove window too low or too high\r\n", 
"invalid window");
+
+    sleep 4;
+    print $sock "version\r\n";
+    like(scalar <$sock>, qr/VERSION/, "daemon still alive");
+
+    print $sock "slabs automove window 67108864\r\n";
+    is(scalar <$sock>, "CLIENT_ERROR automove window too low or too high\r\n", 
"invalid window");
+    sleep 4;
+
+    print $sock "version\r\n";
+    like(scalar <$sock>, qr/VERSION/, "daemon still alive");
+
+    print $sock "slabs automove 0\r\n";
+    is(scalar <$sock>, "OK\r\n", "automover off");
+}
+
 # NOTE: Can't validate reflocked items in an integration test since we leak
 # the memory and cannot de-ref an unlinked item.
 # TODO: test reflocked chunked items as well
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/tls.c new/memcached-1.6.45/tls.c
--- old/memcached-1.6.44/tls.c  2026-03-05 00:05:05.000000000 +0100
+++ new/memcached-1.6.45/tls.c  2026-07-10 06:32:06.000000000 +0200
@@ -86,6 +86,7 @@
                             NULL, c->sfd, strerror(errno));
                 } else {
                     char ssl_err[SSL_ERROR_MSG_SIZE];
+                    ssl_err[0] = '\0';
                     // OpenSSL internal error. One or more, but lets only care 
about
                     // the top error for now.
                     print_ssl_error(ssl_err, SSL_ERROR_MSG_SIZE);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/vendor/mcmc/mcmc.c 
new/memcached-1.6.45/vendor/mcmc/mcmc.c
--- old/memcached-1.6.44/vendor/mcmc/mcmc.c     2026-07-03 02:30:18.000000000 
+0200
+++ new/memcached-1.6.45/vendor/mcmc/mcmc.c     2026-07-10 06:32:06.000000000 
+0200
@@ -655,6 +655,21 @@
 
 #undef X
 
+#define X(n, p, c) \
+    int n(const char *l, mcmc_tokenizer_t *t, int idx, p *val) { \
+        int tlen = 0; \
+        const char *tok = _mcmc_token(l, t, idx, &tlen); \
+        if (tlen > 1) { \
+            return c(tok+1, tlen-1, val); \
+        } \
+        return MCMC_ERR; \
+    }
+
+X(mcmc_token_get_flag_arg_u32, uint32_t, mcmc_toktou32)
+X(mcmc_token_get_flag_arg_u64, uint64_t, mcmc_toktou64)
+X(mcmc_token_get_flag_arg_32, int32_t, mcmc_tokto32)
+X(mcmc_token_get_flag_arg_64, int64_t, mcmc_tokto64)
+
 int mcmc_token_has_flag(const char *l, mcmc_tokenizer_t *t, char flag) {
     if (flag < 65 || flag > 122) {
         return MCMC_ERR;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/vendor/mcmc/mcmc.h 
new/memcached-1.6.45/vendor/mcmc/mcmc.h
--- old/memcached-1.6.44/vendor/mcmc/mcmc.h     2026-03-05 00:05:05.000000000 
+0100
+++ new/memcached-1.6.45/vendor/mcmc/mcmc.h     2026-07-10 06:32:06.000000000 
+0200
@@ -154,6 +154,15 @@
 int mcmc_token_get_flag_64(const char *l, mcmc_tokenizer_t *t, char flag, 
int64_t *val);
 int mcmc_token_get_flag_idx(const char *l, mcmc_tokenizer_t *t, char flag);
 
+// WARNING: these assume a valid index fetched via get_flag_idx or a loop
+// iteration against ntokens.
+// If exists, convert the argument to the flag at position idx into the
+// requested numeric.
+int mcmc_token_get_flag_arg_u32(const char *l, mcmc_tokenizer_t *t, int idx, 
uint32_t *val);
+int mcmc_token_get_flag_arg_u64(const char *l, mcmc_tokenizer_t *t, int idx, 
uint64_t *val);
+int mcmc_token_get_flag_arg_32(const char *l, mcmc_tokenizer_t *t, int idx, 
int32_t *val);
+int mcmc_token_get_flag_arg_64(const char *l, mcmc_tokenizer_t *t, int idx, 
int64_t *val);
+
 #ifdef MCMC_TEST
 int mcmc_toktou32(const char *t, size_t len, uint32_t *out);
 int mcmc_toktou64(const char *t, size_t len, uint64_t *out);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/memcached-1.6.44/version.m4 
new/memcached-1.6.45/version.m4
--- old/memcached-1.6.44/version.m4     2026-07-07 06:24:04.000000000 +0200
+++ new/memcached-1.6.45/version.m4     2026-07-10 06:35:09.000000000 +0200
@@ -1 +1 @@
-m4_define([VERSION_NUMBER], [1.6.44])
+m4_define([VERSION_NUMBER], [1.6.45])

Reply via email to