[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-2025-7424: libxslt 1.1.43 and earlier is vulnerable to CVE-2025-7424, a type confusion that can lead to heap corruption. The psvi memory field is shared between stylesheet and input data without proper type tracking, causing confusion during XSLT transformations when the library attempts to read data stored by one code path using assumptions from another. An attacker can exploit this by crafting a malicious XSL stylesheet to corrupt memory and potentially execute arbitrary code.

# Vulnerable source (libxslt/xsltutils.h)
```c

/*
 * Output, reuse libxml I/O buffers.
 */
XSLTPUBFUN int XSLTCALL
		xsltSaveResultTo		(xmlOutputBufferPtr buf,
						 xmlDocPtr result,
						 xsltStylesheetPtr style);
XSLTPUBFUN int XSLTCALL
		xsltSaveResultToFilename	(const char *URI,
						 xmlDocPtr result,
						 xsltStylesheetPtr style,
						 int compression);
XSLTPUBFUN int XSLTCALL
		xsltSaveResultToFile		(FILE *file,
						 xmlDocPtr result,
						 xsltStylesheetPtr style);
XSLTPUBFUN int XSLTCALL
		xsltSaveResultToFd		(int fd,
						 xmlDocPtr result,
						 xsltStylesheetPtr style);
XSLTPUBFUN int XSLTCALL
		xsltSaveResultToString          (xmlChar **doc_txt_ptr,
                                                 int * doc_txt_len,
                                                 xmlDocPtr result,
                                                 xsltStylesheetPtr style);

/*
 * XPath interface
 */
XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL
		xsltXPathCompile		(xsltStylesheetPtr style,
						 const xmlChar *str);
XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL
		xsltXPathCompileFlags		(xsltStylesheetPtr style,
						 const xmlChar *str,
						 int flags);

#ifdef IN_LIBXSLT
/** DOC_DISABLE */
#define XSLT_SOURCE_NODE_MASK       15u
#define XSLT_SOURCE_NODE_HAS_KEY    1u
#define XSLT_SOURCE_NODE_HAS_ID     2u
int
xsltGetSourceNodeFlags(xmlNodePtr node);
int
xsltSetSourceNodeFlags(xsltTransformContextPtr ctxt, xmlNodePtr node,
                       int flags);
int
xsltClearSourceNodeFlags(xmlNodePtr node, int flags);
void **
xsltGetPSVIPtr(xmlNodePtr cur);
/** DOC_ENABLE */
#endif

#ifdef WITH_PROFILER
/*
 * Profiling.
 */
XSLTPUBFUN void XSLTCALL
		xsltSaveProfiling		(xsltTransformContextPtr ctxt,
						 FILE *output);
XSLTPUBFUN xmlDocPtr XSLTCALL
		xsltGetProfileInformation	(xsltTransformContextPtr ctxt);

XSLTPUBFUN long XSLTCALL
		xsltTimestamp			(void);
XSLTPUBFUN void XSLTCALL
		xsltCalibrateAdjust		(long delta);
#endif

/**
 * XSLT_TIMESTAMP_TICS_PER_SEC:
 *
 * Sampling precision for profiling
 */
#define XSLT_TIMESTAMP_TICS_PER_SEC 100000l

/*
 * Hooks for the debugger.
 */

typedef enum {
    XSLT_DEBUG_NONE = 0, /* no debugging allowed */
    XSLT_DEBUG_INIT,
    XSLT_DEBUG_STEP,
    XSLT_DEBUG_STEPOUT,
    XSLT_DEBUG_NEXT,
    XSLT_DEBUG_STOP,
    XSLT_DEBUG_CONT,
    XSLT_DEBUG_RUN,
    XSLT_DEBUG_RUN_RESTART,
    XSLT_DEBUG_QUIT
```

[Assistant]
<<<<<<< SEARCH
#define XSLT_SOURCE_NODE_MASK       15u
#define XSLT_SOURCE_NODE_HAS_KEY    1u
#define XSLT_SOURCE_NODE_HAS_ID     2u
int
xsltGetSourceNodeFlags(xmlNodePtr node);
int
=======
#define XSLT_SOURCE_NODE_MASK       15u
#define XSLT_SOURCE_NODE_HAS_KEY    1u
#define XSLT_SOURCE_NODE_HAS_ID     2u
#define XSLT_SOURCE_NODE_SHIFT_16   12u
#define XSLT_SOURCE_NODE_SHIFT_32   28u
#define XSLT_SOURCE_NODE_VALUE_MASK ((1 << XSLT_SOURCE_NODE_SHIFT_32) - 1)
#define XSLT_SOURCE_NODE_VALUE_MAX  XSLT_SOURCE_NODE_VALUE_MASK
int
xsltGetSourceNodeFlags(xmlNodePtr node);
int
>>>>>>> REPLACE
<<<<<<< SEARCH
                       int flags);
int
xsltClearSourceNodeFlags(xmlNodePtr node, int flags);
void **
xsltGetPSVIPtr(xmlNodePtr cur);
/** DOC_ENABLE */
=======
                       int flags);
int
xsltClearSourceNodeFlags(xmlNodePtr node, int flags);
int
xsltSetSourceNodeValue(xmlNodePtr node, int value);
int
xsltGetSourceNodeValue(xmlNodePtr node);
void **
xsltGetPSVIPtr(xmlNodePtr cur);
/** DOC_ENABLE */
>>>>>>> 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-0989: Stack overflow via unbounded recursion when parsing a RelaxNG schema in libxml2 2.13.9 (CWE-674, uncontrolled recursion / denial of service). A crafted .rng schema whose definitions reference other sub-schemas in a deeply nested chain makes the parser recurse without any depth bound while resolving each referenced sub-grammar, exhausting the call stack. Triggered by schema input alone during validation setup; no network or special privileges are required.

