[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 one or more SEARCH/REPLACE blocks. Follow these rules exactly:
1. Each block is:
<<<<<<< SEARCH
<exact lines copied verbatim from the shown source window>
=======
<the replacement lines>
>>>>>>> REPLACE
2. The SEARCH text MUST appear verbatim in the shown source window — copy it exactly, including whitespace; do not invent or paraphrase it.
3. Change as few lines as possible; keep the SEARCH span tight around the edit.
4. Modify ONLY code visible in the shown source window.
5. Output only the SEARCH/REPLACE block(s) with no other text.
6. Prefer folding a new bound or check into an existing condition over adding a separate guard, when the upstream fix does so.

[User]
# CVE
CVE-2026-40164: An attacker can craft a JSON object whose keys all map to the same hash bucket, causing worst-case O(n^2) collision-chain traversal during parsing and evaluation. Processing a sufficiently large crafted object causes excessive CPU consumption and service unavailability.

# Vulnerable source (src/jv.c)
```c
/*
 * Portions Copyright (c) 2016 Kungliga Tekniska Högskolan
 * (Royal Institute of Technology, Stockholm, Sweden).
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 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
 * COPYRIGHT HOLDER 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.
 *
 */

#include <stdint.h>
#include <stddef.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <limits.h>
#include <math.h>
#include <float.h>

#include "jv_alloc.h"
#include "jv.h"
#include "jv_unicode.h"
#include "util.h"

/*
 * Internal refcounting helpers
 */

typedef struct jv_refcnt {
  int count;
} jv_refcnt;

static const jv_refcnt JV_REFCNT_INIT = {1};

static void jvp_refcnt_inc(jv_refcnt* c) {
  c->count++;
}

static int jvp_refcnt_dec(jv_refcnt* c) {
  c->count--;
  return c->count == 0;
}

static int jvp_refcnt_unshared(jv_refcnt* c) {
  assert(c->count > 0);
  return c->count == 1;
}

#define KIND_MASK   0xF
#define PFLAGS_MASK 0xF0
#define PTYPE_MASK  0x70

typedef enum {
  JVP_PAYLOAD_NONE = 0,
  JVP_PAYLOAD_ALLOCATED = 0x80,
} payload_flags;

#define JVP_MAKE_PFLAGS(ptype, allocated) ((((ptype) << 4) & PTYPE_MASK) | ((allocated) ? JVP_PAYLOAD_ALLOCATED : 0))
#define JVP_MAKE_FLAGS(kind, pflags) ((kind & KIND_MASK) | (pflags & PFLAGS_MASK))

#define JVP_FLAGS(j)  ((j).kind_flags)
#define JVP_KIND(j)   (JVP_FLAGS(j) & KIND_MASK)

#define JVP_HAS_FLAGS(j, flags) (JVP_FLAGS(j) == flags)
#define JVP_HAS_KIND(j, kind)   (JVP_KIND(j) == kind)

#define JVP_IS_ALLOCATED(j) (j.kind_flags & JVP_PAYLOAD_ALLOCATED)

#define JVP_FLAGS_NULL      JVP_MAKE_FLAGS(JV_KIND_NULL, JVP_PAYLOAD_NONE)
#define JVP_FLAGS_INVALID   JVP_MAKE_FLAGS(JV_KIND_INVALID, JVP_PAYLOAD_NONE)
#define JVP_FLAGS_FALSE     JVP_MAKE_FLAGS(JV_KIND_FALSE, JVP_PAYLOAD_NONE)
#define JVP_FLAGS_TRUE      JVP_MAKE_FLAGS(JV_KIND_TRUE, JVP_PAYLOAD_NONE)

jv_kind jv_get_kind(jv x) {
  return JVP_KIND(x);
}

const char* jv_kind_name(jv_kind k) {
  switch (k) {
  case JV_KIND_INVALID: return "<invalid>";
  case JV_KIND_NULL:    return "null";
  case JV_KIND_FALSE:   return "boolean";
  case JV_KIND_TRUE:    return "boolean";
  case JV_KIND_NUMBER:  return "number";
  case JV_KIND_STRING:  return "string";
  case JV_KIND_ARRAY:   return "array";
  case JV_KIND_OBJECT:  return "object";
  }
  assert(0 && "invalid kind");
  return "<unknown>";
}

const jv JV_NULL = {JVP_FLAGS_NULL, 0, 0, 0, {0}};
const jv JV_INVALID = {JVP_FLAGS_INVALID, 0, 0, 0, {0}};
const jv JV_FALSE = {JVP_FLAGS_FALSE, 0, 0, 0, {0}};
const jv JV_TRUE = {JVP_FLAGS_TRUE, 0, 0, 0, {0}};

jv jv_true(void) {
  return JV_TRUE;
}

jv jv_false(void) {
  return JV_FALSE;
}

jv jv_null(void) {
  return JV_NULL;
}

jv jv_bool(int x) {
  return x ? JV_TRUE : JV_FALSE;
}

/*
 * Invalid objects, with optional error messages
 */

#define JVP_FLAGS_INVALID_MSG   JVP_MAKE_FLAGS(JV_KIND_INVALID, JVP_PAYLOAD_ALLOCATED)

typedef struct {
  jv_refcnt refcnt;
  jv errmsg;
} jvp_invalid;

jv jv_invalid_with_msg(jv err) {
  jvp_invalid* i = jv_mem_alloc(sizeof(jvp_invalid));
  i->refcnt = JV_REFCNT_INIT;
  i->errmsg = err;

  jv x = {JVP_FLAGS_INVALID_MSG, 0, 0, 0, {&i->refcnt}};
  return x;
}

jv jv_invalid(void) {
  return JV_INVALID;
}

jv jv_invalid_get_msg(jv inv) {
  assert(JVP_HAS_KIND(inv, JV_KIND_INVALID));

  jv x;
  if (JVP_HAS_FLAGS(inv, JVP_FLAGS_INVALID_MSG)) {
    x = jv_copy(((jvp_invalid*)inv.u.ptr)->errmsg);
  }
  else {
    x = jv_null();
  }

  jv_free(inv);
  return x;
}

int jv_invalid_has_msg(jv inv) {
  assert(JVP_HAS_KIND(inv, JV_KIND_INVALID));
  int r = JVP_HAS_FLAGS(inv, JVP_FLAGS_INVALID_MSG);
  jv_free(inv);
  return r;
}

static void jvp_invalid_free(jv x) {
  assert(JVP_HAS_KIND(x, JV_KIND_INVALID));
  if (JVP_HAS_FLAGS(x, JVP_FLAGS_INVALID_MSG) && jvp_refcnt_dec(x.u.ptr)) {
    jv_free(((jvp_invalid*)x.u.ptr)->errmsg);
    jv_mem_free(x.u.ptr);
  }
}

/*
 * Numbers
 */

#ifdef USE_DECNUM
#include "jv_dtoa.h"
#include "jv_dtoa_tsd.h"

// we will manage the space for the struct
#define DECNUMDIGITS 1
#include "decNumber/decNumber.h"

enum {
  JVP_NUMBER_NATIVE = 0,
  JVP_NUMBER_DECIMAL = 1
};

#define JVP_FLAGS_NUMBER_NATIVE       JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_NATIVE, 0))
#define JVP_FLAGS_NUMBER_LITERAL      JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_DECIMAL, 1))

// the decimal precision of binary double
#define DEC_NUMBER_DOUBLE_PRECISION   (17)
#define DEC_NUMBER_STRING_GUARD       (14)
#define DEC_NUMBER_DOUBLE_EXTRA_UNITS ((DEC_NUMBER_DOUBLE_PRECISION - DECNUMDIGITS + DECDPUN - 1)/DECDPUN)

#include "jv_thread.h"
#ifdef WIN32
#ifndef __MINGW32__
/* Copied from Heimdal: thread-specific keys; see lib/base/dll.c in Heimdal */

/*
 * This is an implementation of thread-specific storage with
 * destructors.  WIN32 doesn't quite have this.  Instead it has
 * DllMain(), an entry point in every DLL that gets called to notify the
 * DLL of thread/process "attach"/"detach" events.
 *
 * We use __thread (or __declspec(thread)) for the thread-local itself
 * and DllMain() DLL_THREAD_DETACH events to drive destruction of
 * thread-local values.
 *
 * When building in maintainer mode on non-Windows pthread systems this
 * uses a single pthread key instead to implement multiple keys.  This
 * keeps the code from rotting when modified by non-Windows developers.
 */

/* Logical array of keys that grows lock-lessly */
typedef struct tls_keys tls_keys;
struct tls_keys {
    void (**keys_dtors)(void *);    /* array of destructors         */
    size_t keys_start_idx;          /* index of first destructor    */
    size_t keys_num;
    tls_keys *keys_next;
};

/*
 * Well, not quite locklessly.  We need synchronization primitives to do
 * this locklessly.  An atomic CAS will do.
 */
static pthread_mutex_t tls_key_defs_lock = PTHREAD_MUTEX_INITIALIZER;
static tls_keys *tls_key_defs;

/* Logical array of values (per-thread; no locking needed here) */
struct tls_values {
    void **values; /* realloc()ed */
    size_t values_num;
};

#ifdef _MSC_VER
static __declspec(thread) struct nomem_handler nomem_handler;
#else
static __thread struct tls_values values;
#endif

#define DEAD_KEY ((void *)8)

static void
w32_service_thread_detach(void *unused)
{
    tls_keys *key_defs;
    void (*dtor)(void*);
    size_t i;

    pthread_mutex_lock(&tls_key_defs_lock);
    key_defs = tls_key_defs;
    pthread_mutex_unlock(&tls_key_defs_lock);

    if (key_defs == NULL)
        return;

    for (i = 0; i < values.values_num; i++) {
        assert(i >= key_defs->keys_start_idx);
        if (i >= key_defs->keys_start_idx + key_defs->keys_num) {
            pthread_mutex_lock(&tls_key_defs_lock);
            key_defs = key_defs->keys_next;
            pthread_mutex_unlock(&tls_key_defs_lock);

            assert(key_defs != NULL);
            assert(i >= key_defs->keys_start_idx);
            assert(i < key_defs->keys_start_idx + key_defs->keys_num);
        }
        dtor = key_defs->keys_dtors[i - key_defs->keys_start_idx];
        if (values.values[i] != NULL && dtor != NULL && dtor != DEAD_KEY)
            dtor(values.values[i]);
        values.values[i] = NULL;
    }
}

extern void jv_tsd_dtoa_ctx_init();
extern void jv_tsd_dtoa_ctx_fini();
void jv_tsd_dec_ctx_fini();
void jv_tsd_dec_ctx_init();

BOOL WINAPI DllMain(HINSTANCE hinstDLL,
                    DWORD fdwReason,
                    LPVOID lpvReserved)
{
    switch (fdwReason) {
    case DLL_PROCESS_ATTACH:
	/*create_pt_key();*/
	jv_tsd_dtoa_ctx_init();
	jv_tsd_dec_ctx_init();
	return TRUE;
    case DLL_PROCESS_DETACH:
	jv_tsd_dtoa_ctx_fini();
	jv_tsd_dec_ctx_fini();
	return TRUE;
    case DLL_THREAD_ATTACH: return 0;
    case DLL_THREAD_DETACH:
        w32_service_thread_detach(NULL);
        return TRUE;
    default: return TRUE;
    }
}

int
pthread_key_create(pthread_key_t *key, void (*dtor)(void *))
{
    tls_keys *key_defs, *new_key_defs;
    size_t i, k;
    int ret = ENOMEM;

    pthread_mutex_lock(&tls_key_defs_lock);
    if (tls_key_defs == NULL) {
        /* First key */
        new_key_defs = calloc(1, sizeof(*new_key_defs));
        if (new_key_defs == NULL) {
            pthread_mutex_unlock(&tls_key_defs_lock);
            return ENOMEM;
        }
        new_key_defs->keys_num = 8;
        new_key_defs->keys_dtors = calloc(new_key_defs->keys_num,
                                          sizeof(*new_key_defs->keys_dtors));
        if (new_key_defs->keys_dtors == NULL) {
            pthread_mutex_unlock(&tls_key_defs_lock);
            free(new_key_defs);
            return ENOMEM;
        }
        tls_key_defs = new_key_defs;
        new_key_defs->keys_dtors[0] = dtor;
        for (i = 1; i < new_key_defs->keys_num; i++)
            new_key_defs->keys_dtors[i] = NULL;
        pthread_mutex_unlock(&tls_key_defs_lock);
        return 0;
    }

    for (key_defs = tls_key_defs;
         key_defs != NULL;
         key_defs = key_defs->keys_next) {
        k = key_defs->keys_start_idx;
        for (i = 0; i < key_defs->keys_num; i++, k++) {
            if (key_defs->keys_dtors[i] == NULL) {
                /* Found free slot; use it */
                key_defs->keys_dtors[i] = dtor;
                *key = k;
                pthread_mutex_unlock(&tls_key_defs_lock);
                return 0;
            }
        }
        if (key_defs->keys_next != NULL)
            continue;

        /* Grow the registration array */
        /* XXX DRY */
        new_key_defs = calloc(1, sizeof(*new_key_defs));
        if (new_key_defs == NULL)
            break;

        new_key_defs->keys_dtors =
            calloc(key_defs->keys_num + key_defs->keys_num / 2,
                   sizeof(*new_key_defs->keys_dtors));
        if (new_key_defs->keys_dtors == NULL) {
            free(new_key_defs);
            break;
        }
        new_key_defs->keys_start_idx = key_defs->keys_start_idx +
            key_defs->keys_num;
        new_key_defs->keys_num = key_defs->keys_num + key_defs->keys_num / 2;
        new_key_defs->keys_dtors[i] = dtor;
        for (i = 1; i < new_key_defs->keys_num; i++)
            new_key_defs->keys_dtors[i] = NULL;
        key_defs->keys_next = new_key_defs;
        ret = 0;
        break;
    }
    pthread_mutex_unlock(&tls_key_defs_lock);
    return ret;
}

static void
key_lookup(pthread_key_t key, tls_keys **kd,
           size_t *dtor_idx, void (**dtor)(void *))
{
    tls_keys *key_defs;

    if (kd != NULL)
        *kd = NULL;
    if (dtor_idx != NULL)
        *dtor_idx = 0;
    if (dtor != NULL)
        *dtor = NULL;

    pthread_mutex_lock(&tls_key_defs_lock);
    key_defs = tls_key_defs;
    pthread_mutex_unlock(&tls_key_defs_lock);

    while (key_defs != NULL) {
        if (key >= key_defs->keys_start_idx &&
            key < key_defs->keys_start_idx + key_defs->keys_num) {
            if (kd != NULL)
                *kd = key_defs;
            if (dtor_idx != NULL)
                *dtor_idx = key - key_defs->keys_start_idx;
            if (dtor != NULL)
                *dtor = key_defs->keys_dtors[key - key_defs->keys_start_idx];
            return;
        }

        pthread_mutex_lock(&tls_key_defs_lock);
        key_defs = key_defs->keys_next;
        pthread_mutex_unlock(&tls_key_defs_lock);
        assert(key_defs != NULL);
        assert(key >= key_defs->keys_start_idx);
    }
}

int
pthread_setspecific(pthread_key_t key, void *value)
{
    void **new_values;
    size_t new_num;
    void (*dtor)(void *);
    size_t i;

    key_lookup(key, NULL, NULL, &dtor);
    if (dtor == NULL)
        return EINVAL;

    if (key >= values.values_num) {
        if (values.values_num == 0) {
            values.values = NULL;
            new_num = 8;
        } else {
            new_num = (values.values_num + values.values_num / 2);
        }
        new_values = realloc(values.values, sizeof(void *) * new_num);
        if (new_values == NULL)
            return ENOMEM;
        for (i = values.values_num; i < new_num; i++)
            new_values[i] = NULL;
        values.values = new_values;
        values.values_num = new_num;
    }

    assert(key < values.values_num);

    if (values.values[key] != NULL && dtor != NULL && dtor != DEAD_KEY)
        dtor(values.values[key]);

    values.values[key] = value;
    return 0;
}

void *
pthread_getspecific(pthread_key_t key)
{
    if (key >= values.values_num)
        return NULL;
    return values.values[key];
}
#else
#include <pthread.h>
#endif
#else
#include <pthread.h>
#endif

static pthread_key_t dec_ctx_key;
static pthread_once_t dec_ctx_once = PTHREAD_ONCE_INIT;

#define DEC_CONTEXT() tsd_dec_ctx_get(&dec_ctx_key)

// atexit finalizer to clean up the tsd dec contexts if main() exits
// without having called pthread_exit()
void jv_tsd_dec_ctx_fini(void) {
  jv_mem_free(pthread_getspecific(dec_ctx_key));
  pthread_setspecific(dec_ctx_key, NULL);
}

void jv_tsd_dec_ctx_init(void) {
  if (pthread_key_create(&dec_ctx_key, jv_mem_free) != 0) {
    fprintf(stderr, "error: cannot create thread specific key");
    abort();
  }
  atexit(jv_tsd_dec_ctx_fini);
}

static decContext* tsd_dec_ctx_get(pthread_key_t *key) {
  pthread_once(&dec_ctx_once, jv_tsd_dec_ctx_init); // cannot fail
  decContext *ctx = (decContext*)pthread_getspecific(*key);
  if (ctx) {
    return ctx;
  }

  ctx = malloc(sizeof(decContext));
  if (ctx) {
    if (key == &dec_ctx_key)
    {
      decContextDefault(ctx, DEC_INIT_BASE);
      // make sure (Int)D2U(rhs->exponent-lhs->exponent) does not overflow
      ctx->digits = MIN(DEC_MAX_DIGITS,
          INT32_MAX - (DECDPUN - 1) - (ctx->emax - ctx->emin - 1));
      ctx->traps = 0; /*no errors*/
    }
    if (pthread_setspecific(*key, ctx) != 0) {
      fprintf(stderr, "error: cannot store thread specific data");
      abort();
    }
  }
  return ctx;
}

typedef struct {
  jv_refcnt refcnt;
  double num_double;
  char * literal_data;
  decNumber num_decimal; // must be the last field in the structure for memory management
} jvp_literal_number;

typedef struct {
  decNumber number;
  decNumberUnit units[DEC_NUMBER_DOUBLE_EXTRA_UNITS];
} decNumberDoublePrecision;

static inline int jvp_number_is_literal(jv n) {
  assert(JVP_HAS_KIND(n, JV_KIND_NUMBER));
  return JVP_HAS_FLAGS(n, JVP_FLAGS_NUMBER_LITERAL);
}

static jvp_literal_number* jvp_literal_number_ptr(jv j) {
  assert(JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL));
  return (jvp_literal_number*)j.u.ptr;
}

static decNumber* jvp_dec_number_ptr(jv j) {
  assert(JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL));
  return &(((jvp_literal_number*)j.u.ptr)->num_decimal);
}

static jvp_literal_number* jvp_literal_number_alloc(unsigned literal_length) {
  /* The number of units needed is ceil(DECNUMDIGITS/DECDPUN)         */
  int units = ((literal_length+DECDPUN-1)/DECDPUN);

  jvp_literal_number* n = jv_mem_alloc(
    sizeof(jvp_literal_number)
    + sizeof(decNumberUnit) * units
  );

  n->refcnt = JV_REFCNT_INIT;
  n->num_double = NAN;
  n->literal_data = NULL;
  return n;
}

static jv jvp_literal_number_new(const char * literal) {
  jvp_literal_number* n = jvp_literal_number_alloc(strlen(literal));

  decContext *ctx = DEC_CONTEXT();
  decContextClearStatus(ctx, DEC_Conversion_syntax);
  decNumberFromString(&n->num_decimal, literal, ctx);

  if (ctx->status & DEC_Conversion_syntax) {
    jv_mem_free(n);
    return JV_INVALID;
  }
  if (decNumberIsNaN(&n->num_decimal)) {
    // Reject NaN with payload.
    if (n->num_decimal.digits > 1 || *n->num_decimal.lsu != 0) {
      jv_mem_free(n);
      return JV_INVALID;
    }
    jv_mem_free(n);
    return jv_number(NAN);
  }

  jv r = {JVP_FLAGS_NUMBER_LITERAL, 0, 0, 0, {&n->refcnt}};
  return r;
}

static double jvp_literal_number_to_double(jv j) {
  assert(JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL));
  decContext dblCtx;

  // init as decimal64 but change digits to allow conversion to binary64 (double)
  decContextDefault(&dblCtx, DEC_INIT_DECIMAL64);
  dblCtx.digits = DEC_NUMBER_DOUBLE_PRECISION;

  decNumber *p_dec_number = jvp_dec_number_ptr(j);
  decNumberDoublePrecision dec_double;
  char literal[DEC_NUMBER_DOUBLE_PRECISION + DEC_NUMBER_STRING_GUARD + 1];

  // reduce the number to the shortest possible form
  // that fits into the 64 bit floating point representation
  decNumberReduce(&dec_double.number, p_dec_number, &dblCtx);

  decNumberToString(&dec_double.number, literal);

  char *end;
  return jvp_strtod(tsd_dtoa_context_get(), literal, &end);
}

static const char* jvp_literal_number_literal(jv n) {
  assert(JVP_HAS_FLAGS(n, JVP_FLAGS_NUMBER_LITERAL));
  decNumber *pdec = jvp_dec_number_ptr(n);
  jvp_literal_number* plit = jvp_literal_number_ptr(n);

  if (decNumberIsNaN(pdec)) {
    return "null";
  }

  if (decNumberIsInfinite(pdec)) {
    // We cannot preserve the literal data of numbers outside the limited
    // range of exponent. Since `decNumberToString` returns "Infinity"
    // (or "-Infinity"), and to reduce stack allocations as possible, we
    // normalize infinities in the callers instead of printing the maximum
    // (or minimum) double here.
    return NULL;
  }

  if (plit->literal_data == NULL) {
    int len = jvp_dec_number_ptr(n)->digits + 15 /* 14 + NUL */;
    plit->literal_data = jv_mem_alloc(len);

    // Preserve the actual precision as we have parsed it
    // don't do decNumberTrim(pdec);

    decNumberToString(pdec, plit->literal_data);
  }

  return plit->literal_data;
}

int jv_number_has_literal(jv n) {
  assert(JVP_HAS_KIND(n, JV_KIND_NUMBER));
  return JVP_HAS_FLAGS(n, JVP_FLAGS_NUMBER_LITERAL);
}

const char* jv_number_get_literal(jv n) {
  assert(JVP_HAS_KIND(n, JV_KIND_NUMBER));

  if (JVP_HAS_FLAGS(n, JVP_FLAGS_NUMBER_LITERAL)) {
    return jvp_literal_number_literal(n);
  } else {
    return NULL;
  }
}

jv jv_number_with_literal(const char * literal) {
  return jvp_literal_number_new(literal);
}
#endif /* USE_DECNUM */

jv jv_number(double x) {
  jv j = {
#ifdef USE_DECNUM
    JVP_FLAGS_NUMBER_NATIVE,
#else
    JV_KIND_NUMBER,
#endif
    0, 0, 0, {.number = x}
  };
  return j;
}

static void jvp_number_free(jv j) {
  assert(JVP_HAS_KIND(j, JV_KIND_NUMBER));
#ifdef USE_DECNUM
  if (JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL) && jvp_refcnt_dec(j.u.ptr)) {
    jvp_literal_number* n = jvp_literal_number_ptr(j);
    if (n->literal_data) {
      jv_mem_free(n->literal_data);
    }
    jv_mem_free(n);
  }
#endif
}

double jv_number_value(jv j) {
  assert(JVP_HAS_KIND(j, JV_KIND_NUMBER));
#ifdef USE_DECNUM
  if (JVP_HAS_FLAGS(j, JVP_FLAGS_NUMBER_LITERAL)) {
    jvp_literal_number* n = jvp_literal_number_ptr(j);

    if (isnan(n->num_double)) {
      n->num_double = jvp_literal_number_to_double(j);
    }

    return n->num_double;
  }
#endif
  return j.u.number;
}

int jv_is_integer(jv j){
  if (!JVP_HAS_KIND(j, JV_KIND_NUMBER)){
    return 0;
  }

  double x = jv_number_value(j);

  double ipart;
  double fpart = modf(x, &ipart);

  return fabs(fpart) < DBL_EPSILON;
}

int jvp_number_is_nan(jv n) {
  assert(JVP_HAS_KIND(n, JV_KIND_NUMBER));

#ifdef USE_DECNUM
  if (JVP_HAS_FLAGS(n, JVP_FLAGS_NUMBER_LITERAL)) {
    decNumber *pdec = jvp_dec_number_ptr(n);
    return decNumberIsNaN(pdec);
  }
#endif
  return isnan(n.u.number);
}

jv jv_number_abs(jv n) {
  assert(JVP_HAS_KIND(n, JV_KIND_NUMBER));

#ifdef USE_DECNUM
  if (JVP_HAS_FLAGS(n, JVP_FLAGS_NUMBER_LITERAL)) {
    jvp_literal_number* m = jvp_literal_number_alloc(jvp_dec_number_ptr(n)->digits);

    decNumberAbs(&m->num_decimal, jvp_dec_number_ptr(n), DEC_CONTEXT());
    jv r = {JVP_FLAGS_NUMBER_LITERAL, 0, 0, 0, {&m->refcnt}};
    return r;
  }
#endif
  return jv_number(fabs(jv_number_value(n)));
}

jv jv_number_negate(jv n) {
  assert(JVP_HAS_KIND(n, JV_KIND_NUMBER));

#ifdef USE_DECNUM
  if (JVP_HAS_FLAGS(n, JVP_FLAGS_NUMBER_LITERAL)) {
    jvp_literal_number* m = jvp_literal_number_alloc(jvp_dec_number_ptr(n)->digits);

    decNumberMinus(&m->num_decimal, jvp_dec_number_ptr(n), DEC_CONTEXT());
    jv r = {JVP_FLAGS_NUMBER_LITERAL, 0, 0, 0, {&m->refcnt}};
    return r;
  }
#endif
  return jv_number(-jv_number_value(n));
}

int jvp_number_cmp(jv a, jv b) {
  assert(JVP_HAS_KIND(a, JV_KIND_NUMBER));
  assert(JVP_HAS_KIND(b, JV_KIND_NUMBER));

#ifdef USE_DECNUM
  if (JVP_HAS_FLAGS(a, JVP_FLAGS_NUMBER_LITERAL) && JVP_HAS_FLAGS(b, JVP_FLAGS_NUMBER_LITERAL)) {
    struct {
      decNumber number;
      decNumberUnit units[1];
    } res;

    decNumberCompare(&res.number,
                     jvp_dec_number_ptr(a),
                     jvp_dec_number_ptr(b),
                     DEC_CONTEXT()
                     );
    if (decNumberIsZero(&res.number)) {
      return 0;
    } else if (decNumberIsNegative(&res.number)) {
      return -1;
    } else {
      return 1;
    }
  }
#endif
  double da = jv_number_value(a), db = jv_number_value(b);
  if (da < db) {
    return -1;
  } else if (da == db) {
    return 0;
  } else {
    return 1;
  }
}

static int jvp_number_equal(jv a, jv b) {
  return jvp_number_cmp(a, b) == 0;
}

/*
 * Arrays (internal helpers)
 */

#define ARRAY_SIZE_ROUND_UP(n) (((n)*3)/2)
#define JVP_FLAGS_ARRAY   JVP_MAKE_FLAGS(JV_KIND_ARRAY, JVP_PAYLOAD_ALLOCATED)

static int imax(int a, int b) {
  if (a>b) return a;
  else return b;
}

//FIXME signed vs unsigned
typedef struct {
  jv_refcnt refcnt;
  int length, alloc_length;
  jv elements[];
} jvp_array;

static jvp_array* jvp_array_ptr(jv a) {
  assert(JVP_HAS_KIND(a, JV_KIND_ARRAY));
  return (jvp_array*)a.u.ptr;
}

static jvp_array* jvp_array_alloc(unsigned size) {
  jvp_array* a = jv_mem_alloc(sizeof(jvp_array) + sizeof(jv) * size);
  a->refcnt.count = 1;
  a->length = 0;
  a->alloc_length = size;
  return a;
}

static jv jvp_array_new(unsigned size) {
  jv r = {JVP_FLAGS_ARRAY, 0, 0, 0, {&jvp_array_alloc(size)->refcnt}};
  return r;
}

static void jvp_array_free(jv a) {
  assert(JVP_HAS_KIND(a, JV_KIND_ARRAY));
  if (jvp_refcnt_dec(a.u.ptr)) {
    jvp_array* array = jvp_array_ptr(a);
    for (int i=0; i<array->length; i++) {
      jv_free(array->elements[i]);
    }
    jv_mem_free(array);
  }
}

static int jvp_array_length(jv a) {
  assert(JVP_HAS_KIND(a, JV_KIND_ARRAY));
  return a.size;
}

static int jvp_array_offset(jv a) {
  assert(JVP_HAS_KIND(a, JV_KIND_ARRAY));
  return a.offset;
}

static jv* jvp_array_read(jv a, int i) {
  assert(JVP_HAS_KIND(a, JV_KIND_ARRAY));
  if (i >= 0 && i < jvp_array_length(a)) {
    jvp_array* array = jvp_array_ptr(a);
    assert(i + jvp_array_offset(a) < array->length);
    return &array->elements[i + jvp_array_offset(a)];
  } else {
    return 0;
  }
}

static jv* jvp_array_write(jv* a, int i) {
  assert(i >= 0);
  jvp_array* array = jvp_array_ptr(*a);

  int pos = i + jvp_array_offset(*a);
  if (pos < array->alloc_length && jvp_refcnt_unshared(a->u.ptr)) {
    // use existing array space
    for (int j = array->length; j <= pos; j++) {
      array->elements[j] = JV_NULL;
    }
    array->length = imax(pos + 1, array->length);
    a->size = imax(i + 1, a->size);
    return &array->elements[pos];
  } else {
    // allocate a new array
    int new_length = imax(i + 1, jvp_array_length(*a));
    jvp_array* new_array = jvp_array_alloc(ARRAY_SIZE_ROUND_UP(new_length));
    int j;
    for (j = 0; j < jvp_array_length(*a); j++) {
      new_array->elements[j] =
        jv_copy(array->elements[j + jvp_array_offset(*a)]);
    }
    for (; j < new_length; j++) {
      new_array->elements[j] = JV_NULL;
    }
    new_array->length = new_length;
    jvp_array_free(*a);
    jv new_jv = {JVP_FLAGS_ARRAY, 0, 0, new_length, {&new_array->refcnt}};
    *a = new_jv;
    return &new_array->elements[i];
  }
}

static int jvp_array_equal(jv a, jv b) {
  if (jvp_array_length(a) != jvp_array_length(b))
    return 0;
  if (jvp_array_ptr(a) == jvp_array_ptr(b) &&
      jvp_array_offset(a) == jvp_array_offset(b))
    return 1;
  for (int i=0; i<jvp_array_length(a); i++) {
    if (!jv_equal(jv_copy(*jvp_array_read(a, i)),
                  jv_copy(*jvp_array_read(b, i))))
      return 0;
  }
  return 1;
}

static void jvp_clamp_slice_params(int len, int *pstart, int *pend)
{
  if (*pstart < 0) *pstart = len + *pstart;
  if (*pend < 0) *pend = len + *pend;

  if (*pstart < 0) *pstart = 0;
  if (*pstart > len) *pstart = len;
  if (*pend > len) *pend = len;
  if (*pend < *pstart) *pend = *pstart;
}

static int jvp_array_contains(jv a, jv b) {
  int r = 1;
  jv_array_foreach(b, bi, belem) {
    int ri = 0;
    jv_array_foreach(a, ai, aelem) {
      if (jv_contains(aelem, jv_copy(belem))) {
        ri = 1;
        break;
      }
    }
    jv_free(belem);
    if (!ri) {
      r = 0;
      break;
    }
  }
  return r;
}

/*
 * Public
 */

static jv jvp_array_slice(jv a, int start, int end) {
  assert(JVP_HAS_KIND(a, JV_KIND_ARRAY));
  int len = jvp_array_length(a);
  jvp_clamp_slice_params(len, &start, &end);
  assert(0 <= start && start <= end && end <= len);

  // FIXME: maybe slice should reallocate if the slice is small enough
  if (start == end) {
    jv_free(a);
    return jv_array();
  }

  if (a.offset + start >= 1 << (sizeof(a.offset) * CHAR_BIT)) {
    jv r = jv_array_sized(end - start);
    for (int i = start; i < end; i++)
      r = jv_array_append(r, jv_array_get(jv_copy(a), i));
    jv_free(a);
    return r;
  } else {
    a.offset += start;
    a.size = end - start;
    return a;
  }
}

/*
 * Arrays (public interface)
 */

jv jv_array_sized(int n) {
  return jvp_array_new(n);
}

jv jv_array(void) {
  return jv_array_sized(16);
}

int jv_array_length(jv j) {
  assert(JVP_HAS_KIND(j, JV_KIND_ARRAY));
  int len = jvp_array_length(j);
  jv_free(j);
  return len;
}

jv jv_array_get(jv j, int idx) {
  assert(JVP_HAS_KIND(j, JV_KIND_ARRAY));
  jv* slot = jvp_array_read(j, idx);
  jv val;
  if (slot) {
    val = jv_copy(*slot);
  } else {
    val = jv_invalid();
  }
  jv_free(j);
  return val;
}

jv jv_array_set(jv j, int idx, jv val) {
  assert(JVP_HAS_KIND(j, JV_KIND_ARRAY));

  if (idx < 0)
    idx = jvp_array_length(j) + idx;
  if (idx < 0) {
    jv_free(j);
    jv_free(val);
    return jv_invalid_with_msg(jv_string("Out of bounds negative array index"));
  }
  if (idx > (INT_MAX >> 2) - jvp_array_offset(j)) {
    jv_free(j);
    jv_free(val);
    return jv_invalid_with_msg(jv_string("Array index too large"));
  }
  // copy/free of val,j coalesced
  jv* slot = jvp_array_write(&j, idx);
  jv_free(*slot);
  *slot = val;
  return j;
}

jv jv_array_append(jv j, jv val) {
  // copy/free of val,j coalesced
  return jv_array_set(j, jv_array_length(jv_copy(j)), val);
}

jv jv_array_concat(jv a, jv b) {
  assert(JVP_HAS_KIND(a, JV_KIND_ARRAY));
  assert(JVP_HAS_KIND(b, JV_KIND_ARRAY));

  // FIXME: could be faster
  jv_array_foreach(b, i, elem) {
    a = jv_array_append(a, elem);
    if (!jv_is_valid(a)) break;
  }
  jv_free(b);
  return a;
}

jv jv_array_slice(jv a, int start, int end) {
  assert(JVP_HAS_KIND(a, JV_KIND_ARRAY));
  // copy/free of a coalesced
  return jvp_array_slice(a, start, end);
}

jv jv_array_indexes(jv a, jv b) {
  jv res = jv_array();
  int idx = -1;
  int alen = jv_array_length(jv_copy(a));
  for (int ai = 0; ai < alen; ++ai) {
    jv_array_foreach(b, bi, belem) {
      if (!jv_equal(jv_array_get(jv_copy(a), ai + bi), belem))
        idx = -1;
      else if (bi == 0 && idx == -1)
        idx = ai;
    }
    if (idx > -1)
      res = jv_array_append(res, jv_number(idx));
    idx = -1;
  }
  jv_free(a);
  jv_free(b);
  return res;
}

/*
 * Strings (internal helpers)
 */

#define JVP_FLAGS_STRING  JVP_MAKE_FLAGS(JV_KIND_STRING, JVP_PAYLOAD_ALLOCATED)

typedef struct {
  jv_refcnt refcnt;
  uint32_t hash;
  // high 31 bits are length, low bit is a flag
  // indicating whether hash has been computed.
  uint32_t length_hashed;
  uint32_t alloc_length;
  char data[];
} jvp_string;

static jvp_string* jvp_string_ptr(jv a) {
  assert(JVP_HAS_KIND(a, JV_KIND_STRING));
  return (jvp_string*)a.u.ptr;
}

static jvp_string* jvp_string_alloc(uint32_t size) {
  jvp_string* s = jv_mem_alloc(sizeof(jvp_string) + size + 1);
  s->refcnt.count = 1;
  s->alloc_length = size;
  return s;
}

/* Copy a UTF8 string, replacing all badly encoded points with U+FFFD */
static jv jvp_string_copy_replace_bad(const char* data, uint32_t length) {
  const char* end = data + length;
  const char* i = data;

  uint32_t maxlength = length * 3 + 1; // worst case: all bad bytes, each becomes a 3-byte U+FFFD
  jvp_string* s = jvp_string_alloc(maxlength);
  char* out = s->data;
  int c = 0;

  while ((i = jvp_utf8_next(i, end, &c))) {
    if (c == -1) {
      c = 0xFFFD; // U+FFFD REPLACEMENT CHARACTER
    }
    out += jvp_utf8_encode(c, out);
    assert(out < s->data + maxlength);
  }
  length = out - s->data;
  s->data[length] = 0;
  s->length_hashed = length << 1;
  jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&s->refcnt}};
  return r;
}

/* Assumes valid UTF8 */
static jv jvp_string_new(const char* data, uint32_t length) {
  jvp_string* s = jvp_string_alloc(length);
  s->length_hashed = length << 1;
  if (data != NULL)
    memcpy(s->data, data, length);
  s->data[length] = 0;
  jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&s->refcnt}};
  return r;
}

static jv jvp_string_empty_new(uint32_t length) {
  jvp_string* s = jvp_string_alloc(length);
  s->length_hashed = 0;
  memset(s->data, 0, length);
  s->data[length] = 0;
  jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&s->refcnt}};
  return r;
}

static void jvp_string_free(jv js) {
  jvp_string* s = jvp_string_ptr(js);
  if (jvp_refcnt_dec(&s->refcnt)) {
    jv_mem_free(s);
  }
}

static uint32_t jvp_string_length(jvp_string* s) {
  return s->length_hashed >> 1;
}

static uint32_t jvp_string_remaining_space(jvp_string* s) {
  assert(s->alloc_length >= jvp_string_length(s));
  uint32_t r = s->alloc_length - jvp_string_length(s);
  return r;
}

static jv jvp_string_append(jv string, const char* data, uint32_t len) {
  jvp_string* s = jvp_string_ptr(string);
  uint32_t currlen = jvp_string_length(s);

  if (jvp_refcnt_unshared(string.u.ptr) &&
      jvp_string_remaining_space(s) >= len) {
    // the next string fits at the end of a
    memcpy(s->data + currlen, data, len);
    s->data[currlen + len] = 0;
    s->length_hashed = (currlen + len) << 1;
    return string;
  } else {
    // allocate a bigger buffer and copy
    uint32_t allocsz = (currlen + len) * 2;
    if (allocsz < 32) allocsz = 32;
    jvp_string* news = jvp_string_alloc(allocsz);
    news->length_hashed = (currlen + len) << 1;
    memcpy(news->data, s->data, currlen);
    memcpy(news->data + currlen, data, len);
    news->data[currlen + len] = 0;
    jvp_string_free(string);
    jv r = {JVP_FLAGS_STRING, 0, 0, 0, {&news->refcnt}};
    return r;
  }
}

static const uint32_t HASH_SEED = 0x432A9843;

static uint32_t rotl32 (uint32_t x, int8_t r){
  return (x << r) | (x >> (32 - r));
}

static uint32_t jvp_string_hash(jv jstr) {
  jvp_string* str = jvp_string_ptr(jstr);
  if (str->length_hashed & 1)
    return str->hash;

  /* The following is based on MurmurHash3.
     MurmurHash3 was written by Austin Appleby, and is placed
     in the public domain. */

  const uint8_t* data = (const uint8_t*)str->data;
  int len = (int)jvp_string_length(str);
  const int nblocks = len / 4;

  uint32_t h1 = HASH_SEED;

  const uint32_t c1 = 0xcc9e2d51;
  const uint32_t c2 = 0x1b873593;
  const uint32_t* blocks = (const uint32_t *)(data + nblocks*4);

  for(int i = -nblocks; i; i++) {
    uint32_t k1 = blocks[i]; //FIXME: endianness/alignment

    k1 *= c1;
    k1 = rotl32(k1,15);
    k1 *= c2;

    h1 ^= k1;
    h1 = rotl32(h1,13);
    h1 = h1*5+0xe6546b64;
  }

  const uint8_t* tail = (const uint8_t*)(data + nblocks*4);

  uint32_t k1 = 0;

  switch(len & 3) {
  case 3: k1 ^= tail[2] << 16;
          JQ_FALLTHROUGH;
  case 2: k1 ^= tail[1] << 8;
          JQ_FALLTHROUGH;
  case 1: k1 ^= tail[0];
          k1 *= c1; k1 = rotl32(k1,15); k1 *= c2; h1 ^= k1;
  }

  h1 ^= len;

  h1 ^= h1 >> 16;
  h1 *= 0x85ebca6b;
  h1 ^= h1 >> 13;
  h1 *= 0xc2b2ae35;
  h1 ^= h1 >> 16;

  str->length_hashed |= 1;
  str->hash = h1;

  return h1;
}

static int jvp_string_equal(jv a, jv b) {
  assert(JVP_HAS_KIND(a, JV_KIND_STRING));
  assert(JVP_HAS_KIND(b, JV_KIND_STRING));
  jvp_string* stra = jvp_string_ptr(a);
  jvp_string* strb = jvp_string_ptr(b);
  if (jvp_string_length(stra) != jvp_string_length(strb)) return 0;
  return memcmp(stra->data, strb->data, jvp_string_length(stra)) == 0;
```

[Assistant]
<<<<<<< SEARCH
#include <limits.h>
#include <math.h>
#include <float.h>

#include "jv_alloc.h"
#include "jv.h"
=======
#include <limits.h>
#include <math.h>
#include <float.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>

#include "jv_alloc.h"
#include "jv.h"
>>>>>>> REPLACE
<<<<<<< SEARCH
  }
}

