[System]
You are a security engineer fixing a CVE. You are given the vulnerability description (symptom only) and the vulnerable source window. Author the MINIMAL fix as a unified diff. Follow these rules exactly:
1. Target ONLY the file named in the `# Vulnerable source (...)` header — do not invent or substitute file paths.
2. Modify ONLY code visible in the shown source window.
3. Change as few lines as possible; do not rewrite surrounding logic.
4. Output only the unified diff with no other text.
5. Prefer the minimal structural change: if an existing condition is missing a check, add it inline to that condition rather than inserting a new code block. If existing code is redundant or overcomplicated, replace it — do not add more code around it.
6. Edit the most specific method or class that directly handles the vulnerable operation — not a base class, interface, or Protocol definition.

[User]
# CVE
CVE-2019-5544: openslp parses attacker-controlled SLP network messages and uses a shared opaque buffer descriptor ring; the copy path for incoming option strings does not verify enough space remains before the end pointer, so a crafted peer message can overflow the heap allocation and write arbitrary data into adjacent memory.

# Vulnerable source (common/slp_buffer.c)
```c
/*-------------------------------------------------------------------------
 * Copyright (C) 2000 Caldera Systems, Inc
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 *    Neither the name of Caldera Systems nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CALDERA
 * SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *-------------------------------------------------------------------------*/

/** Functions for managing SLP message buffers.
 *
 * This file provides a higher level abstraction over malloc and free that
 * deals specifically with message buffer management.
 *
 * @file       slp_buffer.c
 * @author     Matthew Peterson, John Calcote (jcalcote@novell.com)
 * @attention  Please submit patches to http://www.openslp.org
 * @ingroup    CommonCodeBuffers
 */

#include "slp_buffer.h"
#include "slp_xmalloc.h"

/** Allocates an SLP message buffer.
 *
 * This routines must be called to initially allocate a SLPBuffer.
 *
 * @param[in] size The size of the buffer to be allocated.
 *
 * @return A newly allocated SLPBuffer, or NULL on memory allocation
 *    failure.
 *
 * @remarks An extra byte is allocated to store the terminating null for
 *    strings stored in the buffer. This extra byte is not counted in the
 *    buffer size.
 */
SLPBuffer SLPBufferAlloc(size_t size)
{
   SLPBuffer result;

   /* Allocate one extra byte for null terminating strings that
    * occupy the last field of the buffer.
    */
   result = xmalloc(sizeof(struct _SLPBuffer) + size + 1);
   if (result)
   {
      result->allocated = size;
      result->start = (uint8_t *) (result + 1);
      result->curpos = result->start;
      result->end = result->start + size;

#ifdef DEBUG
      memset(result->start, 0x4d, size + 1);
#endif
   }
   return result;
}

/** Resizes an SLP message buffer.
 *
 * This routine should be called to resize an existing memory buffer
 * that is too small.
 *
 * @param[in] buf    The buffer to be resized.
 * @param[in] size   The new size to reallocate for @p buf.
 *
 * @return A pointer to the newly allocated, or resized buffer is
 *    returned, or NULL on memory allocation failure.
 *
 * @sa See the @b remarks section for SLPBufferAlloc.
 */
SLPBuffer SLPBufferRealloc(SLPBuffer buf, size_t size)
{
   SLPBuffer result;
   if (buf)
   {
      if (buf->allocated >= size)
         result = buf;
      else
      {
         /* Allocate one extra byte for null terminating strings that
          * occupy the last field of the buffer.
          */
         result = xrealloc(buf, sizeof(struct _SLPBuffer) + size + 1);
         if (result)
             result->allocated = size;
      }
      if (result)
      {
         result->start = (uint8_t *)(result + 1);
         result->curpos = result->start;
         result->end = result->start + size;

#ifdef DEBUG
         memset(result->start, 0x4d, size + 1);
#endif
      }
   }
   else
      result = SLPBufferAlloc(size);
   return result;
}

/** Returns a duplicate buffer.
 *
 * Duplicate buffers must be freed by a call to SLPBufferFree.
 *
 * @param[in] buf The @c SLPBuffer to be duplicated.
 *
 * @return A newly allocated SLPBuffer that is a byte-for-byte copy
 *    of @p buf, or NULL on memory allocation failure.
 */
SLPBuffer SLPBufferDup(SLPBuffer buf)
{
   SLPBuffer dup = 0;
   if (buf && (dup = SLPBufferAlloc(buf->end - buf->start)) != 0)
      memcpy(dup->start, buf->start, buf->end - buf->start + 1);
   return dup;
}

/** Free an SLPBuffer.
 *
 * This routine releases the memory for a previously allocated
 * @c SLPBuffer object.
 *
 * @param[in] buf The SLPBuffer to be freed.
 */
void SLPBufferFree(SLPBuffer buf)
{
   xfree(buf);
}

/*=========================================================================*/
```