# Vulnerable source (relaxng.c, include/libxml/relaxng.h)
```c
/* ==== file: relaxng.c ==== */
 *
 * Author: Daniel Veillard
 */

/**
 * TODO:
 * - add support for DTD compatibility spec
 *   http://www.oasis-open.org/committees/relax-ng/compatibility-20011203.html
 * - report better mem allocations pbms at runtime and abort immediately.
 */

#define IN_LIBXML
#include "libxml.h"

#ifdef LIBXML_RELAXNG_ENABLED

#include <string.h>
#include <stdio.h>
#include <stddef.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/parserInternals.h>
#include <libxml/hash.h>
#include <libxml/uri.h>

#include <libxml/relaxng.h>

#include <libxml/xmlautomata.h>
#include <libxml/xmlregexp.h>
#include <libxml/xmlschemastypes.h>

#include "private/error.h"
#include "private/regexp.h"
#include "private/string.h"
#include "private/threads.h"

/*
 * The Relax-NG namespace
 */
static const xmlChar *xmlRelaxNGNs = (const xmlChar *)
    "http://relaxng.org/ns/structure/1.0";

#define IS_RELAXNG(node, typ)						\
   ((node != NULL) && (node->ns != NULL) &&				\
    (node->type == XML_ELEMENT_NODE) &&					\
    (xmlStrEqual(node->name, (const xmlChar *) typ)) &&		\
    (xmlStrEqual(node->ns->href, xmlRelaxNGNs)))

#define MAX_ERROR 5

typedef struct _xmlRelaxNGSchema xmlRelaxNGSchema;
typedef xmlRelaxNGSchema *xmlRelaxNGSchemaPtr;

        /* ... */
    xmlRelaxNGDefinePtr *defTab;        /* pointer to the allocated definitions */

    const char *buffer;
    int size;

    /* the document stack */
    xmlRelaxNGDocumentPtr doc;  /* Current parsed external ref */
    int docNr;                  /* Depth of the parsing stack */
    int docMax;                 /* Max depth of the parsing stack */
    xmlRelaxNGDocumentPtr *docTab;      /* array of docs */

    /* the include stack */
    xmlRelaxNGIncludePtr inc;   /* Current parsed include */
    int incNr;                  /* Depth of the include parsing stack */
    int incMax;                 /* Max depth of the parsing stack */
    xmlRelaxNGIncludePtr *incTab;       /* array of incs */

    int idref;                  /* requires idref checking */

    /* used to compile content models */
    xmlAutomataPtr am;          /* the automata */
    xmlAutomataStatePtr state;  /* used to build the automata */

    int crng;			/* compact syntax and other flags */
    int freedoc;		/* need to free the document */

    xmlResourceLoader resourceLoader;
    void *resourceCtxt;
        /* ... */
int
xmlRelaxParserSetFlag(xmlRelaxNGParserCtxt *ctxt, int flags)
{
    if (ctxt == NULL) return(-1);
    if (flags & XML_RELAXNGP_FREE_DOC) {
        ctxt->crng |= XML_RELAXNGP_FREE_DOC;
	flags -= XML_RELAXNGP_FREE_DOC;
    }
    if (flags & XML_RELAXNGP_CRNG) {
        ctxt->crng |= XML_RELAXNGP_CRNG;
	flags -= XML_RELAXNGP_CRNG;
    }
    if (flags != 0) return(-1);
    return(0);
}

/************************************************************************
 *									*
 *			Document functions				*
 *									*
 ************************************************************************/
static xmlDocPtr xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt,
                                      xmlDocPtr doc);

static xmlDoc *
xmlRelaxReadFile(xmlRelaxNGParserCtxtPtr ctxt, const char *filename) {
    xmlParserCtxtPtr pctxt;
    xmlDocPtr doc;
        /* ... */
    if (ctxt->serror != NULL)
        xmlCtxtSetErrorHandler(pctxt, ctxt->serror, ctxt->userData);
    if (ctxt->resourceLoader != NULL)
        xmlCtxtSetResourceLoader(pctxt, ctxt->resourceLoader,
                                 ctxt->resourceCtxt);
    doc = xmlCtxtReadMemory(pctxt, buf, size, NULL, NULL, 0);
    xmlFreeParserCtxt(pctxt);

    return(doc);
}

/**
 * Pushes a new include on top of the include stack
 *
 * @param ctxt  the parser context
 * @param value  the element doc
 * @returns 0 in case of error, the index in the stack otherwise
 */
static int
xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
                      xmlRelaxNGIncludePtr value)
{
    if (ctxt->incTab == NULL) {
        ctxt->incMax = 4;
        ctxt->incNr = 0;
        ctxt->incTab =
            (xmlRelaxNGIncludePtr *) xmlMalloc(ctxt->incMax *
                                               sizeof(ctxt->incTab[0]));
        if (ctxt->incTab == NULL) {
            xmlRngPErrMemory(ctxt);
            return (0);
        }
    }
    if (ctxt->incNr >= ctxt->incMax) {
        ctxt->incMax *= 2;
        ctxt->incTab =
            (xmlRelaxNGIncludePtr *) xmlRealloc(ctxt->incTab,
                                                ctxt->incMax *
                                                sizeof(ctxt->incTab[0]));
        if (ctxt->incTab == NULL) {
            xmlRngPErrMemory(ctxt);
            return (0);
        }
    }
    ctxt->incTab[ctxt->incNr] = value;
    ctxt->inc = value;
    return (ctxt->incNr++);
}

/**
 * Pops the top include from the include stack
 *
 * @param ctxt  the parser context
        /* ... */

    /*
     * transmit the ns if needed
     */
    if (ns != NULL) {
        root = xmlDocGetRootElement(doc);
        if (root != NULL) {
            if (xmlHasProp(root, BAD_CAST "ns") == NULL) {
                xmlSetProp(root, BAD_CAST "ns", ns);
            }
        }
    }

    /*
     * push it on the stack
     */
    xmlRelaxNGIncludePush(ctxt, ret);

    /*
     * Some preprocessing of the document content, this include recursing
     * in the include stack.
     */

    doc = xmlRelaxNGCleanupDoc(ctxt, doc);
    if (doc == NULL) {
        ctxt->inc = NULL;
        return (NULL);
    }
        /* ... */

/**
 * parse a schema definition resource and build an internal
 * XML Schema structure which can be used to validate instances.
 *
 * @param ctxt  a Relax-NG parser context
 * @returns the internal XML RelaxNG structure built from the resource or
 *         NULL in case of error
 */
xmlRelaxNG *
xmlRelaxNGParse(xmlRelaxNGParserCtxt *ctxt)
{
    xmlRelaxNGPtr ret = NULL;
    xmlDocPtr doc;
    xmlNodePtr root;

    xmlRelaxNGInitTypes();

    if (ctxt == NULL)
        return (NULL);

    /*
     * First step is to parse the input document into an DOM/Infoset
     */
    if (ctxt->URL != NULL) {
        doc = xmlRelaxReadFile(ctxt, (const char *) ctxt->URL);
        if (doc == NULL) {
            xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,

/* ==== file: include/libxml/relaxng.h ==== */

/*
 * Interfaces for parsing.
 */
XMLPUBFUN xmlRelaxNGParserCtxt *
		    xmlRelaxNGNewParserCtxt	(const char *URL);
XMLPUBFUN xmlRelaxNGParserCtxt *
		    xmlRelaxNGNewMemParserCtxt	(const char *buffer,
						 int size);
XMLPUBFUN xmlRelaxNGParserCtxt *
		    xmlRelaxNGNewDocParserCtxt	(xmlDoc *doc);

XMLPUBFUN int
		    xmlRelaxParserSetFlag	(xmlRelaxNGParserCtxt *ctxt,
						 int flag);

XMLPUBFUN void
		    xmlRelaxNGFreeParserCtxt	(xmlRelaxNGParserCtxt *ctxt);
XMLPUBFUN void
		    xmlRelaxNGSetParserErrors(xmlRelaxNGParserCtxt *ctxt,
					 xmlRelaxNGValidityErrorFunc err,
					 xmlRelaxNGValidityWarningFunc warn,
					 void *ctx);
XMLPUBFUN int
		    xmlRelaxNGGetParserErrors(xmlRelaxNGParserCtxt *ctxt,
					 xmlRelaxNGValidityErrorFunc *err,
					 xmlRelaxNGValidityWarningFunc *warn,
					 void **ctx);
```

[Assistant]
<<<<<<< SEARCH
		    xmlRelaxParserSetFlag	(xmlRelaxNGParserCtxt *ctxt,
						 int flag);

XMLPUBFUN void
		    xmlRelaxNGFreeParserCtxt	(xmlRelaxNGParserCtxt *ctxt);
XMLPUBFUN void
=======
		    xmlRelaxParserSetFlag	(xmlRelaxNGParserCtxt *ctxt,
						 int flag);

XMLPUBFUN int
		    xmlRelaxParserSetIncLImit	(xmlRelaxNGParserCtxt *ctxt,
						 int limit);

XMLPUBFUN void
		    xmlRelaxNGFreeParserCtxt	(xmlRelaxNGParserCtxt *ctxt);
XMLPUBFUN void
>>>>>>> REPLACE
<<<<<<< SEARCH

#ifdef LIBXML_RELAXNG_ENABLED

#include <string.h>
#include <stdio.h>
#include <stddef.h>
=======

#ifdef LIBXML_RELAXNG_ENABLED

#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stddef.h>
>>>>>>> REPLACE
<<<<<<< SEARCH
static const xmlChar *xmlRelaxNGNs = (const xmlChar *)
    "http://relaxng.org/ns/structure/1.0";