static const uint32_t HASH_SEED = 0x432A9843;

static uint32_t rotl32 (uint32_t x, int8_t r){
  return (x << r) | (x >> (32 - r));
=======
  }
}

static uint32_t hash_seed;
static pthread_once_t hash_seed_once = PTHREAD_ONCE_INIT;

static void jvp_hash_seed_init(void) {
  uint32_t seed;
#if defined(HAVE_ARC4RANDOM)
  seed = arc4random();
#elif defined(HAVE_GETENTROPY)
  if (getentropy(&seed, sizeof(seed)) != 0)
    seed = (uint32_t)getpid() ^ (uint32_t)time(NULL);
#else
  int fd = open("/dev/urandom", O_RDONLY);
  if (fd >= 0) {
    if (read(fd, &seed, sizeof(seed)) != 4)
      seed = (uint32_t)getpid() ^ (uint32_t)time(NULL);
    close(fd);
  } else {
    seed = (uint32_t)getpid() ^ (uint32_t)time(NULL);
  }
#endif
  hash_seed = seed;
}

static uint32_t jvp_hash_seed(void) {
  pthread_once(&hash_seed_once, jvp_hash_seed_init);
  return hash_seed;
}

static uint32_t rotl32 (uint32_t x, int8_t r){
  return (x << r) | (x >> (32 - r));
>>>>>>> REPLACE
<<<<<<< SEARCH
  int len = (int)jvp_string_length(str);
  const int nblocks = len / 4;

  uint32_t h1 = HASH_SEED;

  const uint32_t c1 = 0xcc9e2d51;
  const uint32_t c2 = 0x1b873593;
=======
  int len = (int)jvp_string_length(str);
  const int nblocks = len / 4;

  uint32_t h1 = jvp_hash_seed();

  const uint32_t c1 = 0xcc9e2d51;
  const uint32_t c2 = 0x1b873593;
>>>>>>> REPLACE


[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 one or more SEARCH/REPLACE blocks. Follow these rules exactly:
1. Each block is:
<<<<<<< SEARCH
<exact lines copied verbatim from the shown source window>
=======
<the replacement lines>
>>>>>>> REPLACE
2. The SEARCH text MUST appear verbatim in the shown source window — copy it exactly, including whitespace; do not invent or paraphrase it.
3. Change as few lines as possible; keep the SEARCH span tight around the edit.
4. Modify ONLY code visible in the shown source window.
5. Output only the SEARCH/REPLACE block(s) with no other text.
6. Prefer folding a new bound or check into an existing condition over adding a separate guard, when the upstream fix does so.

[User]
# CVE
CVE-2026-40198: Improper input validation / incorrect computation (CWE-20) in the Perl module Net::CIDR::Lite. The IPv6 packer accepted an uncompressed address that had fewer than the eight groups a full IPv6 address requires and carried no compression marker, for example a seven-group string. Such an address has no valid 128-bit interpretation, but the module produced a packed value for it anyway, which corrupts the subsequent network-mask and range-comparison so a range or membership test operates on the wrong bytes. A CIDR allow-list or deny-list built from attacker-influenced IPv6 input therefore admits or blocks the wrong addresses, an IP access-control bypass via find(). Affects Net::CIDR::Lite before 0.23.

# Vulnerable source (Lite.pm)
```perl
}

sub _unpack_ipv4 {
    join(".", unpack("xC*", shift));
}

sub _pack_ipv6 {
    my $ip = shift;
    $ip =~ s/^::$/::0/;
    return if $ip =~ /^:/ and $ip !~ s/^::/:/;
    return if $ip =~ /:$/ and $ip !~ s/::$/:/;
    my @nums = split /:/, $ip, -1;
    return unless @nums <= 8;
    my ($empty, $ipv4, $str) = (0,'','');
    for (@nums) {
        return if $ipv4;
        $str .= "0" x (4-length) . $_, next if /^[a-fA-F\d]{1,4}$/;
        do { return if $empty++ }, $str .= "X", next if $_ eq '';
        next if $ipv4 = _pack_ipv4($_);
        return;
    }
    return if $ipv4 and @nums > 6;
    $str =~ s/X/"0" x (($ipv4 ? 25 : 33)-length($str))/e if $empty;
    pack("H*", "00" . $str).$ipv4;
}

sub _unpack_ipv6 {
    _compress_ipv6(join(":", unpack("xH*", shift) =~ /..../g)),
}

# Replace longest run of null blocks with a double colon
sub _compress_ipv6 {
    my $ip = shift;
    if (my @runs = $ip =~ /((?:(?:^|:)(?:0000))+:?)/g ) {
        my $max = $runs[0];
        for (@runs[1..$#runs]) {
            $max = $_ if length($max) < length;
        }
        $ip =~ s/$max/::/;
    }
```

[Assistant]
<<<<<<< SEARCH
        return;
    }
    return if $ipv4 and @nums > 6;
    $str =~ s/X/"0" x (($ipv4 ? 25 : 33)-length($str))/e if $empty;
    pack("H*", "00" . $str).$ipv4;
}
=======
        return;
    }
    return if $ipv4 and @nums > 6;
    return unless $empty or @nums == ($ipv4 ? 6 : 8);
    $str =~ s/X/"0" x (($ipv4 ? 25 : 33)-length($str))/e if $empty;
    pack("H*", "00" . $str).$ipv4;
}
>>>>>>> REPLACE