[Assistant]
diff --git a/common/slp_buffer.c b/common/slp_buffer.c
--- a/common/slp_buffer.c
+++ b/common/slp_buffer.c
@@ -30,6 +30,13 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *-------------------------------------------------------------------------*/

+/* Copyright (c) 2019 VMware, Inc.
+ * SPDX-License-Identifier: BSD-3-Clause
+ * This file is provided under the BSD-3-Clause license.
+ * See COPYING file for more details and other copyrights
+ * that may apply.
+ */
+
 /** Functions for managing SLP message buffers.
  *
  * This file provides a higher level abstraction over malloc and free that
@@ -153,4 +160,20 @@
    xfree(buf);
 }

+/** Report remaining free buffer size in bytes.
+ *
+ * Check if buffer is allocated and if so return bytes left in a
+ * @c SLPBuffer object.
+ *
+ * @param[in] buf The SLPBuffer to be freed.
+ */
+size_t
+RemainingBufferSpace(SLPBuffer buf)
+{
+   if (buf->allocated == 0) {
+      return 0;
+   }
+   return buf->end - buf->curpos;
+}
+
 /*=========================================================================*/


[System]
You are a security engineer fixing a CVE. You are given the vulnerability description (symptom only) and the vulnerable source window. Author the MINIMAL fix as a unified diff. Follow these rules exactly:
1. Target ONLY the file named in the `# Vulnerable source (...)` header — do not invent or substitute file paths.
2. Modify ONLY code visible in the shown source window.
3. Change as few lines as possible; do not rewrite surrounding logic.
4. Output only the unified diff with no other text.
5. Prefer the minimal structural change: if an existing condition is missing a check, add it inline to that condition rather than inserting a new code block. If existing code is redundant or overcomplicated, replace it — do not add more code around it.
6. Edit the most specific method or class that directly handles the vulnerable operation — not a base class, interface, or Protocol definition.

[User]
# CVE
CVE-2025-55763: civetweb constructs a redirect URL by appending a query string to an internal buffer using unchecked concatenation, allowing a crafted HTTP request with an overlong query to overflow the buffer and corrupt adjacent memory.