#define IS_RELAXNG(node, typ)						\
   ((node != NULL) && (node->ns != NULL) &&				\
    (node->type == XML_ELEMENT_NODE) &&					\
=======
static const xmlChar *xmlRelaxNGNs = (const xmlChar *)
    "http://relaxng.org/ns/structure/1.0";

/*
 * Default include limit, this can be override with RNG_INCLUDE_LIMIT
 * env variable
 */
static const int _xmlRelaxNGIncludeLimit = 1000;

#define IS_RELAXNG(node, typ)						\
   ((node != NULL) && (node->ns != NULL) &&				\
    (node->type == XML_ELEMENT_NODE) &&					\
>>>>>>> REPLACE
<<<<<<< SEARCH
    int incNr;                  /* Depth of the include parsing stack */
    int incMax;                 /* Max depth of the parsing stack */
    xmlRelaxNGIncludePtr *incTab;       /* array of incs */

    int idref;                  /* requires idref checking */

=======
    int incNr;                  /* Depth of the include parsing stack */
    int incMax;                 /* Max depth of the parsing stack */
    xmlRelaxNGIncludePtr *incTab;       /* array of incs */
    int incLimit;               /* Include limit, to avoid stack-overflow on parse */

    int idref;                  /* requires idref checking */

>>>>>>> REPLACE
<<<<<<< SEARCH
    return(0);
}

/************************************************************************
 *									*
 *			Document functions				*
=======
    return(0);
}

/**
 * Semi private function used to set the include recursion limit to a
 * parser context. Set to 0 to use the default value.
 *
 * @param ctxt  a RelaxNG parser context
 * @param limit the new include depth limit
 * @returns 0 if success and -1 in case of error
 */
int
xmlRelaxParserSetIncLImit(xmlRelaxNGParserCtxt *ctxt, int limit)
{
    if (ctxt == NULL) return(-1);
    if (limit < 0) return(-1);
    ctxt->incLimit = limit;
    return(0);
}

/************************************************************************
 *									*
 *			Document functions				*
>>>>>>> REPLACE
<<<<<<< SEARCH
 *
 * @param ctxt  the parser context
 * @param value  the element doc
 * @returns 0 in case of error, the index in the stack otherwise
 */
static int
xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
=======
 *
 * @param ctxt  the parser context
 * @param value  the element doc
 * @returns -1 in case of error, the index in the stack otherwise
 */
static int
xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
>>>>>>> REPLACE
<<<<<<< SEARCH
                                               sizeof(ctxt->incTab[0]));
        if (ctxt->incTab == NULL) {
            xmlRngPErrMemory(ctxt);
            return (0);
        }
    }
    if (ctxt->incNr >= ctxt->incMax) {
        ctxt->incMax *= 2;
        ctxt->incTab =
=======
                                               sizeof(ctxt->incTab[0]));
        if (ctxt->incTab == NULL) {
            xmlRngPErrMemory(ctxt);
            return (-1);
        }
    }
    if (ctxt->incNr >= ctxt->incLimit) {
        xmlRngPErr(ctxt, (xmlNodePtr)value->doc, XML_RNGP_PARSE_ERROR,
                   "xmlRelaxNG: inclusion recursion limit reached\n", NULL, NULL);
        return(-1);
    }

    if (ctxt->incNr >= ctxt->incMax) {
        ctxt->incMax *= 2;
        ctxt->incTab =
>>>>>>> REPLACE
<<<<<<< SEARCH
                                                sizeof(ctxt->incTab[0]));
        if (ctxt->incTab == NULL) {
            xmlRngPErrMemory(ctxt);
            return (0);
        }
    }
    ctxt->incTab[ctxt->incNr] = value;
=======
                                                sizeof(ctxt->incTab[0]));
        if (ctxt->incTab == NULL) {
            xmlRngPErrMemory(ctxt);
            return (-1);
        }
    }
    ctxt->incTab[ctxt->incNr] = value;
>>>>>>> REPLACE
<<<<<<< SEARCH
    /*
     * push it on the stack
     */
    xmlRelaxNGIncludePush(ctxt, ret);

    /*
     * Some preprocessing of the document content, this include recursing
=======
    /*
     * push it on the stack
     */
    if (xmlRelaxNGIncludePush(ctxt, ret) < 0) {
        return (NULL);
    }

    /*
     * Some preprocessing of the document content, this include recursing
>>>>>>> REPLACE
<<<<<<< SEARCH
    xmlDocPtr doc;
    xmlNodePtr root;

    xmlRelaxNGInitTypes();

    if (ctxt == NULL)
        return (NULL);

    /*
     * First step is to parse the input document into an DOM/Infoset
     */
=======
    xmlDocPtr doc;
    xmlNodePtr root;

    const char *include_limit_env = getenv("RNG_INCLUDE_LIMIT");

    xmlRelaxNGInitTypes();

    if (ctxt == NULL)
        return (NULL);

    if (ctxt->incLimit == 0) {
        ctxt->incLimit = _xmlRelaxNGIncludeLimit;
        if (include_limit_env != NULL) {
            char *strEnd;
            unsigned long val = 0;
            errno = 0;
            val = strtoul(include_limit_env, &strEnd, 10);
            if (errno != 0 || *strEnd != 0 || val > INT_MAX) {
                xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
                           "xmlRelaxNGParse: invalid RNG_INCLUDE_LIMIT %s\n",
                           (const xmlChar*)include_limit_env,
                           NULL);
                return(NULL);
            }
            if (val)
                ctxt->incLimit = val;
        }
    }

    /*
     * First step is to parse the input document into an DOM/Infoset
     */
>>>>>>> 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-0992: Denial-of-service vulnerability (CWE-400) in libxml2 2.13.9 XML catalog processing. This causes O(n^2) growth in catalog lookup cost when the resulting list is traversed repeatedly, enabling an attacker who controls catalog file content to cause unbounded CPU or memory consumption.

# Vulnerable source (catalog.c)
```c
		BAD_CAST "rewritePrefix", prefer, cgroup);
    } else if (xmlStrEqual(cur->name, BAD_CAST "delegatePublic")) {
	entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_PUBLIC,
		BAD_CAST "delegatePublic", BAD_CAST "publicIdStartString",
		BAD_CAST "catalog", prefer, cgroup);
    } else if (xmlStrEqual(cur->name, BAD_CAST "delegateSystem")) {
	entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_SYSTEM,
		BAD_CAST "delegateSystem", BAD_CAST "systemIdStartString",
		BAD_CAST "catalog", prefer, cgroup);
    } else if (xmlStrEqual(cur->name, BAD_CAST "uri")) {
	entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_URI,
		BAD_CAST "uri", BAD_CAST "name",
		BAD_CAST "uri", prefer, cgroup);
    } else if (xmlStrEqual(cur->name, BAD_CAST "rewriteURI")) {
	entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_REWRITE_URI,
		BAD_CAST "rewriteURI", BAD_CAST "uriStartString",
		BAD_CAST "rewritePrefix", prefer, cgroup);
    } else if (xmlStrEqual(cur->name, BAD_CAST "delegateURI")) {
	entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_DELEGATE_URI,
		BAD_CAST "delegateURI", BAD_CAST "uriStartString",
		BAD_CAST "catalog", prefer, cgroup);
    } else if (xmlStrEqual(cur->name, BAD_CAST "nextCatalog")) {
	entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_NEXT_CATALOG,
		BAD_CAST "nextCatalog", NULL,
		BAD_CAST "catalog", prefer, cgroup);
    }
    if (entry != NULL) {
        if (parent != NULL) {
	    entry->parent = parent;
	    if (parent->children == NULL)
		parent->children = entry;
	    else {
		xmlCatalogEntryPtr prev;

		prev = parent->children;
		while (prev->next != NULL)
		    prev = prev->next;
		prev->next = entry;
	    }
	}
```