[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 one or more SEARCH/REPLACE blocks. Follow these rules exactly:
1. Each block is:
<<<<<<< SEARCH
<exact lines copied verbatim from the shown source window>
=======
<the replacement lines>
>>>>>>> REPLACE
2. The SEARCH text MUST appear verbatim in the shown source window — copy it exactly, including whitespace; do not invent or paraphrase it.
3. Change as few lines as possible; keep the SEARCH span tight around the edit.
4. Modify ONLY code visible in the shown source window.
5. Output only the SEARCH/REPLACE block(s) with no other text.
6. Prefer folding a new bound or check into an existing condition over adding a separate guard, when the upstream fix does so.

[User]
# CVE
CVE-2026-40199: Improper input validation / incorrect computation (CWE-20) in the Perl module Net::CIDR::Lite. When packing an IPv4-mapped IPv6 address such as ::ffff:192.168.1.0, the module appended the full result of its IPv4 packer, which carries an extra leading sentinel byte, instead of the address bytes alone. The packed value was therefore one byte too long, which corrupts the subsequent network-mask and range-comparison so a membership test returns the wrong answer: an address outside an IPv4-mapped allow-list range is reported as inside it. A CIDR allow-list or deny-list built over IPv4-mapped IPv6 ranges consequently admits or blocks the wrong addresses, an IP access-control bypass via find(). Affects Net::CIDR::Lite before 0.23.

# Vulnerable source (Lite.pm)
```perl
sub _unpack_ipv4 {
    join(".", unpack("xC*", shift));
}

sub _pack_ipv6 {
    my $ip = shift;
    $ip =~ s/^::$/::0/;
    return if $ip =~ /^:/ and $ip !~ s/^::/:/;
    return if $ip =~ /:$/ and $ip !~ s/::$/:/;
    my @nums = split /:/, $ip, -1;
    return unless @nums <= 8;
    my ($empty, $ipv4, $str) = (0,'','');
    for (@nums) {
        return if $ipv4;
        $str .= "0" x (4-length) . $_, next if /^[a-fA-F\d]{1,4}$/;
        do { return if $empty++ }, $str .= "X", next if $_ eq '';
        next if $ipv4 = _pack_ipv4($_);
        return;
    }
    return if $ipv4 and @nums > 6;
    return unless $empty or @nums == ($ipv4 ? 6 : 8);
    $str =~ s/X/"0" x (($ipv4 ? 25 : 33)-length($str))/e if $empty;
    pack("H*", "00" . $str).$ipv4;
}

sub _unpack_ipv6 {
    _compress_ipv6(join(":", unpack("xH*", shift) =~ /..../g)),
}

# Replace longest run of null blocks with a double colon
sub _compress_ipv6 {
    my $ip = shift;
    if (my @runs = $ip =~ /((?:(?:^|:)(?:0000))+:?)/g ) {
        my $max = $runs[0];
        for (@runs[1..$#runs]) {
            $max = $_ if length($max) < length;
        }
        $ip =~ s/$max/::/;
    }
    $ip =~ s/:0{1,3}/:/g;
```

[Assistant]
<<<<<<< SEARCH
    return if $ipv4 and @nums > 6;
    return unless $empty or @nums == ($ipv4 ? 6 : 8);
    $str =~ s/X/"0" x (($ipv4 ? 25 : 33)-length($str))/e if $empty;
    pack("H*", "00" . $str).$ipv4;
}