# Vulnerable source (src/civetweb.c)
```c
		so->lsa.sin.sin_port = htons((uint16_t)port);
		*ip_version = 4;

#if defined(USE_IPV6)
	} else if (sscanf(vec->ptr, "[%49[^]]]:%u%n", buf, &port, &len) == 2
	           && ((size_t)len <= vec->len)
	           && mg_inet_pton(
	                  AF_INET6, buf, &so->lsa.sin6, sizeof(so->lsa.sin6), 0)) {
		/* IPv6 address, examples: see above */
		/* so->lsa.sin6.sin6_family = AF_INET6; already set by mg_inet_pton
		 */
		so->lsa.sin6.sin6_port = htons((uint16_t)port);
		*ip_version = 6;
#endif

	} else if ((vec->ptr[0] == '+')
	           && (sscanf(vec->ptr + 1, "%u%n", &port, &len)
	               == 1)) { // NOLINT(cert-err34-c) 'sscanf' used to convert a
		                    // string to an integer value, but function will not
		                    // report conversion errors; consider using 'strtol'
		                    // instead

		/* Port is specified with a +, bind to IPv6 and IPv4, INADDR_ANY */
		/* Add 1 to len for the + character we skipped before */
		len++;

#if defined(USE_IPV6)
		/* Set socket family to IPv6, do not use IPV6_V6ONLY */
		so->lsa.sin6.sin6_family = AF_INET6;
		so->lsa.sin6.sin6_port = htons((uint16_t)port);
		*ip_version = 4 + 6;
#else
		/* Bind to IPv4 only, since IPv6 is not built in. */
		so->lsa.sin.sin_port = htons((uint16_t)port);
		*ip_version = 4;
#endif

	} else if (is_valid_port(portUL = strtoul(vec->ptr, &endptr, 0))
	           && (vec->ptr != endptr)) {
		len = (int)(endptr - vec->ptr);
		port = (uint16_t)portUL;
		/* If only port is specified, bind to IPv4, INADDR_ANY */
		so->lsa.sin.sin_port = htons((uint16_t)port);
		*ip_version = 4;

	} else if ((cb = strchr(vec->ptr, ':')) != NULL) {
		/* String could be a hostname. This check algorithm
		 * will only work for RFC 952 compliant hostnames,
		 * starting with a letter, containing only letters,
		 * digits and hyphen ('-'). Newer specs may allow
		 * more, but this is not guaranteed here, since it
		 * may interfere with rules for port option lists. */

		/* According to RFC 1035, hostnames are restricted to 255 characters
		 * in total (63 between two dots). */
		char hostname[256];
		size_t hostnlen = (size_t)(cb - vec->ptr);

		if ((hostnlen >= vec->len) || (hostnlen >= sizeof(hostname))) {
			/* This would be invalid in any case */
			*ip_version = 0;
			return 0;
		}

		mg_strlcpy(hostname, vec->ptr, hostnlen + 1);

		if (mg_inet_pton(
		        AF_INET, hostname, &so->lsa.sin, sizeof(so->lsa.sin), 1)) {
			if (sscanf(cb + 1, "%u%n", &port, &len)
			    == 1) { // NOLINT(cert-err34-c) 'sscanf' used to convert a
				        // string to an integer value, but function will not
				        // report conversion errors; consider using 'strtol'
				        // instead
				*ip_version = 4;
				so->lsa.sin.sin_port = htons((uint16_t)port);
				len += (int)(hostnlen + 1);
			} else {
				len = 0;
			}
#if defined(USE_IPV6)
		} else if (mg_inet_pton(AF_INET6,
		                        hostname,
		                        &so->lsa.sin6,
		                        sizeof(so->lsa.sin6),
		                        1)) {
			if (sscanf(cb + 1, "%u%n", &port, &len) == 1) {
				*ip_version = 6;
				so->lsa.sin6.sin6_port = htons((uint16_t)port);
				len += (int)(hostnlen + 1);
			} else {
				len = 0;
			}
#endif
		} else {
			len = 0;
		}

#if defined(USE_X_DOM_SOCKET)

	} else if (vec->ptr[0] == 'x') {
		/* unix (linux) domain socket */
		if (vec->len < sizeof(so->lsa.sun.sun_path)) {
			len = vec->len;
			so->lsa.sun.sun_family = AF_UNIX;
			memset(so->lsa.sun.sun_path, 0, sizeof(so->lsa.sun.sun_path));
```

[Assistant]
diff --git a/src/civetweb.c b/src/civetweb.c
index bbc9aa8be..e969c939f 100644
--- a/src/civetweb.c
+++ b/src/civetweb.c
@@ -15579,7 +15579,6 @@ handle_request(struct mg_connection *conn)
 	/* 12. Directory uris should end with a slash */
 	if (file.stat.is_directory && ((uri_len = (int)strlen(ri->local_uri)) > 0)
 	    && (ri->local_uri[uri_len - 1] != '/')) {
-
 		/* Path + server root */
 		size_t buflen = UTF8_PATH_MAX * 2 + 2;
 		char *new_path;
@@ -15592,12 +15591,26 @@ handle_request(struct mg_connection *conn)
 			mg_send_http_error(conn, 500, "out or memory");
 		} else {
 			mg_get_request_link(conn, new_path, buflen - 1);
-			strcat(new_path, "/");
+
+			size_t len = strlen(new_path);
+			if (len + 1 < buflen) {
+				new_path[len] = '/';
+				new_path[len + 1] = '\0';
+				len += 1;
+			}
+
 			if (ri->query_string) {
-				/* Append ? and query string */
-				strcat(new_path, "?");
-				strcat(new_path, ri->query_string);
+				if (len + 1 < buflen) {
+					new_path[len] = '?';
+					new_path[len + 1] = '\0';
+					len += 1;
+				}
+
+				/* Append with size of space left for query string + null terminator */
+				size_t max_append = buflen - len - 1;
+				strncat(new_path, ri->query_string, max_append);
 			}
+
 			mg_send_http_redirect(conn, new_path, 301);
 			mg_free(new_path);
 		}