[Assistant]
<<<<<<< SEARCH
		BAD_CAST "delegateURI", BAD_CAST "uriStartString",
		BAD_CAST "catalog", prefer, cgroup);
    } else if (xmlStrEqual(cur->name, BAD_CAST "nextCatalog")) {
	entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_NEXT_CATALOG,
		BAD_CAST "nextCatalog", NULL,
		BAD_CAST "catalog", prefer, cgroup);
    }
    if (entry != NULL) {
        if (parent != NULL) {
=======
		BAD_CAST "delegateURI", BAD_CAST "uriStartString",
		BAD_CAST "catalog", prefer, cgroup);
    } else if (xmlStrEqual(cur->name, BAD_CAST "nextCatalog")) {
	xmlCatalogEntryPtr prev = parent->children;

	entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_NEXT_CATALOG,
		BAD_CAST "nextCatalog", NULL,
		BAD_CAST "catalog", prefer, cgroup);
	/* Avoid duplication of nextCatalog */
	while (prev != NULL) {
	    if ((prev->type == XML_CATA_NEXT_CATALOG) &&
		(xmlStrEqual (prev->URL, entry->URL)) &&
		(xmlStrEqual (prev->value, entry->value)) &&
		(prev->prefer == entry->prefer) &&
		(prev->group == entry->group)) {
		    if (xmlDebugCatalogs)
			xmlCatalogPrintDebug(
			    "Ignoring repeated nextCatalog %s\n", entry->URL);
		    xmlFreeCatalogEntry(entry, NULL);
		    entry = NULL;
		    break;
	    }
	    prev = prev->next;
	}
    }
    if (entry != NULL) {
        if (parent != NULL) {
>>>>>>> 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-10275: Buffer overflow (CWE-122) in OpenSC 0.27.1 pkcs11-tool.

# Vulnerable source (src/tools/pkcs11-tool.c)
```c
			if (strcmp(opt_uri->type, "cert") == 0) {
				opt_object_class = CKO_CERTIFICATE;
				opt_object_class_str = "cert";
			} else if (strcmp(opt_uri->type, "private") == 0) {
				opt_object_class = CKO_PRIVATE_KEY;
				opt_object_class_str = "privkey";
			} else if (strcmp(opt_uri->type, "secret-key") == 0) {
				opt_object_class = CKO_SECRET_KEY;
				opt_object_class_str = "secrkey";
			} else if (strcmp(opt_uri->type, "public") == 0) {
				opt_object_class = CKO_PUBLIC_KEY;
				opt_object_class_str = "pubkey,";
			} else if (strcmp(opt_uri->type, "data") == 0) {
				opt_object_class = CKO_DATA;
				opt_object_class_str = "data";
			} else {
				fprintf(stderr, "Unsupported object type \"%s\" specified in PKCS#11 URI\n", opt_uri->type);
				util_print_usage_and_die(app_name, options, option_help, NULL);
			}
		}
		if (opt_uri->id) {
			opt_object_id_len = opt_uri->id_len;
			memcpy(opt_object_id, opt_uri->id, opt_object_id_len);
		}
	}

	if (!opt_module) {
		opt_module = DEFAULT_PKCS11_PROVIDER;
	}
#ifdef _WIN32
	expanded_len = PATH_MAX;
	expanded_len = ExpandEnvironmentStringsA(opt_module, expanded_val, expanded_len);
	if (0 < expanded_len && expanded_len < sizeof expanded_val)
		opt_module = expanded_val;
#endif

#ifndef ENABLE_SHARED
	if (strcmp(opt_module, DEFAULT_PKCS11_PROVIDER) == 0)
		p11 = &pkcs11_function_list_3_0;
	else
        /* ... */
	f = fopen(opt_file_to_write, "rb");
	if (f == NULL)
		util_fatal("Couldn't open file \"%s\"", opt_file_to_write);
	fclose(f);

	/* Get for a not-yet-existing ID */
	while(find_object(session, CKO_PRIVATE_KEY, &priv_key, id, id_len, NULL, 0))
		id[0]++;

	printf("\n*** Generating a %s key pair ***\n", opt_key_type);

	if (!gen_keypair(slot, session, &pub_key, &priv_key, opt_key_type)) {
		printf("ERR: cannot generate new key pair\n");
		return session;
	}

	tmp = getID(session, priv_key, &i);
	if (i == 0) {
		fprintf(stderr, "ERR: newly generated private key has no (or an empty) CKA_ID\n");
		return session;
	}
	opt_object_id_len = (size_t) i;
	memcpy(opt_object_id, tmp, opt_object_id_len);

	/* This is done in NSS */
	getMODULUS(session, priv_key, &mod_len);
	if (mod_len < 5 || mod_len > 10000) { /* should be reasonable limits */
		fprintf(stderr, "ERR: GetAttribute(privkey, CKA_MODULUS) doesn't seem to work\n");
		return session;
	}

	printf("\n*** Changing the CKA_ID of private and public key into one of 20 bytes ***\n");

	rv = p11->C_SetAttributeValue(session, priv_key, attribs, 1);
	if (rv != CKR_OK)
		p11_fatal("C_SetAttributeValue(priv_key)", rv);

	rv = p11->C_SetAttributeValue(session, pub_key, attribs, 1);
	if (rv != CKR_OK)
		p11_fatal("C_SetAttributeValue(pub_key)", rv);
```

[Assistant]
<<<<<<< SEARCH
		}
		if (opt_uri->id) {
			opt_object_id_len = opt_uri->id_len;
			memcpy(opt_object_id, opt_uri->id, opt_object_id_len);
		}
	}
=======
		}
		if (opt_uri->id) {
			opt_object_id_len = opt_uri->id_len;
			if (opt_object_id_len > sizeof(opt_object_id))
				util_fatal("URI's object ID too long");
			memcpy(opt_object_id, opt_uri->id, opt_object_id_len);
		}
	}
>>>>>>> REPLACE
<<<<<<< SEARCH
		return session;
	}
	opt_object_id_len = (size_t) i;
	memcpy(opt_object_id, tmp, opt_object_id_len);

	/* This is done in NSS */
=======
		return session;
	}
	opt_object_id_len = (size_t) i;
	if (opt_object_id_len > sizeof(opt_object_id)) {
		fprintf(stderr, "ERR: object ID too long\n");
		return session;
	}
	memcpy(opt_object_id, tmp, opt_object_id_len);

	/* This is done in NSS */
>>>>>>> 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-11625: The Bytes::Random::Secure Perl module does not detect when a process has been forked. After a fork, the child process inherits the parent's pseudorandom number generator (PRNG) state and will produce the same sequence of bytes as the parent, breaking the cryptographic security guarantees the module is meant to provide. An attacker who can observe the output of both parent and child processes can recover the full PRNG state.