sub _unpack_ipv6 {
=======
    return if $ipv4 and @nums > 6;
    return unless $empty or @nums == ($ipv4 ? 6 : 8);
    $str =~ s/X/"0" x (($ipv4 ? 25 : 33)-length($str))/e if $empty;
    pack("H*", "00" . $str).substr($ipv4, 1);
}

sub _unpack_ipv6 {
>>>>>>> REPLACE


[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 one or more SEARCH/REPLACE blocks. Follow these rules exactly:
1. Each block is:
<<<<<<< SEARCH
<exact lines copied verbatim from the shown source window>
=======
<the replacement lines>
>>>>>>> REPLACE
2. The SEARCH text MUST appear verbatim in the shown source window — copy it exactly, including whitespace; do not invent or paraphrase it.
3. Change as few lines as possible; keep the SEARCH span tight around the edit.
4. Modify ONLY code visible in the shown source window.
5. Output only the SEARCH/REPLACE block(s) with no other text.
6. Prefer folding a new bound or check into an existing condition over adding a separate guard, when the upstream fix does so.

[User]
# CVE
CVE-2026-40355: Null pointer dereference in MIT krb5 1.22.2 NegoEx message parsing: the parse_nego_message() function in src/lib/gssapi/spnego/negoex_util.c obtains a pointer via vector_base() to an extension table in the message payload but does not verify whether the pointer is non-null before indexing into the extension table, allowing an unauthenticated remote attacker to crash any GSS application that accepts NegoEx context tokens.

# Vulnerable source (src/lib/gssapi/spnego/negoex_util.c)
```c
static OM_uint32
parse_nego_message(OM_uint32 *minor, struct k5input *in,
                   const uint8_t *msg_base, size_t msg_len,
                   struct nego_message *msg)
{
    const uint8_t *p;
    uint64_t protocol_version;
    uint32_t extension_type;
    size_t offset, count, i;

    p = k5_input_get_bytes(in, sizeof(msg->random));
    if (p != NULL)
        memcpy(msg->random, p, sizeof(msg->random));
    protocol_version = k5_input_get_uint64_le(in);
    if (protocol_version != 0) {
        *minor = ERR_NEGOEX_UNSUPPORTED_VERSION;
        return GSS_S_UNAVAILABLE;
    }

    offset = k5_input_get_uint32_le(in);
    count = k5_input_get_uint16_le(in);
    msg->schemes = vector_base(offset, count, GUID_LENGTH, msg_base, msg_len);
    msg->nschemes = count;
    if (msg->schemes == NULL) {
        *minor = ERR_NEGOEX_INVALID_MESSAGE_SIZE;
        return GSS_S_DEFECTIVE_TOKEN;
    }

    offset = k5_input_get_uint32_le(in);
    count = k5_input_get_uint16_le(in);
    p = vector_base(offset, count, EXTENSION_LENGTH, msg_base, msg_len);
    for (i = 0; i < count; i++) {
        extension_type = load_32_le(p + i * EXTENSION_LENGTH);
        if (extension_type & EXTENSION_FLAG_CRITICAL) {
            *minor = ERR_NEGOEX_UNSUPPORTED_CRITICAL_EXTENSION;
            return GSS_S_UNAVAILABLE;
        }
    }

    return GSS_S_COMPLETE;
}
```

[Assistant]
<<<<<<< SEARCH
    offset = k5_input_get_uint32_le(in);
    count = k5_input_get_uint16_le(in);
    p = vector_base(offset, count, EXTENSION_LENGTH, msg_base, msg_len);
    for (i = 0; i < count; i++) {
        extension_type = load_32_le(p + i * EXTENSION_LENGTH);
        if (extension_type & EXTENSION_FLAG_CRITICAL) {
=======
    offset = k5_input_get_uint32_le(in);
    count = k5_input_get_uint16_le(in);
    p = vector_base(offset, count, EXTENSION_LENGTH, msg_base, msg_len);
    if (p == NULL) {
        *minor = ERR_NEGOEX_INVALID_MESSAGE_SIZE;
        return GSS_S_DEFECTIVE_TOKEN;
    }
    for (i = 0; i < count; i++) {
        extension_type = load_32_le(p + i * EXTENSION_LENGTH);
        if (extension_type & EXTENSION_FLAG_CRITICAL) {
>>>>>>> REPLACE


[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 one or more SEARCH/REPLACE blocks. Follow these rules exactly:
1. Each block is:
<<<<<<< SEARCH
<exact lines copied verbatim from the shown source window>
=======
<the replacement lines>
>>>>>>> REPLACE
2. The SEARCH text MUST appear verbatim in the shown source window — copy it exactly, including whitespace; do not invent or paraphrase it.
3. Change as few lines as possible; keep the SEARCH span tight around the edit.
4. Modify ONLY code visible in the shown source window.
5. Output only the SEARCH/REPLACE block(s) with no other text.
6. Prefer folding a new bound or check into an existing condition over adding a separate guard, when the upstream fix does so.

[User]
# CVE
CVE-2026-42046: libcaca is a graphics library that renders images as colored ASCII art. Signed integer overflow is undefined behavior in C, so a sufficiently large canvas request can produce a negative or incorrect allocation size without being caught by the subsequent check. An attacker who can control canvas dimensions could trigger this overflow, resulting in an undersized buffer allocation followed by heap corruption when the library writes past the buffer boundary.

# Vulnerable source (caca/canvas.c)
```c
/*
 *  libcaca     Colour ASCII-Art library
 *  Copyright © 2002—2021 Sam Hocevar <sam@hocevar.net>
 *              All Rights Reserved
 *
 *  This library is free software. It comes without any warranty, to
 *  the extent permitted by applicable law. You can redistribute it
 *  and/or modify it under the terms of the Do What the Fuck You Want
 *  to Public License, Version 2, as published by Sam Hocevar. See
 *  http://www.wtfpl.net/ for more details.
 */

/*
 *  This file contains the main functions used by \e libcaca applications
 *  to initialise a drawing context.
 */

#include "config.h"

#if !defined(__KERNEL__)
#   include <stdio.h>
#   include <stdlib.h>
#   include <string.h>
#   include <time.h>
#   include <sys/types.h>
#   if defined(HAVE_UNISTD_H)
#       include <unistd.h>
#   endif
#endif

#include "caca.h"
#include "caca_internals.h"

static int caca_resize(caca_canvas_t *, int, int);

/** \brief Initialise a \e libcaca canvas.
 *
 *  Initialise internal \e libcaca structures and the backend that will
 *  be used for subsequent graphical operations. It must be the first
 *  \e libcaca function to be called in a function. caca_free_canvas()
 *  should be called at the end of the program to free all allocated resources.
 *
 *  Both the cursor and the canvas' handle are initialised at the top-left
 *  corner.
 *
 *  If an error occurs, NULL is returned and \b errno is set accordingly:
 *  - \c EINVAL Specified width or height is invalid.
 *  - \c EOVERFLOW Specified width and height overflowed.
 *  - \c ENOMEM Not enough memory for the requested canvas size.
 *
 *  \param width The desired canvas width
 *  \param height The desired canvas height
 *  \return A libcaca canvas handle upon success, NULL if an error occurred.
 */
caca_canvas_t * caca_create_canvas(int width, int height)
{
    caca_canvas_t *cv;

    if(width < 0 || height < 0)
    {
        seterrno(EINVAL);
        return NULL;
    }

    cv = malloc(sizeof(caca_canvas_t));

    if(!cv)
        goto nomem;

    cv->refcount = 0;
    cv->autoinc = 0;
    cv->resize_callback = NULL;
    cv->resize_data = NULL;

    cv->frame = 0;
    cv->framecount = 1;
    cv->frames = malloc(sizeof(struct caca_frame));
    if(!cv->frames)
    {
        free(cv);
        goto nomem;
    }

    cv->frames[0].width = cv->frames[0].height = 0;
    cv->frames[0].chars = NULL;
    cv->frames[0].attrs = NULL;
    cv->frames[0].x = cv->frames[0].y = 0;
    cv->frames[0].handlex = cv->frames[0].handley = 0;
    cv->frames[0].curattr = 0;
    cv->frames[0].name = strdup("frame#00000000");

    _caca_load_frame_info(cv);
    caca_set_color_ansi(cv, CACA_DEFAULT, CACA_TRANSPARENT);

    cv->ndirty = 0;
    cv->dirty_disabled = 0;
    cv->ff = NULL;

    if(caca_resize(cv, width, height) < 0)
    {
        int saved_errno = geterrno();
        free(cv->frames[0].name);
        free(cv->frames);
        free(cv);
        seterrno(saved_errno);
        return NULL;
    }

    return cv;

nomem:
    seterrno(ENOMEM);
    return NULL;
}

/** \brief Manage a canvas.
 *
 *  Lock a canvas to prevent it from being resized. If non-NULL,
 *  the \e callback function pointer will be called upon each
 *  \e caca_set_canvas_size call and if the returned value is zero, the
 *  canvas resize request will be denied.
 *
 *  This function is only useful for display drivers such as the \e libcaca
 *  library.
 *
 *  If an error occurs, -1 is returned and \b errno is set accordingly:
 *  - \c EBUSY The canvas is already being managed.
 *
 *  \param cv A libcaca canvas.
 *  \param callback An optional callback function pointer.
 *  \param p The argument to be passed to \e callback.
 *  \return 0 in case of success, -1 if an error occurred.
 */
int caca_manage_canvas(caca_canvas_t *cv, int (*callback)(void *), void *p)
{
    if(cv->refcount)
    {
        seterrno(EBUSY);
        return -1;
    }

    cv->resize_callback = callback;
    cv->resize_data = p;
    cv->refcount = 1;

    return 0;
}

/** \brief unmanage a canvas.
 *
 *  unlock a canvas previously locked by caca_manage_canvas(). for safety
 *  reasons, the callback and callback data arguments must be the same as for
 *  the caca_manage_canvas() call.
 *
 *  this function is only useful for display drivers such as the \e libcaca
 *  library.
 *
 *  if an error occurs, -1 is returned and \b errno is set accordingly:
 *  - \c einval the canvas is not managed, or the callback arguments do
 *              not match.
 *
 *  \param cv a libcaca canvas.
 *  \param callback the \e callback argument previously passed to
 *                  caca_manage_canvas().
 *  \param p the \e p argument previously passed to caca_manage_canvas().
 *  \return 0 in case of success, -1 if an error occurred.
 */
int caca_unmanage_canvas(caca_canvas_t *cv, int (*callback)(void *), void *p)
{
    if(!cv->refcount
        || cv->resize_callback != callback || cv->resize_data != p)
    {
        seterrno(EINVAL);
        return -1;
    }

    cv->refcount = 0;

    return 0;
}

/** \brief Resize a canvas.
 *
 *  Set the canvas' width and height, in character cells.
 *
 *  The contents of the canvas are preserved to the extent of the new
 *  canvas size. Newly allocated character cells at the right and/or at
 *  the bottom of the canvas are filled with spaces.
 *
 *  If as a result of the resize the cursor coordinates fall outside the
 *  new canvas boundaries, they are readjusted. For instance, if the
 *  current X cursor coordinate is 11 and the requested width is 10, the
 *  new X cursor coordinate will be 10.
 *
 *  It is an error to try to resize the canvas if an output driver has
 *  been attached to the canvas using caca_create_display(). You need to
 *  remove the output driver using caca_free_display() before you can change
 *  the canvas size again. However, the caca output driver can cause a
 *  canvas resize through user interaction. See the caca_event() documentation
 *  for more about this.
 *
 *  If an error occurs, -1 is returned and \b errno is set accordingly:
 *  - \c EINVAL Specified width or height is invalid.
 *  - \c EOVERFLOW Specified width and height overflowed.
 *  - \c EBUSY The canvas is in use by a display driver and cannot be resized.
 *  - \c ENOMEM Not enough memory for the requested canvas size. If this
 *    happens, the canvas handle becomes invalid and should not be used.
 *
 *  \param cv A libcaca canvas.
 *  \param width The desired canvas width.
 *  \param height The desired canvas height.
 *  \return 0 in case of success, -1 if an error occurred.
 */
int caca_set_canvas_size(caca_canvas_t *cv, int width, int height)
{
    if(width < 0 || height < 0)
    {
        seterrno(EINVAL);
        return -1;
    }

    if(cv->refcount && cv->resize_callback
        && !cv->resize_callback(cv->resize_data))
    {
        seterrno(EBUSY);
        return -1;
    }

    return caca_resize(cv, width, height);
}

/** \brief Get the canvas width.
 *
 *  Return the current canvas' width, in character cells.
 *
 *  This function never fails.
 *
 *  \param cv A libcaca canvas.
 *  \return The canvas width.
 */
int caca_get_canvas_width(caca_canvas_t const *cv)
{
    return cv->width;
}

/** \brief Get the canvas height.
 *
 *  Returns the current canvas' height, in character cells.
 *
 *  This function never fails.
 *
 *  \param cv A libcaca canvas.
 *  \return The canvas height.
 */
int caca_get_canvas_height(caca_canvas_t const *cv)
{
    return cv->height;
}

/** \brief Get the canvas character array.
 *
 *  Return the current canvas' internal character array. The array elements
 *  consist in native endian 32-bit Unicode values as returned by
 *  caca_get_char().
 *
 *  This function is probably only useful for \e libcaca 's internal display
 *  drivers.
 *
 *  This function never fails.
 *
 *  \param cv A libcaca canvas.
 *  \return The canvas character array.
 */
uint32_t const * caca_get_canvas_chars(caca_canvas_t const *cv)
{
    return (uint32_t const *)cv->chars;
}

/** \brief Get the canvas attribute array.
 *
 *  Returns the current canvas' internal attribute array. The array elements
 *  consist in native endian 32-bit attribute values as returned by
 *  caca_get_attr().
 *
 *  This function is probably only useful for \e libcaca 's internal display
 *  drivers.
 *
 *  This function never fails.
 *
 *  \param cv A libcaca canvas.
 *  \return The canvas attribute array.
 */
uint32_t const * caca_get_canvas_attrs(caca_canvas_t const *cv)
{
    return (uint32_t const *)cv->attrs;
}

/** \brief Free a \e libcaca canvas.
 *
 *  Free all resources allocated by caca_create_canvas(). The canvas
 *  pointer becomes invalid and must no longer be used unless a new call
 *  to caca_create_canvas() is made.
 *
 *  If an error occurs, -1 is returned and \b errno is set accordingly:
 *  - \c EBUSY The canvas is in use by a display driver and cannot be freed.
 *
 *  \param cv A libcaca canvas.
 *  \return 0 in case of success, -1 if an error occurred.
 */
int caca_free_canvas(caca_canvas_t *cv)
{
    int f;

    if(cv->refcount)
    {
        seterrno(EBUSY);
        return -1;
    }

    for(f = 0; f < cv->framecount; f++)
    {
        free(cv->frames[f].chars);
        free(cv->frames[f].attrs);
        free(cv->frames[f].name);
    }

    caca_canvas_set_figfont(cv, NULL);

    free(cv->frames);
    free(cv);

    return 0;
}

/** \brief Generate a random integer within a range.
 *
 *  Generate a random integer within the given range.
 *
 *  This function never fails.
 *
 *  \param min The lower bound of the integer range.
 *  \param max The upper bound of the integer range.
 *  \return A random integer comprised between \p min  and \p max - 1
 *  (inclusive).
 */
static caca_timer_t timer = {0, 0};

int caca_rand(int min, int max)
{
    static int need_init = 1;

    if(need_init)
    {
        srand(getpid() + _caca_getticks(&timer));
        need_init = 0;
    }

    return min + (int)((1.0 * (max - min)) * rand() / (RAND_MAX + 1.0));
}

/*
 * XXX: The following functions are local.
 */

int caca_resize(caca_canvas_t *cv, int width, int height)
{
    int x, y, f, old_width, old_height, old_size;

    /* Check for overflow */
    int new_size = width * height;
    if (new_size < 0 || (width > 0 && new_size / width != height))
    {
        seterrno(EOVERFLOW);
        return -1;
    }

    old_width = cv->width;
    old_height = cv->height;
    old_size = old_width * old_height;

    _caca_save_frame_info(cv);

    /* Preload new width and height values into the canvas to optimise
     * dirty rectangle handling */
    cv->width = width;
    cv->height = height;

    /* If width or height is smaller (or both), we have the opportunity to
     * reduce or even remove dirty rectangles */
    if(width < old_width || height < old_height)
        _caca_clip_dirty_rect_list(cv);

    /* Step 1: if new area is bigger, resize the memory area now. */
    if(new_size > old_size)
    {
        for(f = 0; f < cv->framecount; f++)
        {
            cv->frames[f].chars = realloc(cv->frames[f].chars,
                                          new_size * sizeof(uint32_t));
            cv->frames[f].attrs = realloc(cv->frames[f].attrs,
                                          new_size * sizeof(uint32_t));
            if(new_size && (!cv->frames[f].chars || !cv->frames[f].attrs))
            {
                seterrno(ENOMEM);
                return -1;
            }
        }
    }

    /* Step 2: move line data if necessary. */
    if(width == old_width)
    {
        /* Width did not change, which means we do not need to move data. */
        ;
    }
    else if(width > old_width)
    {
        /* New width is bigger than old width, which means we need to
```

[Assistant]
<<<<<<< SEARCH
#   if defined(HAVE_UNISTD_H)
#       include <unistd.h>
#   endif
#endif

#include "caca.h"
=======
#   if defined(HAVE_UNISTD_H)
#       include <unistd.h>
#   endif
#   include <limits.h>
#endif

#include "caca.h"
>>>>>>> REPLACE
<<<<<<< SEARCH
    int x, y, f, old_width, old_height, old_size;

    /* Check for overflow */
    int new_size = width * height;
    if (new_size < 0 || (width > 0 && new_size / width != height))
    {
        seterrno(EOVERFLOW);
        return -1;
    }

    old_width = cv->width;
    old_height = cv->height;
=======
    int x, y, f, old_width, old_height, old_size;

    /* Check for overflow */
    if (width != 0 && height > INT_MAX / width)
    {
        seterrno(EOVERFLOW);
        return -1;
    }
    int new_size = width * height;

    old_width = cv->width;
    old_height = cv->height;
>>>>>>> REPLACE


[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 one or more SEARCH/REPLACE blocks. Follow these rules exactly:
1. Each block is:
<<<<<<< SEARCH
<exact lines copied verbatim from the shown source window>
=======
<the replacement lines>
>>>>>>> REPLACE
2. The SEARCH text MUST appear verbatim in the shown source window — copy it exactly, including whitespace; do not invent or paraphrase it.
3. Change as few lines as possible; keep the SEARCH span tight around the edit.
4. Modify ONLY code visible in the shown source window.
5. Output only the SEARCH/REPLACE block(s) with no other text.
6. Prefer folding a new bound or check into an existing condition over adding a separate guard, when the upstream fix does so.

[User]
# CVE
CVE-2026-45190: Improper input validation (CWE-20) in the Perl module Net::CIDR::Lite. Such inputs passed the numeric validators in add() and the address packers, and were then numerically coerced and re-encoded to a different address than a strict reader would use. Affects Net::CIDR::Lite before 0.24.

# Vulnerable source (Lite.pm)
```perl
    $self->add_any($_) for @_;
    $self;
}

sub add_any {
    my $self = shift;
    for (@_) {
        tr|/|| && do { $self->add($_); next };
        tr|-|| && do { $self->add_range($_); next };
        UNIVERSAL::isa($_, 'Net::CIDR::Lite') && do {
            $self->add_cidr($_); next
        };
        $self->add_ip($_), next;
    }
    $self;
}

sub add {
    my $self = shift;
    my ($ip, $mask) = split "/", shift;
    $self->_init($ip) || confess "Can't determine ip format" unless %$self;
    confess "Bad mask $mask"
        unless $mask =~ /^\d+$/ and $mask <= $self->{NBITS}-8;
    $mask += 8;
    my $start = $self->{PACK}->($ip) & $self->{MASKS}[$mask]
        or confess "Bad ip address: $ip";
    my $end = $self->_add_bit($start, $mask);
    ++$$self{RANGES}{$start} || delete $$self{RANGES}{$start};
    --$$self{RANGES}{$end}   || delete $$self{RANGES}{$end};
    $self;
}

sub clean {
    my $self = shift;
    return $self unless $self->{RANGES};
    my $ranges = $$self{RANGES};
    my $total;
    $$self{RANGES} = {
      map { $total ? ($total+=$$ranges{$_})? () : ($_=>-1)
                   : do { $total+=$$ranges{$_}; ($_=>1) }
        /* ... */
    } elsif (_pack_ipv6($ip)) {
        $nbits = 136;
        $pack = \&_pack_ipv6;
        $unpack = \&_unpack_ipv6;
    } else {
        return;
    }
    $$self{PACK}  = $pack;
    $$self{UNPACK}  = $unpack;
    $$self{NBITS} = $nbits;
    $$self{MASKS} = $masks{$nbits} ||= [
      map { pack("B*", substr("1" x $_ . "0" x $nbits, 0, $nbits))
          } 0..$nbits
    ];
    $$self{RANGES} = {};
    $self;
}

sub _pack_ipv4 {
    my @nums = split /\./, shift(), -1;
    return unless @nums == 4;
    for (@nums) {
        return unless /^\d{1,3}$/ and !/^0\d{1,2}$/ and $_ <= 255;
    }
    pack("CC*", 0, @nums);
}

sub _unpack_ipv4 {
    join(".", unpack("xC*", shift));
}

sub _pack_ipv6 {
    my $ip = shift;
    $ip =~ s/^::$/::0/;
    return if $ip =~ /^:/ and $ip !~ s/^::/:/;
    return if $ip =~ /:$/ and $ip !~ s/::$/:/;
    my @nums = split /:/, $ip, -1;
    return unless @nums <= 8;
    my ($empty, $ipv4, $str) = (0,'','');
    for (@nums) {
        return if $ipv4;
        $str .= "0" x (4-length) . $_, next if /^[a-fA-F\d]{1,4}$/;
        do { return if $empty++ }, $str .= "X", next if $_ eq '';
        next if $ipv4 = _pack_ipv4($_);
        return;
    }
    return if $ipv4 and @nums > 6;
    return unless $empty or @nums == ($ipv4 ? 6 : 8);
    $str =~ s/X/"0" x (($ipv4 ? 25 : 33)-length($str))/e if $empty;
    pack("H*", "00" . $str).substr($ipv4, 1);
}
```

[Assistant]
<<<<<<< SEARCH
    my ($ip, $mask) = split "/", shift;
    $self->_init($ip) || confess "Can't determine ip format" unless %$self;
    confess "Bad mask $mask"
        unless $mask =~ /^\d+$/ and $mask <= $self->{NBITS}-8;
    $mask += 8;
    my $start = $self->{PACK}->($ip) & $self->{MASKS}[$mask]
        or confess "Bad ip address: $ip";
=======
    my ($ip, $mask) = split "/", shift;
    $self->_init($ip) || confess "Can't determine ip format" unless %$self;
    confess "Bad mask $mask"
        unless $mask =~ /\A[0-9]+\z/ and $mask <= $self->{NBITS}-8;
    $mask += 8;
    my $start = $self->{PACK}->($ip) & $self->{MASKS}[$mask]
        or confess "Bad ip address: $ip";
>>>>>>> REPLACE
<<<<<<< SEARCH
    my @nums = split /\./, shift(), -1;
    return unless @nums == 4;
    for (@nums) {
        return unless /^\d{1,3}$/ and !/^0\d{1,2}$/ and $_ <= 255;
    }
    pack("CC*", 0, @nums);
}
=======
    my @nums = split /\./, shift(), -1;
    return unless @nums == 4;
    for (@nums) {
        return unless /\A[0-9]{1,3}\z/ and !/\A0[0-9]{1,2}\z/ and $_ <= 255;
    }
    pack("CC*", 0, @nums);
}
>>>>>>> REPLACE
<<<<<<< SEARCH

sub _pack_ipv6 {
    my $ip = shift;
    $ip =~ s/^::$/::0/;
    return if $ip =~ /^:/ and $ip !~ s/^::/:/;
    return if $ip =~ /:$/ and $ip !~ s/::$/:/;
    my @nums = split /:/, $ip, -1;
    return unless @nums <= 8;
    my ($empty, $ipv4, $str) = (0,'','');
    for (@nums) {
        return if $ipv4;
        $str .= "0" x (4-length) . $_, next if /^[a-fA-F\d]{1,4}$/;
        do { return if $empty++ }, $str .= "X", next if $_ eq '';
        next if $ipv4 = _pack_ipv4($_);
        return;
=======

sub _pack_ipv6 {
    my $ip = shift;
    $ip =~ s/\A::\z/::0/;
    return if $ip =~ /\A:/ and $ip !~ s/\A::/:/;
    return if $ip =~ /:\z/ and $ip !~ s/::\z/:/;
    my @nums = split /:/, $ip, -1;
    return unless @nums <= 8;
    my ($empty, $ipv4, $str) = (0,'','');
    for (@nums) {
        return if $ipv4;
        $str .= "0" x (4-length) . $_, next if /\A[a-fA-F0-9]{1,4}\z/;
        do { return if $empty++ }, $str .= "X", next if $_ eq '';
        next if $ipv4 = _pack_ipv4($_);
        return;
>>>>>>> REPLACE


[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 one or more SEARCH/REPLACE blocks. Follow these rules exactly:
1. Each block is:
<<<<<<< SEARCH
<exact lines copied verbatim from the shown source window>
=======
<the replacement lines>
>>>>>>> REPLACE
2. The SEARCH text MUST appear verbatim in the shown source window — copy it exactly, including whitespace; do not invent or paraphrase it.
3. Change as few lines as possible; keep the SEARCH span tight around the edit.
4. Modify ONLY code visible in the shown source window.
5. Output only the SEARCH/REPLACE block(s) with no other text.
6. Prefer folding a new bound or check into an existing condition over adding a separate guard, when the upstream fix does so.

[User]
# CVE
CVE-2026-45191: Improper input validation (CWE-20) in the Perl module Net::CIDR::Lite. When adding a network, the prefix-length portion after the slash was accepted as long as it consisted only of digits, with no rejection of a leading zero. A prefix length written with a leading zero, such as the 08 in 10.0.0.0/08 or the 00 in ::/00, was therefore accepted and read as its plain decimal value, whereas a strict reader treats a zero-padded number as malformed. A CIDR allow-list or deny-list built from attacker-influenced input consequently parses to a different prefix length than the author intended, an allow/deny-list inconsistency. Affects Net::CIDR::Lite before 0.24.

# Vulnerable source (Lite.pm)
```perl
    $self->add_any($_) for @_;
    $self;
}

sub add_any {
    my $self = shift;
    for (@_) {
        tr|/|| && do { $self->add($_); next };
        tr|-|| && do { $self->add_range($_); next };
        UNIVERSAL::isa($_, 'Net::CIDR::Lite') && do {
            $self->add_cidr($_); next
        };
        $self->add_ip($_), next;
    }
    $self;
}

sub add {
    my $self = shift;
    my ($ip, $mask) = split "/", shift;
    $self->_init($ip) || confess "Can't determine ip format" unless %$self;
    confess "Bad mask $mask"
        unless $mask =~ /\A[0-9]+\z/ and $mask <= $self->{NBITS}-8;
    $mask += 8;
    my $start = $self->{PACK}->($ip) & $self->{MASKS}[$mask]
        or confess "Bad ip address: $ip";
    my $end = $self->_add_bit($start, $mask);
    ++$$self{RANGES}{$start} || delete $$self{RANGES}{$start};
    --$$self{RANGES}{$end}   || delete $$self{RANGES}{$end};
    $self;
}

sub clean {
    my $self = shift;
    return $self unless $self->{RANGES};
    my $ranges = $$self{RANGES};
    my $total;
    $$self{RANGES} = {
      map { $total ? ($total+=$$ranges{$_})? () : ($_=>-1)
                   : do { $total+=$$ranges{$_}; ($_=>1) }
```

[Assistant]
<<<<<<< SEARCH
    my ($ip, $mask) = split "/", shift;
    $self->_init($ip) || confess "Can't determine ip format" unless %$self;
    confess "Bad mask $mask"
        unless $mask =~ /\A[0-9]+\z/ and $mask <= $self->{NBITS}-8;
    $mask += 8;
    my $start = $self->{PACK}->($ip) & $self->{MASKS}[$mask]
        or confess "Bad ip address: $ip";
=======
    my ($ip, $mask) = split "/", shift;
    $self->_init($ip) || confess "Can't determine ip format" unless %$self;
    confess "Bad mask $mask"
        unless defined $mask
        and $mask =~ /\A(?:0|[1-9][0-9]*)\z/
        and $mask <= $self->{NBITS}-8;
    $mask += 8;
    my $start = $self->{PACK}->($ip) & $self->{MASKS}[$mask]
        or confess "Bad ip address: $ip";
>>>>>>> REPLACE


[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 one or more SEARCH/REPLACE blocks. Follow these rules exactly:
1. Each block is:
<<<<<<< SEARCH
<exact lines copied verbatim from the shown source window>
=======
<the replacement lines>
>>>>>>> REPLACE
2. The SEARCH text MUST appear verbatim in the shown source window — copy it exactly, including whitespace; do not invent or paraphrase it.
3. Change as few lines as possible; keep the SEARCH span tight around the edit.
4. Modify ONLY code visible in the shown source window.
5. Output only the SEARCH/REPLACE block(s) with no other text.
6. Prefer folding a new bound or check into an existing condition over adding a separate guard, when the upstream fix does so.

[User]
# CVE
CVE-2026-50593: Integer underflow and resultant out-of-bounds read (CWE-191/CWE-125) in Graphite (libgraphite2) before 1.3.15. graphite2 compiles and validates a font's Graphite 'silf' passes by running the VM at face-load time, so a crafted font (tests/fonts/underflow.ttf in the upstream regression suite) whose bytecode drives the offset out of range reads past the slot map. Reproduce: shape the text 'baaaaaab' against underflow.ttf via the public API (gr_make_file_face + gr_make_seg).

# Vulnerable source (src/inc/opcodes.h)
```c
//        seg       = A reference to the Segment this code is running over.
//        is        = The current slot index
//        isb       = The original base slot index at the start of this rule
//        isf       = The first positioned slot
//        isl       = The last positioned slot
//        ip        = The current instruction pointer
//        endPos    = Position of advance of last cluster
//        dir       = writing system directionality of the font

// #define NOT_IMPLEMENTED     assert(false)
// #define NOT_IMPLEMENTED

#define binop(op)           const uint32 a = pop(); *sp = uint32(*sp) op a
#define sbinop(op)          const int32 a = pop(); *sp = int32(*sp) op a
#define use_params(n)       dp += n

#define declare_params(n)   const byte * param = dp; \
                            use_params(n);

#define push(n)             { *++sp = n; }
#define pop()               (*sp--)
#define slotat(x)           (map[(x)])
#define DIE                 { is=seg.last(); status = Machine::died_early; EXIT(1); }
#define POSITIONED          1

STARTOP(nop)
    do {} while (0);
ENDOP

STARTOP(push_byte)
    declare_params(1);
    push(int8(*param));
ENDOP

STARTOP(push_byte_u)
    declare_params(1);
    push(uint8(*param));
ENDOP

```

[Assistant]
<<<<<<< SEARCH

#define push(n)             { *++sp = n; }
#define pop()               (*sp--)
#define slotat(x)           (map[(x)])
#define DIE                 { is=seg.last(); status = Machine::died_early; EXIT(1); }
#define POSITIONED          1
=======

#define push(n)             { *++sp = n; }
#define pop()               (*sp--)
#define slotat(x)           ((map + (x) >= &smap[-1] && map + (x) < smap.end()) ? \
                                map[(x)] : (status = Machine::slot_offset_out_bounds, nullptr))
#define DIE                 { is=seg.last(); status = Machine::died_early; EXIT(1); }
#define POSITIONED          1
>>>>>>> REPLACE


[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 one or more SEARCH/REPLACE blocks. Follow these rules exactly:
1. Each block is:
<<<<<<< SEARCH
<exact lines copied verbatim from the shown source window>
=======
<the replacement lines>
>>>>>>> REPLACE
2. The SEARCH text MUST appear verbatim in the shown source window — copy it exactly, including whitespace; do not invent or paraphrase it.
3. Change as few lines as possible; keep the SEARCH span tight around the edit.
4. Modify ONLY code visible in the shown source window.
5. Output only the SEARCH/REPLACE block(s) with no other text.
6. Prefer folding a new bound or check into an existing condition over adding a separate guard, when the upstream fix does so.

[User]
# CVE
CVE-2026-6507: One-byte buffer overflow in dnsmasq 2.92: the DHCPv4 relay reply handler in rfc2131.c uses an off-by-one size when zeroing a DHCP option field, potentially writing one byte beyond the buffer boundary during relay processing.

# Vulnerable source (src/rfc2131.c)
```c
  struct dhcp_relay *relay;

  if (mess->giaddr.s_addr == 0 || mess->op != BOOTREPLY)
    return 0;

  for (relay = daemon->relay4; relay; relay = relay->next)
    {
      unsigned int return_iface = 0;

      if (relay->split_mode)
	{
	  unsigned char *opt, *sopt;

	  /* giaddr is our address on the returning interface in split mode. */
	  if (mess->giaddr.s_addr == relay->uplink.addr4.s_addr &&
	      (opt = option_find(mess, sz, OPTION_AGENT_ID, 1)))
	    {
	      if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_REMOTE_ID, sizeof(unsigned int))))
		return_iface = option_uint(sopt, 0, sizeof(unsigned int));

	      /* delete agent info before return RFC 3046 para 2.1 */
	      *opt = OPTION_END;
	      memset(opt + 1, 0, option_len(opt) + 2);
	    }
	}
      else if (mess->giaddr.s_addr == relay->local.addr4.s_addr)
	return_iface = relay->iface_index;

      if (return_iface && (!relay->interface || wildcard_match(relay->interface, arrival_interface)))
	return return_iface;
    }

  return 0;
}

#endif /* HAVE_DHCP */
```

[Assistant]
<<<<<<< SEARCH

	      /* delete agent info before return RFC 3046 para 2.1 */
	      *opt = OPTION_END;
	      memset(opt + 1, 0, option_len(opt) + 2);
	    }
	}
      else if (mess->giaddr.s_addr == relay->local.addr4.s_addr)
=======

	      /* delete agent info before return RFC 3046 para 2.1 */
	      *opt = OPTION_END;
	      memset(opt + 1, 0, option_len(opt) + 1);
	    }
	}
      else if (mess->giaddr.s_addr == relay->local.addr4.s_addr)
>>>>>>> REPLACE


[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 one or more SEARCH/REPLACE blocks. Follow these rules exactly:
1. Each block is:
<<<<<<< SEARCH
<exact lines copied verbatim from the shown source window>
=======
<the replacement lines>
>>>>>>> REPLACE
2. The SEARCH text MUST appear verbatim in the shown source window — copy it exactly, including whitespace; do not invent or paraphrase it.
3. Change as few lines as possible; keep the SEARCH span tight around the edit.
4. Modify ONLY code visible in the shown source window.
5. Output only the SEARCH/REPLACE block(s) with no other text.
6. Prefer folding a new bound or check into an existing condition over adding a separate guard, when the upstream fix does so.

[User]
# CVE
CVE-2026-7598: Integer overflow (CWE-190) in libssh2 1.11.1 leading to heap-buffer-overflow. Then _libssh2_store_str() calls _libssh2_htonu32 which writes a 4-byte length prefix past the 1-byte buffer (heap-buffer-overflow). The overflow occurs during local packet construction before any network I/O, making it triggerable from the public libssh2_userauth_list() / libssh2_userauth_password() APIs without a live SSH connection.

# Vulnerable source (src/userauth.c)
```c
 * Will yield successful login if "none" happens to be allowable for this user
 * Not a common configuration for any SSH server though
 * username should be NULL, or a null terminated string
 */
static char *userauth_list(LIBSSH2_SESSION *session, const char *username,
                           unsigned int username_len)
{
    unsigned char reply_codes[4] =
        { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE,
          SSH_MSG_USERAUTH_BANNER, 0 };
    /* packet_type(1) + username_len(4) + service_len(4) +
       service(14)"ssh-connection" + method_len(4) = 27 */
    unsigned long methods_len;
    unsigned int banner_len;
    unsigned char *s;
    int rc;

    if(session->userauth_list_state == libssh2_NB_state_idle) {
        /* Zero the whole thing out */
        memset(&session->userauth_list_packet_requirev_state, 0,
               sizeof(session->userauth_list_packet_requirev_state));

        session->userauth_list_data_len = username_len + 27;

        if(session->userauth_list_data) {
            LIBSSH2_FREE(session, session->userauth_list_data);
        }

        s = session->userauth_list_data =
            LIBSSH2_ALLOC(session, session->userauth_list_data_len);
        if(!session->userauth_list_data) {
            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
                           "Unable to allocate memory for userauth_list");
            return NULL;
        }

        *(s++) = SSH_MSG_USERAUTH_REQUEST;
        _libssh2_store_str(&s, username, username_len);
        _libssh2_store_str(&s, "ssh-connection", 14);
        _libssh2_store_u32(&s, 4); /* send "none" separately */
        /* ... */
                  const char *username, unsigned int username_len,
                  const unsigned char *password, unsigned int password_len,
                  LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb)))
{
    unsigned char *s;
    static const unsigned char reply_codes[4] = {
        SSH_MSG_USERAUTH_SUCCESS,
        SSH_MSG_USERAUTH_FAILURE,
        SSH_MSG_USERAUTH_PASSWD_CHANGEREQ,
        0
    };
    int rc;

    if(session->userauth_pswd_state == libssh2_NB_state_idle) {
        /* Zero the whole thing out */
        memset(&session->userauth_pswd_packet_requirev_state, 0,
               sizeof(session->userauth_pswd_packet_requirev_state));

        /*
         * 40 = packet_type(1) + username_len(4) + service_len(4) +
         * service(14)"ssh-connection" + method_len(4) + method(8)"password" +
         * chgpwdbool(1) + password_len(4) */
        session->userauth_pswd_data_len = username_len + 40;

        session->userauth_pswd_data0 =
            (unsigned char) ~SSH_MSG_USERAUTH_PASSWD_CHANGEREQ;

        /* TODO: remove this alloc with a fixed buffer in the session
           struct */
        s = session->userauth_pswd_data =
            LIBSSH2_ALLOC(session, session->userauth_pswd_data_len);
        if(!session->userauth_pswd_data) {
            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
                                  "Unable to allocate memory for "
                                  "userauth-password request");
        }

        *(s++) = SSH_MSG_USERAUTH_REQUEST;
        _libssh2_store_str(&s, username, username_len);
        _libssh2_store_str(&s, "ssh-connection", sizeof("ssh-connection") - 1);
        /* ... */
                (session->userauth_pswd_state == libssh2_NB_state_sent2)) {
                if(session->userauth_pswd_state == libssh2_NB_state_sent1) {
                    _libssh2_debug((session, LIBSSH2_TRACE_AUTH,
                                   "Password change required"));
                    LIBSSH2_FREE(session, session->userauth_pswd_data);
                    session->userauth_pswd_data = NULL;
                }
                if(passwd_change_cb) {
                    if(session->userauth_pswd_state ==
                       libssh2_NB_state_sent1) {
                        passwd_change_cb(session,
                                         &session->userauth_pswd_newpw,
                                         &session->userauth_pswd_newpw_len,
                                         &session->abstract);
                        if(!session->userauth_pswd_newpw) {
                            return _libssh2_error(session,
                                                LIBSSH2_ERROR_PASSWORD_EXPIRED,
                                                  "Password expired, and "
                                                  "callback failed");
                        }

                        /* basic data_len + newpw_len(4) */
                        if(username_len + password_len + 44 <= UINT_MAX) {
                            session->userauth_pswd_data_len =
                                username_len + password_len + 44;
                            s = session->userauth_pswd_data =
                                LIBSSH2_ALLOC(session,
                                              session->userauth_pswd_data_len);
                        }
                        else {
                            s = session->userauth_pswd_data = NULL;
                            session->userauth_pswd_data_len = 0;
                        }

                        if(!session->userauth_pswd_data) {
                            LIBSSH2_FREE(session,
                                         session->userauth_pswd_newpw);
                            session->userauth_pswd_newpw = NULL;
                            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
                                                  "Unable to allocate memory "
```

[Assistant]
<<<<<<< SEARCH
        memset(&session->userauth_list_packet_requirev_state, 0,
               sizeof(session->userauth_list_packet_requirev_state));

        session->userauth_list_data_len = username_len + 27;

        if(session->userauth_list_data) {
=======
        memset(&session->userauth_list_packet_requirev_state, 0,
               sizeof(session->userauth_list_packet_requirev_state));

        if(username_len > UINT32_MAX - 27) {
            _libssh2_error(session, LIBSSH2_ERROR_PROTO,
                           "username_len out of bounds");
            return NULL;
        }

        session->userauth_list_data_len = username_len + 27;

        if(session->userauth_list_data) {
>>>>>>> REPLACE
<<<<<<< SEARCH
         * 40 = packet_type(1) + username_len(4) + service_len(4) +
         * service(14)"ssh-connection" + method_len(4) + method(8)"password" +
         * chgpwdbool(1) + password_len(4) */
        session->userauth_pswd_data_len = username_len + 40;

        session->userauth_pswd_data0 =
=======
         * 40 = packet_type(1) + username_len(4) + service_len(4) +
         * service(14)"ssh-connection" + method_len(4) + method(8)"password" +
         * chgpwdbool(1) + password_len(4) */
        if(username_len > UINT32_MAX - 40) {
            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
                                  "username_len out of bounds");
        }

        session->userauth_pswd_data_len = username_len + 40;

        session->userauth_pswd_data0 =
>>>>>>> REPLACE
<<<<<<< SEARCH
                        }

                        /* basic data_len + newpw_len(4) */
                        if(username_len + password_len + 44 <= UINT_MAX) {
                            session->userauth_pswd_data_len =
                                username_len + password_len + 44;
                            s = session->userauth_pswd_data =
=======
                        }

                        /* basic data_len + newpw_len(4) */
                        if(username_len <= UINT32_MAX - password_len - 44) {
                            session->userauth_pswd_data_len =
                                username_len + password_len + 44;
                            s = session->userauth_pswd_data =
>>>>>>> REPLACE