# Vulnerable source (lib/Bytes/Random/Secure.pm)
```perl
    }
  }
  return %args;
}

# Round bits parameter to nearest greater or equal 32-bit "long".
sub _round_bits_to_ge_32 {
  my( $self, $bits ) = @_;
  my $remainder = $bits % 32;
  return $bits if $remainder == 0;
  carp "Bits field must be a multiple of 32.  Rounding up.";
  return $bits + 32 - $remainder;
}

# Constrain bits argument to a reasonable range.
sub _constrain_bits {
  my( $self, $bits, $min, $max ) = @_;

  if( $bits < $min ) {
    carp "Bits field must be >= 64 (two longs). Rounding up.";
    $bits = $min;
  }
  elsif( $bits > $max ) {
    carp "Bits field must be <= 8192 (256 longs). Rounding down.";
    $bits = $max;
  }
  # No need for an 'else' here.

  return $bits;
}

# Build attributes set by new().  Any not explicitly set will use defaults
# as described in the constant OO_ATTRIBS.
sub _build_attributes {
    my ( $self, $args ) = @_;

    while ( my ( $arg, $default ) = each %{ OO_ATTRIBS() } ) {
      $self->{$arg} = exists $args->{$arg} ? $args->{$arg} : $default;
    }

    $self->{_RNG} = undef;    # Lazy initialization.
    return $self;
}

# Get a seed and use it to instantiate a RNG.
# Note: Currently we specify only Math::Random::ISAAC.  However, the PRNG
# object attribute may be used in the future to specify alternate RNG's.
sub _instantiate_rng {
    my $self = shift;

    my ( %seed_opts ) = $self->_build_seed_options;
    my @seeds = $self->_generate_seed( %seed_opts );
    $self->{_RNG} = Math::Random::ISAAC->new(@seeds);

    return $self->{_RNG};
}

# Set up seed options for Crypt::Random::Seed
sub _build_seed_options {
  my( $self ) = @_;

  my %crs_opts;

  # CRYPT_RANDOM_SEED_OPTS enumerates the options that Crypt::Random::Seed
  # supports.  We have already built object attributes for those options.
  foreach my $opt ( @{ CRYPT_RANDOM_SEED_OPTS() } ) {
      $crs_opts{$opt} = $self->{$opt} if defined $self->{$opt};
  }

  return %crs_opts;
}

# Use Crypt::Random::Seed to generate some high-quality long int
# seeds for Math::Random::ISAAC.
sub _generate_seed {
    my ( $self, %options_hash ) = @_;

    my $seed_size = $self->{Bits} / 32;
    my $source = Crypt::Random::Seed->new(%options_hash);

    croak 'Unable to obtain a strong seed source from Crypt::Random::Seed.'
      unless defined $source;

    return $source->random_values($seed_size); # List of unsigned longs.
}

# Validate that we are getting an integer >= 0.
# If not, throw an exception.
sub _validate_int {
  my( $self, $input ) = @_;
  croak "Byte count must be a positive integer."
    unless    looks_like_number( $input )
           && $input == int( $input )
           && $input >= 0;
  return 1;
}

# Random bytes string.
sub bytes {
  my( $self, $bytes ) = @_;
  $bytes = defined $bytes ? $bytes : 0; # Default to zero bytes.
  $self->_validate_int( $bytes ); # Throws on violation.

  $self->_instantiate_rng unless defined $self->{_RNG};

  my $str = '';

  while ( $bytes >= 4 ) {                  # Utilize irand()'s 32 bits.
    $str .= pack( "L", $self->{_RNG}->irand );
    $bytes -= 4;
  }

  if ( $bytes > 0 ) {
    my $rval = $self->{_RNG}->irand;

    $str .= pack( "S", ( $rval >> 8 ) & 0xFFFF )
      if $bytes >= 2;                    # 16 bits.
    $str .= pack( "C", $rval & 0xFF ) if $bytes % 2;    # 8 bits.

  }
  return $str;
}

# Base64 encoding of random byte string.
sub bytes_base64 {
  my ( $self, $bytes, $eol ) = @_;
  return encode_base64( $self->bytes($bytes), defined($eol) ? $eol : qq{\n} );
}

# Hex digits representing random byte string (No whitespace, no '0x').
sub bytes_hex {
  my ( $self, $bytes ) = @_;
  return unpack 'H*', $self->bytes($bytes);
}

# Quoted Printable representation of random byte string.
sub bytes_qp {
  my ( $self, $bytes, $eol ) = @_;
  return encode_qp $self->bytes($bytes), defined($eol) ? $eol : qq{\n}, 1;
}

sub string_from {
  my( $self, $bag, $bytes ) = @_;
  $bag   = defined $bag   ? $bag   : '';
  $bytes = defined $bytes ? $bytes : 0;
  my $range = length $bag;

  $self->_validate_int( $bytes );

  croak "Bag's size must be at least 1 character."
    if $range < 1;

  my $rand_bytes = q{};              # We need an empty (and defined) string.

  for my $random ( $self->_ranged_randoms( $range, $bytes ) ) {
      $rand_bytes .= substr( $bag, $random, 1 );
  }

  return $rand_bytes;
}

sub shuffle {
    my($self, $aref) = @_;
    croak 'Argument must be an array reference.' unless 'ARRAY' eq ref $aref;
    return $aref unless @$aref;
    for (my $i = @$aref; --$i;) {
        my $r = ($self->_ranged_randoms($i+1, 1))[0];
        ($aref->[$i],$aref->[$r]) = ($aref->[$r], $aref->[$i]);
    }
    return $aref;
}

# Helpers for string_from() and shuffle.

sub _ranged_randoms {
    my ( $self, $range, $count ) = @_;
    $count = defined $count ? $count : 0;

    # Lazily seed the RNG so we don't waste available strong entropy.
    $self->_instantiate_rng unless defined $self->{_RNG};

    my $divisor = $self->_closest_divisor($range);

    my @randoms;

    $#randoms = $count - 1;  # Pre-extend the @randoms array so 'push' avoids
                             # copy on resize.
    @randoms = ();           # Then purge it, but its memory won't be released.

    for my $n ( 1 .. $count ) {
        my $random;

        # The loop rolls, and re-rolls if the random number is out of the bag's
        # range.  This is to avoid a solution that would introduce modulo bias.
        do {
            $random = $self->{_RNG}->irand % $divisor;
        } while ( $random >= $range );

        push @randoms, $random;
    }

    return @randoms;
}

# Find nearest factor of 2**32 >= $range.

sub _closest_divisor {
    my ( $self, $range ) = @_;
    $range = defined $range ? $range : 0;

    croak "$range must be positive." if $range < 0;
    croak "$range exceeds irand max limit of 2**32." if $range > 2**32;

    my $n = 0;
    my $d;
    while ( $n <= 32 ) {
        $d = 2 ** $n++;
        last if $d >= $range;
    }

     return $d;
}

# irand, so that people who don't need "bytes" can enjoy B::R::S's convenience
# without jumping through "unpack" hoops. (A suggestion from Dana Jacobsen.)

sub irand {
  my( $self ) = @_;
  $self->_instantiate_rng unless defined $self->{_RNG};
  return $self->{_RNG}->irand;
}

################################################################################
##  Functions interface                                                       ##
################################################################################

# Instantiate our random number generator(s) inside of a lexical closure,
# limiting the scope of the RNG object so it can't be tampered with.

{
  my $RNG_object = undef;

  # Lazily, instantiate the RNG object, but only once.
  my $fetch_RNG = sub {
    $RNG_object = Bytes::Random::Secure->new( FUNC_STD )
      unless defined $RNG_object;
    return $RNG_object;
  };

  sub random_bytes {
    return $fetch_RNG->()->bytes( @_ );
  }

  sub random_string_from {
    return $fetch_RNG->()->string_from( @_ );
  }

}

# Base64 encoded random bytes functions

sub random_bytes_base64 {
  my ( $bytes, $eof ) = @_;
  return encode_base64 random_bytes($bytes), defined($eof) ? $eof : qq{\n};
}

```

[Assistant]
<<<<<<< SEARCH
      $self->{$arg} = exists $args->{$arg} ? $args->{$arg} : $default;
    }

    $self->{_RNG} = undef;    # Lazy initialization.
    return $self;
}
=======
      $self->{$arg} = exists $args->{$arg} ? $args->{$arg} : $default;
    }

    $self->{_pid} = $$;
    $self->{_RNG} = undef;    # Lazy initialization.
    return $self;
}
>>>>>>> REPLACE
<<<<<<< SEARCH
    my @seeds = $self->_generate_seed( %seed_opts );
    $self->{_RNG} = Math::Random::ISAAC->new(@seeds);

    return $self->{_RNG};
}

=======
    my @seeds = $self->_generate_seed( %seed_opts );
    $self->{_RNG} = Math::Random::ISAAC->new(@seeds);

    $self->{_pid} = $$;

    return $self->{_RNG};
}

>>>>>>> REPLACE
<<<<<<< SEARCH
  $bytes = defined $bytes ? $bytes : 0; # Default to zero bytes.
  $self->_validate_int( $bytes ); # Throws on violation.

  $self->_instantiate_rng unless defined $self->{_RNG};

  my $str = '';

=======
  $bytes = defined $bytes ? $bytes : 0; # Default to zero bytes.
  $self->_validate_int( $bytes ); # Throws on violation.

  $self->_instantiate_rng unless $$ == $self->{_pid} && defined $self->{_RNG};

  my $str = '';

>>>>>>> REPLACE
<<<<<<< SEARCH
    $count = defined $count ? $count : 0;

    # Lazily seed the RNG so we don't waste available strong entropy.
    $self->_instantiate_rng unless defined $self->{_RNG};

    my $divisor = $self->_closest_divisor($range);

=======
    $count = defined $count ? $count : 0;

    # Lazily seed the RNG so we don't waste available strong entropy.
    $self->_instantiate_rng unless $$ == $self->{_pid} && defined $self->{_RNG};

    my $divisor = $self->_closest_divisor($range);

>>>>>>> REPLACE
<<<<<<< SEARCH

sub irand {
  my( $self ) = @_;
  $self->_instantiate_rng unless defined $self->{_RNG};
  return $self->{_RNG}->irand;
}
=======

sub irand {
  my( $self ) = @_;
  $self->_instantiate_rng unless $$ == $self->{_pid} && defined $self->{_RNG};
  return $self->{_RNG}->irand;
}
>>>>>>> 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-31842: HTTP request handling defect in tinyproxy 1.11.3: the transfer-encoding detection in src/reqs.c uses case-sensitive string comparison when checking for chunked encoding, causing tinyproxy to mishandle HTTP requests where the Transfer-Encoding header value uses non-lowercase casing.

# Vulnerable source (src/reqs.c)
```c
 * -1.
 */
static long get_content_length (pseudomap *hashofheaders)
{
        char *data;
        long content_length = -1;

        data = pseudomap_find (hashofheaders, "content-length");

        if (data)
                content_length = atol (data);

        return content_length;
}

static int is_chunked_transfer (pseudomap *hashofheaders)
{
        char *data;
        data = pseudomap_find (hashofheaders, "transfer-encoding");
        return data ? !strcmp (data, "chunked") : 0;
}

/*
 * Search for Via header in a hash of headers and either write a new Via
 * header, or append our information to the end of an existing Via header.
 *
 * FIXME: Need to add code to "hide" our internal information for security
 * purposes.
 */
static int
write_via_header (int fd, pseudomap *hashofheaders,
                  unsigned int major, unsigned int minor)
{
        char hostname[512];
        char *data;
```

[Assistant]
<<<<<<< SEARCH
{
        char *data;
        data = pseudomap_find (hashofheaders, "transfer-encoding");
        return data ? !strcmp (data, "chunked") : 0;
}
=======
{
        char *data;
        data = pseudomap_find (hashofheaders, "transfer-encoding");
        return data ? !strcasecmp (data, "chunked") : 0;
}
>>>>>>> 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-32316: jq 1.8.1 jv.c has two heap buffer overflows in text handling functions: in the bad-byte replacement function, the buffer size calculation could overflow a 32-bit integer when processing a sufficiently large input, resulting in a tiny buffer with a large write beyond it; in the append function, the same wrap-around applies when appending data that pushes the combined total beyond the 32-bit maximum, causing an out-of-bounds write.

# Vulnerable source (src/jv.c)
```c
    }
    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;
```

[Assistant]
<<<<<<< SEARCH
  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;
=======
  const char* end = data + length;
  const char* i = data;

  // worst case: all bad bytes, each becomes a 3-byte U+FFFD
  uint64_t maxlength = (uint64_t)length * 3 + 1;
  if (maxlength >= INT_MAX) {
    return jv_invalid_with_msg(jv_string("String too long"));
  }

  jvp_string* s = jvp_string_alloc(maxlength);
  char* out = s->data;
  int c = 0;
>>>>>>> REPLACE
<<<<<<< SEARCH
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) {
=======
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 ((uint64_t)currlen + len >= INT_MAX) {
    jv_free(string);
    return jv_invalid_with_msg(jv_string("String too long"));
  }

  if (jvp_refcnt_unshared(string.u.ptr) &&
      jvp_string_remaining_space(s) >= len) {
>>>>>>> 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-32746: GNU inetutils includes a telnetd server that passes certain environment variables from clients to the spawned login process. The util-linux login utility, since version 2.40, reads the CREDENTIALS_DIRECTORY environment variable: if a directory at that path contains a 'login.noauth' file set to 'yes', the utility bypasses password authentication. Because telnetd relays client-supplied environment variables directly to login, a remote attacker can supply a path they control as CREDENTIALS_DIRECTORY and place the 'login.noauth' bypass file there, gaining unauthenticated access as any user including root.

# Vulnerable source (telnetd/pty.c)
```c
 * Remove a few things from the environment that
 * don't need to be there.
 *
 * Security fix included in telnet-95.10.23.NE of David Borman <deb@cray.com>.
 */
static void
scrub_env (void)
{
  char **cpp, **cpp2;

  for (cpp2 = cpp = environ; *cpp; cpp++)
    {
      if (strncmp (*cpp, "LD_", 3)
	  && strncmp (*cpp, "_RLD_", 5)
	  && strncmp (*cpp, "LIBPATH=", 8) && strncmp (*cpp, "IFS=", 4))
	*cpp2++ = *cpp;
    }
  *cpp2 = 0;
}

void
start_login (char *host, int autologin, char *name)
{
  char *cmd;
  int argc;
  char **argv;

  (void) host;			/* Silence warnings.  Diagnostic use?  */
  (void) autologin;
  (void) name;

  scrub_env ();

  /* Set the environment variable "LINEMODE" to indicate our linemode */
  if (lmodetype == REAL_LINEMODE)
    setenv ("LINEMODE", "real", 1);
  else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK)
    setenv ("LINEMODE", "kludge", 1);

  cmd = expand_line (login_invocation);
  if (!cmd)
    fatal (net, "can't expand login command line");
  argcv_get (cmd, "", &argc, &argv);
  execv (argv[0], argv);
  syslog (LOG_ERR, "%s: %m\n", cmd);
  fatalperror (net, cmd);
}

/* SIG is generally naught every time the server itself
 * decides to close the connection out of an error condition.
 * In response to TELOPT_LOGOUT from the client, SIG is set
 * to SIGHUP, so we consider the exit as a success.  In other
 * cases, when the forked client process is caught exiting,
 * then SIG will be SIGCHLD.  Then we deliver the clients's
 * reported exit code.
 */
void
cleanup (int sig)
{
  int status = EXIT_FAILURE;
  char *p;

  if (sig == SIGCHLD)
    {
      pid_t pid = waitpid ((pid_t) - 1, &status, WNOHANG);
      syslog (LOG_INFO, "child process %ld exited: %d",
	      (long) pid, WEXITSTATUS (status));

      status = WEXITSTATUS (status);
    }
  else if (sig == SIGHUP)
    status = EXIT_SUCCESS;	/* Response to TELOPT_LOGOUT.  */

  p = line + sizeof (PATH_TTY_PFX) - 1;
  utmp_logout (p);
  chmod (line, 0644);
  chown (line, 0, 0);
  shutdown (net, 2);
  exit (status);
}
```

[Assistant]
<<<<<<< SEARCH
  if (!cmd)
    fatal (net, "can't expand login command line");
  argcv_get (cmd, "", &argc, &argv);
  execv (argv[0], argv);
  syslog (LOG_ERR, "%s: %m\n", cmd);
  fatalperror (net, cmd);
=======
  if (!cmd)
    fatal (net, "can't expand login command line");
  argcv_get (cmd, "", &argc, &argv);

  /* util-linux's "login" introduced an authentication bypass method
   * via environment variable "CREDENTIALS_DIRECTORY" in version 2.40.
   * Clear it from the environment before executing "login" to prevent
   * abuse via Telnet.
   */
  unsetenv ("CREDENTIALS_DIRECTORY");

  execv (argv[0], argv);
  syslog (LOG_ERR, "%s: %m\n", cmd);
  fatalperror (net, cmd);
>>>>>>> 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-33236: CWE-22 in python3Packages.nltk 3.9.2. The NLTK corpus fetch engine reads package catalog data from a CDN endpoint (https://raw.githubusercontent.com/nltk/nltk_data/gh-pages/packages.xml). Each catalog entry specifies a data-category value (e.g. corpora) and a resource identifier (e.g. punkt). Both strings pass directly into os.path.join() when constructing the target disk path, with no sanitization for path-escape sequences. An attacker able to serve a hostile catalog via MITM, CDN compromise, or rogue mirror can embed sequences of two-dot path elements in either field, directing corpus file writes to arbitrary OS paths beyond the NLTK data root.

# Vulnerable source (nltk/downloader.py)
```python
        author="Unknown",
        unzip=True,
        **kw,
    ):
        self.id = id
        """A unique identifier for this package."""

        self.name = name or id
        """A string name for this package."""

        self.subdir = subdir
        """The subdirectory where this package should be installed.
           E.g., ``'corpora'`` or ``'taggers'``."""

        self.url = url
        """A URL that can be used to download this package's file."""

        self.size = int(size)
        """The filesize (in bytes) of the package file."""

        self.unzipped_size = int(unzipped_size)
        """The total filesize of the files contained in the package's
           zipfile."""

        self.checksum = checksum
        """The MD-5 checksum of the package file."""

        self.svn_revision = svn_revision
        """A subversion revision number for this package."""

/* ... */

        # Check for (and remove) any old/stale version.
        filepath = os.path.join(download_dir, info.filename)
        if os.path.exists(filepath):
            if status == self.STALE:
                yield StaleMessage(info)
            os.remove(filepath)

        # Ensure the download_dir exists
        os.makedirs(download_dir, exist_ok=True)
        os.makedirs(os.path.join(download_dir, info.subdir), exist_ok=True)

        # Download the file.  This will raise an IOError if the url
        # is not found.

```

[Assistant]
<<<<<<< SEARCH
        self.name = name or id
        """A string name for this package."""

        self.subdir = subdir
        """The subdirectory where this package should be installed.
           E.g., ``'corpora'`` or ``'taggers'``."""

        self.url = url
        """A URL that can be used to download this package's file."""

=======
        self.name = name or id
        """A string name for this package."""

        # Validate subdir to prevent path traversal from malicious XML index
        if os.path.isabs(subdir) or ".." in subdir.replace("\\", "/").split("/"):
            raise ValueError(
                f"Invalid package subdir {subdir!r}: must be a relative path "
                f"without parent directory references"
            )
        self.subdir = subdir
        """The subdirectory where this package should be installed.
           E.g., ``'corpora'`` or ``'taggers'``."""

        # Validate id to prevent path traversal
        if os.sep in id or "/" in id or "\\" in id or ".." in id:
            raise ValueError(
                f"Invalid package id {id!r}: must not contain path separators"
            )

        self.url = url
        """A URL that can be used to download this package's file."""

>>>>>>> REPLACE
<<<<<<< SEARCH

        # Check for (and remove) any old/stale version.
        filepath = os.path.join(download_dir, info.filename)
        if os.path.exists(filepath):
            if status == self.STALE:
                yield StaleMessage(info)
=======

        # Check for (and remove) any old/stale version.
        filepath = os.path.join(download_dir, info.filename)

        # Defense-in-depth: verify filepath stays within download_dir
        real_download = os.path.realpath(os.path.abspath(download_dir))
        real_filepath = os.path.realpath(os.path.abspath(filepath))
        if not real_filepath.startswith(real_download + os.sep):
            yield ErrorMessage(
                info,
                f"Path traversal blocked: package '{info.id}' attempted to "
                f"write outside download directory (subdir='{info.subdir}')",
            )
            return

        if os.path.exists(filepath):
            if status == self.STALE:
                yield StaleMessage(info)
>>>>>>> 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-33947: jq through 1.8.1 allows deeply nested path arrays to cause unbounded recursion in jv_setpath, jv_getpath, and jv_delpaths, leading to stack overflow. A crafted input document with paths exceeding ten thousand levels of nesting triggers the vulnerability when processed with path manipulation filters.

# Vulnerable source (src/jv_aux.c)
```c
        }
        if (i < delidx) {
          break;
        }
        neg_idx++;
      }
      while (nonneg_idx < jv_array_length(jv_copy(nonneg_keys))) {
        int delidx = (int)jv_number_get_value_and_consume(jv_array_get(jv_copy(nonneg_keys), nonneg_idx));
        if (i == delidx) {
          del = 1;
        }
        if (i < delidx) {
          break;
        }
        nonneg_idx++;
      }
      for (int sidx=0; !del && sidx<jv_array_length(jv_copy(starts)); sidx++) {
        if ((int)jv_number_get_value_and_consume(jv_array_get(jv_copy(starts), sidx)) <= i &&
            i < (int)jv_number_get_value_and_consume(jv_array_get(jv_copy(ends), sidx))) {
          del = 1;
        }
      }
      if (!del)
        new_array = jv_array_append(new_array, jv_array_get(jv_copy(t), i));
    }
  arr_out:
    jv_free(neg_keys);
    jv_free(nonneg_keys);
    jv_free(starts);
    jv_free(ends);
    jv_free(t);
    t = new_array;
  } else if (jv_get_kind(t) == JV_KIND_OBJECT) {
    jv_array_foreach(keys, i, k) {
      if (jv_get_kind(k) != JV_KIND_STRING) {
        jv_free(t);
        t = jv_invalid_with_msg(jv_string_fmt("Cannot delete %s field of object",
                                              jv_kind_name(jv_get_kind(k))));
        jv_free(k);
        break;
      }
      t = jv_object_delete(t, k);
    }
  } else {
    jv err = jv_invalid_with_msg(jv_string_fmt("Cannot delete fields from %s",
                                               jv_kind_name(jv_get_kind(t))));
    jv_free(t);
    t = err;
  }
  jv_free(keys);
  return t;
}

jv jv_setpath(jv root, jv path, jv value) {
  if (jv_get_kind(path) != JV_KIND_ARRAY) {
    jv_free(value);
    jv_free(root);
    jv_free(path);
    return jv_invalid_with_msg(jv_string("Path must be specified as an array"));
  }
  if (!jv_is_valid(root)){
    jv_free(value);
    jv_free(path);
    return root;
  }
  if (jv_array_length(jv_copy(path)) == 0) {
    jv_free(path);
    jv_free(root);
    return value;
  }
  jv pathcurr = jv_array_get(jv_copy(path), 0);
  jv pathrest = jv_array_slice(path, 1, jv_array_length(jv_copy(path)));

  /*
   * We need to be careful not to make extra copies since that leads to
   * quadratic behavior (e.g., when growing large data structures in a
   * reduction with `setpath/2`, i.e., with `|=`.
   */
  if (jv_get_kind(pathcurr) == JV_KIND_OBJECT) {
    // Assignment to slice -- dunno yet how to avoid the extra copy
    return jv_set(root, pathcurr,
                  jv_setpath(jv_get(jv_copy(root), jv_copy(pathcurr)), pathrest, value));
  }

  jv subroot = jv_get(jv_copy(root), jv_copy(pathcurr));
  if (!jv_is_valid(subroot)) {
    jv_free(root);
    jv_free(pathcurr);
    jv_free(pathrest);
    jv_free(value);
    return subroot;
  }

  // To avoid the extra copy we drop the reference from `root` by setting that
  // to null first.
  root = jv_set(root, jv_copy(pathcurr), jv_null());
  if (!jv_is_valid(root)) {
    jv_free(subroot);
    jv_free(pathcurr);
    jv_free(pathrest);
    jv_free(value);
    return root;
  }
  return jv_set(root, pathcurr, jv_setpath(subroot, pathrest, value));
}

jv jv_getpath(jv root, jv path) {
  if (jv_get_kind(path) != JV_KIND_ARRAY) {
    jv_free(root);
    jv_free(path);
    return jv_invalid_with_msg(jv_string("Path must be specified as an array"));
  }
  if (!jv_is_valid(root)) {
    jv_free(path);
    return root;
  }
  if (jv_array_length(jv_copy(path)) == 0) {
    jv_free(path);
    return root;
  }
  jv pathcurr = jv_array_get(jv_copy(path), 0);
  jv pathrest = jv_array_slice(path, 1, jv_array_length(jv_copy(path)));
  return jv_getpath(jv_get(root, pathcurr), pathrest);
}

// assumes paths is a sorted array of arrays
static jv delpaths_sorted(jv object, jv paths, int start) {
  jv delkeys = jv_array();
  for (int i=0; i<jv_array_length(jv_copy(paths));) {
    int j = i;
    assert(jv_array_length(jv_array_get(jv_copy(paths), i)) > start);
    int delkey = jv_array_length(jv_array_get(jv_copy(paths), i)) == start + 1;
    jv key = jv_array_get(jv_array_get(jv_copy(paths), i), start);
    while (j < jv_array_length(jv_copy(paths)) &&
           jv_equal(jv_copy(key), jv_array_get(jv_array_get(jv_copy(paths), j), start)))
      j++;
    // if i <= entry < j, then entry starts with key
    if (delkey) {
      // deleting this entire key, we don't care about any more specific deletions
      delkeys = jv_array_append(delkeys, key);
    } else {
      // deleting certain sub-parts of this key
      jv subobject = jv_get(jv_copy(object), jv_copy(key));
      if (!jv_is_valid(subobject)) {
        jv_free(key);
        jv_free(object);
        object = subobject;
        break;
      } else if (jv_get_kind(subobject) == JV_KIND_NULL) {
        jv_free(key);
        jv_free(subobject);
      } else {
        jv newsubobject = delpaths_sorted(subobject, jv_array_slice(jv_copy(paths), i, j), start+1);
        if (!jv_is_valid(newsubobject)) {
          jv_free(key);
          jv_free(object);
          object = newsubobject;
          break;
        }
        object = jv_set(object, key, newsubobject);
      }
      if (!jv_is_valid(object)) break;
    }
    i = j;
  }
  jv_free(paths);
  if (jv_is_valid(object))
    object = jv_dels(object, delkeys);
  else
    jv_free(delkeys);
  return object;
}

jv jv_delpaths(jv object, jv paths) {
  if (jv_get_kind(paths) != JV_KIND_ARRAY) {
    jv_free(object);
    jv_free(paths);
    return jv_invalid_with_msg(jv_string("Paths must be specified as an array"));
  }
  paths = jv_sort(paths, jv_copy(paths));
  jv_array_foreach(paths, i, elem) {
    if (jv_get_kind(elem) != JV_KIND_ARRAY) {
      jv_free(object);
      jv_free(paths);
      jv err = jv_invalid_with_msg(jv_string_fmt("Path must be specified as array, not %s",
                                                 jv_kind_name(jv_get_kind(elem))));
      jv_free(elem);
      return err;
    }
    jv_free(elem);
  }
  if (jv_array_length(jv_copy(paths)) == 0) {
    // nothing is being deleted
    jv_free(paths);
    return object;
  }
  if (jv_array_length(jv_array_get(jv_copy(paths), 0)) == 0) {
    // everything is being deleted
    jv_free(paths);
    jv_free(object);
    return jv_null();
  }
  return delpaths_sorted(object, paths, 0);
}

static int string_cmp(const void* pa, const void* pb){
  const jv* a = pa;
  const jv* b = pb;
  int lena = jv_string_length_bytes(jv_copy(*a));
  int lenb = jv_string_length_bytes(jv_copy(*b));
  int minlen = lena < lenb ? lena : lenb;
  int r = memcmp(jv_string_value(*a), jv_string_value(*b), minlen);
  if (r == 0) r = lena - lenb;
  return r;
}

jv jv_keys_unsorted(jv x) {
  if (jv_get_kind(x) != JV_KIND_OBJECT)
    return jv_keys(x);
  jv answer = jv_array_sized(jv_object_length(jv_copy(x)));
  jv_object_foreach(x, key, value) {
    answer = jv_array_append(answer, key);
```

[Assistant]
<<<<<<< SEARCH
  return t;
}

jv jv_setpath(jv root, jv path, jv value) {
  if (jv_get_kind(path) != JV_KIND_ARRAY) {
    jv_free(value);
=======
  return t;
}

#ifndef MAX_PATH_DEPTH
#define MAX_PATH_DEPTH (10000)
#endif

jv jv_setpath(jv root, jv path, jv value) {
  if (jv_get_kind(path) != JV_KIND_ARRAY) {
    jv_free(value);
>>>>>>> REPLACE
<<<<<<< SEARCH
    jv_free(path);
    return jv_invalid_with_msg(jv_string("Path must be specified as an array"));
  }
  if (!jv_is_valid(root)){
    jv_free(value);
    jv_free(path);
=======
    jv_free(path);
    return jv_invalid_with_msg(jv_string("Path must be specified as an array"));
  }
  if (jv_array_length(jv_copy(path)) > MAX_PATH_DEPTH) {
    jv_free(value);
    jv_free(root);
    jv_free(path);
    return jv_invalid_with_msg(jv_string("Path too deep"));
  }
  if (!jv_is_valid(root)){
    jv_free(value);
    jv_free(path);
>>>>>>> REPLACE
<<<<<<< SEARCH
    jv_free(path);
    return jv_invalid_with_msg(jv_string("Path must be specified as an array"));
  }
  if (!jv_is_valid(root)) {
    jv_free(path);
    return root;
=======
    jv_free(path);
    return jv_invalid_with_msg(jv_string("Path must be specified as an array"));
  }
  if (jv_array_length(jv_copy(path)) > MAX_PATH_DEPTH) {
    jv_free(root);
    jv_free(path);
    return jv_invalid_with_msg(jv_string("Path too deep"));
  }
  if (!jv_is_valid(root)) {
    jv_free(path);
    return root;
>>>>>>> REPLACE
<<<<<<< SEARCH
      jv_free(elem);
      return err;
    }
    jv_free(elem);
  }
  if (jv_array_length(jv_copy(paths)) == 0) {
=======
      jv_free(elem);
      return err;
    }
    if (jv_array_length(jv_copy(elem)) > MAX_PATH_DEPTH) {
      jv_free(object);
      jv_free(paths);
      jv_free(elem);
      return jv_invalid_with_msg(jv_string("Path too deep"));
    }
    jv_free(elem);
  }
  if (jv_array_length(jv_copy(paths)) == 0) {
>>>>>>> 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-33948: Input like '{}\x00{}' was thus parsed as only '{}' and jq exited 0, dropping the trailing bytes after the NUL — so jq and another NUL-aware consumer could disagree on the document. Affects jq 1.8.x.

# Vulnerable source (src/util.c)
```c

  state->buf[0] = 0;
  state->buf_valid_len = 0;
  if (state->current_input) {
    char *res;
    memset(state->buf, 0xff, sizeof(state->buf));

    const int max_utf8_len = 4;
    const int max_gets_len = sizeof(state->buf) - max_utf8_len;
    while (!(res = fgets(state->buf, max_gets_len, state->current_input)) &&
           ferror(state->current_input) && errno == EINTR)
      clearerr(state->current_input);
    if (res == NULL) {
      state->buf[0] = 0;
      if (ferror(state->current_input))
        state->failures++;
    } else {
      const char *p = memchr(state->buf, '\n', max_gets_len);

      if (p != NULL)
        state->current_line++;

      if (p == NULL && state->parser != NULL) {
        /*
         * There should be no NULs in JSON texts (but JSON text
         * sequences are another story).
         */
        state->buf_valid_len = strlen(state->buf);
      } else if (p == NULL && feof(state->current_input)) {
        size_t i;

        /*
         * XXX We don't know how many bytes we've read!
         *
         * We can't use getline() because there need not be any newlines
         * in the input.  The only entirely correct choices are: use
         * fgetc() or fread().  Using fread() will complicate buffer
         * management here.
         *
         * For now we check how much fgets() read by scanning backwards for the
```

[Assistant]
<<<<<<< SEARCH
      if (p != NULL)
        state->current_line++;

      if (p == NULL && state->parser != NULL) {
        /*
         * There should be no NULs in JSON texts (but JSON text
         * sequences are another story).
         */
        state->buf_valid_len = strlen(state->buf);
      } else if (p == NULL && feof(state->current_input)) {
        size_t i;

        /*
=======
      if (p != NULL)
        state->current_line++;

      if (p == NULL && feof(state->current_input)) {
        size_t i;

        /*
>>>>>>> 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-39979: jq 1.8.1 jv_parse_sized_custom_flags function has an out-of-bounds read when a parse error is reported: the error message formatter used the input pointer with a plain format specifier that reads until NUL rather than stopping at the declared input boundary, allowing a crafted JSON input without a terminating NUL to trigger reads past the allocated buffer.

# Vulnerable source (src/jv_parse.c)
```c
      value = p->next;
    }
    p->next = jv_invalid();
    if ((p->flags & JV_PARSE_SEQ) && !p->last_ch_was_ws && jv_get_kind(value) == JV_KIND_NUMBER) {
      jv_free(value);
      return make_error(p, "Potentially truncated top-level numeric value at EOF at line %d, column %d", p->line, p->column);
    }
    return value;
  }
}

jv jv_parse_sized_custom_flags(const char* string, int length, int flags) {
  struct jv_parser parser;
  parser_init(&parser, flags);
  jv_parser_set_buf(&parser, string, length, 0);
  jv value = jv_parser_next(&parser);
  if (jv_is_valid(value)) {
    jv next = jv_parser_next(&parser);
    if (jv_is_valid(next)) {
      // multiple JSON values, we only wanted one
      jv_free(value);
      jv_free(next);
      value = jv_invalid_with_msg(jv_string("Unexpected extra JSON values"));
    } else if (jv_invalid_has_msg(jv_copy(next))) {
      // parser error after the first JSON value
      jv_free(value);
      value = next;
    } else {
      // a single valid JSON value
      jv_free(next);
    }
  } else if (jv_invalid_has_msg(jv_copy(value))) {
    // parse error, we'll return it
  } else {
    // no value at all
    jv_free(value);
    value = jv_invalid_with_msg(jv_string("Expected JSON value"));
  }
  parser_free(&parser);

  if (!jv_is_valid(value) && jv_invalid_has_msg(jv_copy(value))) {
    jv msg = jv_invalid_get_msg(value);
    value = jv_invalid_with_msg(jv_string_fmt("%s (while parsing '%s')",
                                              jv_string_value(msg),
                                              string));
    jv_free(msg);
  }
  return value;
}

jv jv_parse_sized(const char* string, int length) {
  return jv_parse_sized_custom_flags(string, length, 0);
}

jv jv_parse(const char* string) {
  return jv_parse_sized(string, strlen(string));
}

jv jv_parse_custom_flags(const char* string, int flags) {
  return jv_parse_sized_custom_flags(string, strlen(string), flags);
}
```

[Assistant]
<<<<<<< SEARCH

  if (!jv_is_valid(value) && jv_invalid_has_msg(jv_copy(value))) {
    jv msg = jv_invalid_get_msg(value);
    value = jv_invalid_with_msg(jv_string_fmt("%s (while parsing '%s')",
                                              jv_string_value(msg),
                                              string));
    jv_free(msg);
  }
=======

  if (!jv_is_valid(value) && jv_invalid_has_msg(jv_copy(value))) {
    jv msg = jv_invalid_get_msg(value);
    value = jv_invalid_with_msg(jv_string_fmt("%s (while parsing '%.*s')",
                                              jv_string_value(msg),
                                              length,
                                              string));
    jv_free(msg);
  }
>>>>>>> REPLACE