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

[User]
# CVE
CVE-2025-47256: Stack-based buffer underwrite (CWE-191 integer underflow → CWE-121 stack buffer overflow) in libxmp's Pha Packer loader. In loaders/prowizard/pha.c, the depack_pha() function iterates over compressed blocks using a counter ocpt whose value comes directly from the module file. When ocpt is sufficiently large, the expression used as an array subscript wraps below zero (signed integer underflow), causing writes to memory below the dest buffer's base — a stack buffer underwrite. A crafted .mod file with an overflowed ocpt field triggers a SIGSEGV on any caller of xmp_load_module(). Upstream ships test fixtures: test-dev/data/f/prowizard_pha_invalid_ocpt and prowizard_pha_invalid_ocpt2.

# Vulnerable source (src/loaders/prowizard/pha.c)
```c
/* ProWizard
 * Copyright (C) 1996-1999 Asle / ReDoX
 * Modified in 2006,2007,2014 by Claudio Matsuoka
 * Modified in 2021 by Alice Rowan
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        /* ... */
				paddr1[j] = paddr1[i];
				paddr1[i] = tmp;
				goto restart;
			}
		}
	}

	j = 0;
	for (i = 0; i < 128; i++) {
		if (i == 0) {
			paddr2[j] = paddr1[i];
			continue;
		}

		if (paddr1[i] == paddr2[j])
			continue;
		paddr2[++j] = paddr1[i];
	}

	/* try to take care of unused patterns ... HARRRRRRD */
	memset(paddr1, 0, sizeof(paddr1));
	j = 0;
	k = paddr[0];
	/* 120 ... leaves 8 unused ptk_tableible patterns .. */
	for (i = 0; i < 120; i++) {
		paddr1[j] = paddr2[i];
		j += 1;
		if (j >= 128)
			break;

		if ((paddr2[i + 1] - paddr2[i]) > 1024) {
			paddr1[j] = paddr2[i] + 1024;
			j += 1;
			if (j >= 128)
				break;
		}
	}

	for (c1 = 0; c1 < 128; c1++) {
		for (c2 = 0; c2 < 128; c2++) {
        /* ... */
#if 0
	j = ftell (in);
	fseek (in, 0, 2);	/* SEEK_END */
	psize = ftell (in) - j;
	fseek (in, j, 0);	/* SEEK_SET */
#endif
	/* This value should be larger than the actual size of the
	 * pattern data and will probably set the error flag, so
	 * clear it after reading.
	 */
	psize = npat * 1024;
	if ((pdata = (uint8 *)malloc(psize)) == NULL)
		return -1;

	psize = hio_read(pdata, 1, psize, in);
	hio_error(in);

	size = npat * 1024;
	if ((pat = (uint8 *)calloc(1, size)) == NULL)
		goto err;

	j = 0;
	for (i = 0; i < psize && j < size; i++) {
		if (pdata[i] == 0xff) {
			i += 1;
			if (i >= psize)
				goto err;

			ocpt[(k + 3) % 4] = 0xff - pdata[i];
			continue;
		}
		if (ocpt[k % 4] != 0) {
			ins = onote[k % 4][0];
			note = onote[k % 4][1];
			fxt = onote[k % 4][2];
			fxp = onote[k % 4][3];
			ocpt[k % 4] -= 1;

			pat[j] = ins & 0xf0;
			if (PTK_IS_VALID_NOTE(note / 2)) {
```

[Assistant]
diff --git a/src/loaders/prowizard/pha.c b/src/loaders/prowizard/pha.c
--- a/src/loaders/prowizard/pha.c
+++ b/src/loaders/prowizard/pha.c
@@ -1,7 +1,7 @@
 /* ProWizard
  * Copyright (C) 1996-1999 Asle / ReDoX
  * Modified in 2006,2007,2014 by Claudio Matsuoka
- * Modified in 2021 by Alice Rowan
+ * Modified in 2021, 2025 by Alice Rowan
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -149,7 +149,6 @@ static int depack_pha(HIO_HANDLE *in, FILE *out)
 	/* try to take care of unused patterns ... HARRRRRRD */
 	memset(paddr1, 0, sizeof(paddr1));
 	j = 0;
-	k = paddr[0];
 	/* 120 ... leaves 8 unused ptk_tableible patterns .. */
 	for (i = 0; i < 120; i++) {
 		paddr1[j] = paddr2[i];
@@ -232,6 +231,7 @@ static int depack_pha(HIO_HANDLE *in, FILE *out)
 		goto err;

 	j = 0;
+	k = 0;
 	for (i = 0; i < psize && j < size; i++) {
 		if (pdata[i] == 0xff) {
 			i += 1;


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

[User]
# CVE
CVE-2025-48060: Heap buffer overflow (CWE-122) in jq 1.7.1 and earlier in the string-formatting path. via `0[[]|implode]`) reads one byte past the allocation boundary, causing a heap buffer overflow. A crafted jq program or input that triggers the `implode`-of-empty-array path can crash jq or, under adversarial heap layout, leak or corrupt adjacent heap memory.

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

[Assistant]
diff --git a/src/jv.c b/src/jv.c
index dfb24fa..e4529a4 100644
--- a/src/jv.c
+++ b/src/jv.c
@@ -1148,6 +1148,7 @@ 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;
 }


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

[User]
# CVE
CVE-2025-49466: This could be exploited to cause a denial of service when the intermediate directory was absent, or to write files outside the intended temporary folder.

# Vulnerable source (commands/msgview/open.go)
```go
package msgview

import (
	"errors"
	"io"
	"mime"
	"os"
	"path/filepath"

	"git.sr.ht/~rjarry/aerc/app"
	"git.sr.ht/~rjarry/aerc/commands"
	"git.sr.ht/~rjarry/aerc/lib"
	"git.sr.ht/~rjarry/aerc/lib/log"
)

type Open struct {
	Delete bool   `opt:"-d" desc:"Delete temp file after the opener exits."`
	Cmd    string `opt:"..." required:"false"`
}

func init() {
	commands.Register(Open{})
}

func (Open) Description() string {
	return "Save the current message part to a temporary file, then open it."
}

func (Open) Context() commands.CommandContext {
	return commands.MESSAGE_VIEWER
}

func (Open) Aliases() []string {
	return []string{"open"}
}

func (o Open) Execute(args []string) error {
	mv := app.SelectedTabContent().(*app.MessageViewer)
	if mv == nil {
		return errors.New("open only supported selected message parts")
	}
	p := mv.SelectedMessagePart()

	mv.MessageView().FetchBodyPart(p.Index, func(reader io.Reader) {
		mimeType := ""

		part, err := mv.MessageView().BodyStructure().PartAtIndex(p.Index)
		if err != nil {
			app.PushError(err.Error())
			return
		}
		mimeType = part.FullMIMEType()

		tmpDir, err := os.MkdirTemp(os.TempDir(), "aerc-*")
		if err != nil {
			app.PushError(err.Error())
			return
		}
		filename := part.FileName()
		var tmpFile *os.File
		if filename == "" {
			extension := ""
			if exts, _ := mime.ExtensionsByType(mimeType); len(exts) > 0 {
				extension = exts[0]
			}
			tmpFile, err = os.CreateTemp(tmpDir, "aerc-*"+extension)
		} else {
			tmpFile, err = os.Create(filepath.Join(tmpDir, filename))
		}
		if err != nil {
			app.PushError(err.Error())
			return
		}

		_, err = io.Copy(tmpFile, reader)
		tmpFile.Close()
		if err != nil {
			app.PushError(err.Error())
			return
		}

		go func() {
			defer log.PanicHandler()
			if o.Delete {
				defer os.RemoveAll(tmpDir)
			}
			err = lib.XDGOpenMime(tmpFile.Name(), mimeType, o.Cmd)
			if err != nil {
				app.PushError("open: " + err.Error())
			}
		}()
	})

	return nil
}
```

[Assistant]
diff --git a/commands/msgview/open.go b/commands/msgview/open.go
index 4293b7e4892c137a7f3fbbe79245ffb6733b2671..a6e43cb8da5fd49d2aa562d4c25ee2d597deefc3 100644
--- a/commands/msgview/open.go
+++ b/commands/msgview/open.go
@@ -5,6 +5,7 @@ import (
 	"io"
 	"mime"
 	"os"
+	"path"
 	"path/filepath"

 	"git.sr.ht/~rjarry/aerc/app"
@@ -56,7 +57,7 @@ func (o Open) Execute(args []string) error {
 			app.PushError(err.Error())
 			return
 		}
-		filename := part.FileName()
+		filename := path.Base(part.FileName())
 		var tmpFile *os.File
 		if filename == "" {
 			extension := ""


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

[User]
# CVE
CVE-2025-5278: Heap-buffer-overflow (out-of-bounds read, CWE-127/CWE-823) in GNU coreutils 9.7 `sort`. PoC (from coreutils NEWS): `sort +0.18446744073709551615R input` on 64-bit systems induces a read 1 byte before an allocated heap buffer.

# Vulnerable source (src/sort.c)
```c
      {
        while (ptr < lim && *ptr != tab)
          ++ptr;
        if (ptr < lim)
          ++ptr;
      }
  else
    while (ptr < lim && sword--)
      {
        while (ptr < lim && blanks[to_uchar (*ptr)])
          ++ptr;
        while (ptr < lim && !blanks[to_uchar (*ptr)])
          ++ptr;
      }

  /* If we're ignoring leading blanks when computing the Start
     of the field, skip past them here.  */
  if (key->skipsblanks)
    while (ptr < lim && blanks[to_uchar (*ptr)])
      ++ptr;

  /* Advance PTR by SCHAR (if possible), but no further than LIM.  */
  ptr = MIN (lim, ptr + schar);

  return ptr;
}

/* Return the limit of (a pointer to the first character after) the field
   in LINE specified by KEY. */

ATTRIBUTE_PURE
static char *
limfield (struct line const *line, struct keyfield const *key)
{
  char *ptr = line->text, *lim = ptr + line->length - 1;
  size_t eword = key->eword, echar = key->echar;

  if (echar == 0)
    eword++; /* Skip all of end field.  */

        /* ... */
    }
  else
    {
      char *newlim;
      newlim = ptr;
      while (newlim < lim && blanks[to_uchar (*newlim)])
        ++newlim;
      while (newlim < lim && !blanks[to_uchar (*newlim)])
        ++newlim;
      lim = newlim;
    }
#endif

  if (echar != 0) /* We need to skip over a portion of the end field.  */
    {
      /* If we're ignoring leading blanks when computing the End
         of the field, skip past them here.  */
      if (key->skipeblanks)
        while (ptr < lim && blanks[to_uchar (*ptr)])
          ++ptr;

      /* Advance PTR by ECHAR (if possible), but no further than LIM.  */
      ptr = MIN (lim, ptr + echar);
    }

  return ptr;
}

/* Fill BUF reading from FP, moving buf->left bytes from the end
   of buf->buf to the beginning first.  If EOF is reached and the
   file wasn't terminated by a newline, supply one.  Set up BUF's line
   table too.  FILE is the name of the file corresponding to FP.
   Return true if some input was read.  */

static bool
fillbuf (struct buffer *buf, FILE *fp, char const *file)
{
  struct keyfield const *key = keylist;
  char eol = eolchar;
  size_t line_bytes = buf->line_bytes;
```

[Assistant]
diff --git a/src/sort.c b/src/sort.c
--- a/src/sort.c
+++ b/src/sort.c
@@ -1644,7 +1644,11 @@ begfield (struct line const *line, struct keyfield const *key)
       ++ptr;

   /* Advance PTR by SCHAR (if possible), but no further than LIM.  */
-  ptr = MIN (lim, ptr + schar);
+  size_t remaining_bytes = lim - ptr;
+  if (schar < remaining_bytes)
+    ptr += schar;
+  else
+    ptr = lim;

   return ptr;
 }
@@ -1746,7 +1750,11 @@ limfield (struct line const *line, struct keyfield const *key)
           ++ptr;

       /* Advance PTR by ECHAR (if possible), but no further than LIM.  */
-      ptr = MIN (lim, ptr + echar);
+      size_t remaining_bytes = lim - ptr;
+      if (echar < remaining_bytes)
+        ptr += echar;
+      else
+        ptr = lim;
     }

   return ptr;


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

[User]
# CVE
CVE-2025-57812: Processing such TIFF files triggers out-of-bounds memory access and heap buffer overflows in the TIFF reading code, exploitable via crafted print jobs sent to a CUPS server.

# Vulnerable source (cupsfilters/image-tiff.c)
```c
#  include <tiff.h>	// TIFF image definitions
#  include <tiffio.h>
#  include <unistd.h>

//
// '_cfImageReadTIFF()' - Read a TIFF image file.
//

int					// O - Read status
_cfImageReadTIFF(
    cf_image_t      *img,		// IO - Image
    FILE            *fp,		// I - Image file
    cf_icspace_t    primary,		// I - Primary choice for colorspace
    cf_icspace_t    secondary,		// I - Secondary choice for colorspace
    int             saturation,		// I - Color saturation (%)
    int             hue,		// I - Color hue (degrees)
    const cf_ib_t   *lut)		// I - Lookup table for gamma/brightness
{
  TIFF		*tif;			// TIFF file
  uint32_t	width, height;		// Size of image
  uint16_t	photometric,		// Colorspace
		compression,		// Type of compression
		orientation,		// Orientation
		resunit,		// Units for resolution
		samples,		// Number of samples/pixel
		bits,			// Number of bits/pixel
		inkset,			// Ink set for color separations
		numinks;		// Number of inks in set
  float		xres,			// Horizontal resolution
		yres;			// Vertical resolution
  uint16_t	*redcmap,		// Red colormap information
		*greencmap,		// Green colormap information
		*bluecmap;		// Blue colormap information
  int		c,			// Color index
		num_colors,		// Number of colors
		bpp,			// Bytes per pixel
		x, y,			// Current x & y
		row,			// Current row in image
		xstart, ystart,		// Starting x & y
        /* ... */
    DEBUG_puts("DEBUG: No image width tag in the file!\n");
    TIFFClose(tif);
    fclose(fp);
    return (-1);
  }

  if (!TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height))
  {
    DEBUG_puts("DEBUG: No image height tag in the file!\n");
    TIFFClose(tif);
    fclose(fp);
    return (-1);
  }

  if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric))
  {
    DEBUG_puts("DEBUG: No photometric tag in the file!\n");
    TIFFClose(tif);
    fclose(fp);
    return (-1);
  }

  if (!TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression))
  {
    DEBUG_puts("DEBUG: No compression tag in the file!\n");
    TIFFClose(tif);
    fclose(fp);
    return (-1);
  }

  if (!TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samples))
    samples = 1;

  if (!TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits))
    bits = 1;

  //
  // Get the image orientation...
  //

  if (!TIFFGetField(tif, TIFFTAG_ORIENTATION, &orientation))
    orientation = 0;

  //
  // Get the image resolution...
  //

  int temp = -1;

#ifdef HAVE_EXIF
  //
  // Scan image file for EXIF data
  //

        /* ... */

    if (img->xppi == 0 || img->yppi == 0)
    {
      DEBUG_puts("DEBUG: Bad TIFF resolution.\n");
      img->xppi = img->yppi = 128;
    }

    DEBUG_printf(("DEBUG: TIFF resolution = %fx%f, units=%d\n",
		  xres, yres, resunit));
    DEBUG_printf(("DEBUG: Stored resolution = %dx%d PPI\n",
		  img->xppi, img->yppi));
  }

  //
  // See if the image has an alpha channel...
  //

  if (samples == 2 || (samples == 4 && photometric == PHOTOMETRIC_RGB))
    alpha = 1;
  else
    alpha = 0;

  //
  // Check the size of the image...
  //

  if (width == 0 || width > CF_IMAGE_MAX_WIDTH ||
      height == 0 || height > CF_IMAGE_MAX_HEIGHT ||
      (bits != 1 && bits != 2 && bits != 4 && bits != 8) ||
      samples < 1 || samples > 4)
  {
    DEBUG_printf(("DEBUG: Bad TIFF dimensions %ux%ux%ux%u!\n",
		  (unsigned)width, (unsigned)height, (unsigned)bits,
		  (unsigned)samples));
    TIFFClose(tif);
    fclose(fp);
    return (1);
  }

  //
        /* ... */
        break;
    default :
    case ORIENTATION_TOPLEFT :
        DEBUG_puts("DEBUG: orientation = top-left\n");
        break;
    case ORIENTATION_LEFTTOP :
        DEBUG_puts("DEBUG: orientation = left-top\n");
        break;
    case ORIENTATION_BOTLEFT :
        DEBUG_puts("DEBUG: orientation = bottom-left\n");
        break;
    case ORIENTATION_LEFTBOT :
        DEBUG_puts("DEBUG: orientation = left-bottom\n");
        break;
    case ORIENTATION_BOTRIGHT :
        DEBUG_puts("DEBUG: orientation = bottom-right\n");
        break;
    case ORIENTATION_RIGHTBOT :
        DEBUG_puts("DEBUG: orientation = right-bottom\n");
        break;
  }

  switch (orientation)
  {
    case ORIENTATION_TOPRIGHT :
    case ORIENTATION_RIGHTTOP :
        xstart = img->xsize - 1;
        xdir   = -1;
        ystart = 0;
        ydir   = 1;
        break;
    default :
    case ORIENTATION_TOPLEFT :
    case ORIENTATION_LEFTTOP :
        xstart = 0;
        xdir   = 1;
        ystart = 0;
        ydir   = 1;
        break;
    case ORIENTATION_BOTLEFT :
        /* ... */
	      {
		default :
		    break;

		case CF_IMAGE_WHITE :
		    cfImageRGBToWhite(in, out, img->xsize);
		    break;
		case CF_IMAGE_RGB :
		    cfImageRGBToRGB(in, out, img->xsize);
		    break;
		case CF_IMAGE_BLACK :
		    cfImageRGBToBlack(in, out, img->xsize);
		    break;
		case CF_IMAGE_CMY :
		    cfImageRGBToCMY(in, out, img->xsize);
		    break;
		case CF_IMAGE_CMYK :
		    cfImageRGBToCMYK(in, out, img->xsize);
		    break;
	      }

	      if (lut)
	        cfImageLut(out, img->xsize * 3, lut);

              _cfImagePutRow(img, 0, y, img->xsize, out);
            }
          }
          else
          {
	    //
	    // Column major order...
	    //

            for (x = xstart, xcount = img->xsize, row = 0;
        	 xcount > 0;
        	 xcount --, x += xdir, row ++)
            {
              if (bits == 1)
              {
        	TIFFReadScanline(tif, scanline, row, 0);
```

[Assistant]
diff --git a/cupsfilters/image-tiff.c b/cupsfilters/image-tiff.c
--- a/cupsfilters/image-tiff.c
+++ b/cupsfilters/image-tiff.c
@@ -41,6 +41,7 @@ _cfImageReadTIFF(
   TIFF		*tif;			// TIFF file
   uint32_t	width, height;		// Size of image
   uint16_t	photometric,		// Colorspace
+    planar,         // Color components in separate planes
 		compression,		// Type of compression
 		orientation,		// Orientation
 		resunit,		// Units for resolution
@@ -113,6 +114,15 @@ _cfImageReadTIFF(
     return (-1);
   }

+  if (TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planar) &&
+      planar == PLANARCONFIG_SEPARATE)
+  {
+    fputs("DEBUG: Images with planar color configuration are not supported!\n", stderr);
+    TIFFClose(tif);
+    fclose(fp);
+    return (1);
+  }
+
   if (!TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression))
   {
     DEBUG_puts("DEBUG: No compression tag in the file!\n");
@@ -127,6 +137,15 @@ _cfImageReadTIFF(
   if (!TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits))
     bits = 1;

+  if (bits == 1 && samples > 1)
+  {
+    fprintf(stderr, "ERROR: Color images with 1 bit per sample not supported! "
+                    "Samples per pixel: %d; Bits per sample: %d\n", samples, bits);
+    TIFFClose(tif);
+    fclose(fp);
+    return (1);
+  }
+
   //
   // Get the image orientation...
   //
@@ -193,6 +212,23 @@ _cfImageReadTIFF(
   else
     alpha = 0;

+  //
+  // Check whether number of samples per pixel corresponds with color space
+  //
+
+  if ((photometric == PHOTOMETRIC_RGB && (samples < 3 || samples > 4)) ||
+      (photometric == PHOTOMETRIC_SEPARATED && samples != 4))
+  {
+    fprintf(stderr, "DEBUG: Number of samples per pixel does not correspond to color space! "
+                    "Color space: %s; Samples per pixel: %d\n",
+                    (photometric == PHOTOMETRIC_RGB ? "RGB" :
+                     (photometric == PHOTOMETRIC_SEPARATED ? "CMYK" : "Unknown")),
+                    samples);
+    TIFFClose(tif);
+    fclose(fp);
+    return (1);
+  }
+
   //
   // Check the size of the image...
   //
@@ -265,6 +301,14 @@ _cfImageReadTIFF(
         break;
   }

+  if (orientation >= ORIENTATION_LEFTTOP)
+  {
+    fputs("ERROR: TIFF files with vertical scanlines are not supported!\n", stderr);
+    TIFFClose(tif);
+    fclose(fp);
+    return (-1);
+  }
+
   switch (orientation)
   {
     case ORIENTATION_TOPRIGHT :
@@ -1493,7 +1537,7 @@ _cfImageReadTIFF(
 	      }

 	      if (lut)
-	        cfImageLut(out, img->xsize * 3, lut);
+	        cfImageLut(out, img->xsize * bpp, lut);

               _cfImagePutRow(img, 0, y, img->xsize, out);
             }


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

[User]
# CVE
CVE-2025-60876: HTTP header injection in BusyBox 1.37.0 wget: the networking/wget.c URL parsing function accepts URLs containing ASCII control characters and space characters, allowing a server or redirect to craft a URL that injects arbitrary headers into subsequent HTTP requests.

# Vulnerable source (networking/wget.c)
```c
			fprintf(stderr, "--> %s%s\n\n", s1, s2);
		fflush(fp);
		log_io("> %s%s", s1, s2);
	}

	/* Read until "Nxx something" is received */
	G.wget_buf[3] = 0;
	do {
		fgets_trim_sanitize(fp, "%s\n");
	} while (!isdigit(G.wget_buf[0]) || G.wget_buf[3] != ' ');

	G.wget_buf[3] = '\0';
	result = xatoi_positive(G.wget_buf);
	G.wget_buf[3] = ' ';
	return result;
}
#endif

static void parse_url(const char *src_url, struct host_info *h)
{
	char *url, *p, *sp;

	free(h->allocated);
	h->allocated = url = xstrdup(src_url);

	h->protocol = P_HTTP;
	p = strstr(url, "://");
	if (p) {
		*p = '\0';
		h->host = p + 3;
#if ENABLE_FEATURE_WGET_FTP
		if (strcmp(url, P_FTP) == 0) {
			h->port = bb_lookup_std_port(P_FTP, "tcp", 21);
			h->protocol = P_FTP;
		} else
#endif
#if FTPS_SUPPORTED
		if (strcmp(url, P_FTPS) == 0) {
			h->port = bb_lookup_std_port(P_FTPS, "tcp", 990);
			h->protocol = P_FTPS;
```

[Assistant]
diff --git a/networking/wget.c b/networking/wget.c
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -536,6 +536,15 @@ static void parse_url(const char *src_url, struct host_info *h)
 {
 	char *url, *p, *sp;

+	/* Fix for CVE-2025-60876 - don't allow control characters or spaces in the URL */
+	/* otherwise a malicious URL can be used to inject HTTP headers in the request */
+	const unsigned char *u = (void *) src_url;
+	while (*u) {
+		if (*u <= ' ')
+			bb_simple_error_msg_and_die("Unencoded control character found in the URL!");
+		u++;
+	}
+
 	free(h->allocated);
 	h->allocated = url = xstrdup(src_url);


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

[User]
# CVE
CVE-2025-6170: Stack-buffer-overflow (CWE-787 out-of-bounds write) in libxml2's xmllint interactive shell. Affects the 2.13.x series; nixpkgs carries it as the libxml2_13 compat attr.

# Vulnerable source (debugXML.c, xmllint.c)
```c
/* ==== file: debugXML.c ==== */
    if ((node == NULL) || (buffer == NULL))
        return (-1);

    path = xmlGetNodePath(node);
    if (path == NULL)
	return (-1);

    /*
     * This test prevents buffer overflow, because this routine
     * is only called by xmlShell, in which the second argument is
     * 500 chars long.
     * It is a dirty hack before a cleaner solution is found.
     * Documentation should mention that the second argument must
     * be at least 500 chars long, and could be stripped if too long.
     */
    snprintf(buffer, 499, "%s", path);
    buffer[499] = '0';
    xmlFree(path);

    return (0);
}

/**
 * xmlShell:
 * @doc:  the initial document
 * @filename:  the output buffer
 * @input:  the line reading function
 * @output:  the output FILE*, defaults to stdout if NULL
 *
 * Implements the XML shell
 * This allow to load, validate, view, modify and save a document
 * using a environment similar to a UNIX commandline.
 */
void
xmlShell(xmlDocPtr doc, const char *filename, xmlShellReadlineFunc input,
         FILE * output)
{
    char prompt[500] = "/ > ";
    char *cmdline = NULL, *cur;
    char command[100];
    char arg[400];
    int i;
    xmlShellCtxtPtr ctxt;
    xmlXPathObjectPtr list;

    if (doc == NULL)
        return;
    if (filename == NULL)
        return;
    if (input == NULL)
        return;
    if (output == NULL)
        output = stdout;
    ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
    if (ctxt == NULL)
        /* ... */
                     (ctxt->node->ns->prefix), ctxt->node->name);
        else if ((ctxt->node != NULL) && (ctxt->node->name))
            snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
        else
            snprintf(prompt, sizeof(prompt), "? > ");
        prompt[sizeof(prompt) - 1] = 0;

        /*
         * Get a new command line
         */
        cmdline = ctxt->input(prompt);
        if (cmdline == NULL)
            break;

        /*
         * Parse the command itself
         */
        cur = cmdline;
        while ((*cur == ' ') || (*cur == '\t'))
            cur++;
        i = 0;
        while ((*cur != ' ') && (*cur != '\t') &&
               (*cur != '\n') && (*cur != '\r')) {
            if (*cur == 0)
                break;
            command[i++] = *cur++;
        }
        command[i] = 0;
        if (i == 0)
            continue;

        /*
         * Parse the argument
         */
        while ((*cur == ' ') || (*cur == '\t'))
            cur++;
        i = 0;
        while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
            if (*cur == 0)
                break;
            arg[i++] = *cur++;
        }
        arg[i] = 0;

        /*
         * start interpreting the command
         */
        if (!strcmp(command, "exit"))
            break;
        if (!strcmp(command, "quit"))
            break;
        if (!strcmp(command, "bye"))
            break;
		if (!strcmp(command, "help")) {
		  fprintf(ctxt->output, "\tbase         display XML base of the node\n");

/* ==== file: xmllint.c ==== */

    xmlHTMLPrintFileInfo(input);

    fprintf(ERR_STREAM, "<b>validity warning</b>: ");
    va_start(args, msg);
    len = strlen(buffer);
    vsnprintf(&buffer[len],  sizeof(buffer) - len, msg, args);
    va_end(args);
    xmlHTMLEncodeSend();
    fprintf(ERR_STREAM, "</p>\n");

    xmlHTMLPrintFileContext(input);
    xmlHTMLEncodeSend();
}

/************************************************************************
 *									*
 *			Shell Interface					*
 *									*
 ************************************************************************/
#ifdef LIBXML_DEBUG_ENABLED
#ifdef LIBXML_XPATH_ENABLED
/**
 * xmlShellReadline:
 * @prompt:  the prompt value
 *
 * Read a string
 *
 * Returns a pointer to it or NULL on EOF the caller is expected to
 *     free the returned string.
 */
static char *
xmlShellReadline(char *prompt) {
#ifdef HAVE_LIBREADLINE
    char *line_read;

    /* Get a line from the user. */
    line_read = readline (prompt);

    /* If the line has any text in it, save it on the history. */
    if (line_read && *line_read)
	add_history (line_read);

    return (line_read);
#else
    char line_read[501];
    char *ret;
    int len;

    if (prompt != NULL)
	fprintf(stdout, "%s", prompt);
    fflush(stdout);
    if (!fgets(line_read, 500, stdin))
        return(NULL);
    line_read[500] = 0;
    len = strlen(line_read);
    ret = (char *) malloc(len + 1);
    if (ret != NULL) {
	memcpy (ret, line_read, len + 1);
    }
    return(ret);
#endif
}
#endif /* LIBXML_XPATH_ENABLED */
#endif /* LIBXML_DEBUG_ENABLED */

/************************************************************************
 *									*
 *			I/O Interfaces					*
 *									*
```

[Assistant]
diff --git a/debugXML.c b/debugXML.c
--- a/debugXML.c
+++ b/debugXML.c
@@ -2780,6 +2780,10 @@ xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
     return (0);
 }

+#define MAX_PROMPT_SIZE     500
+#define MAX_ARG_SIZE        400
+#define MAX_COMMAND_SIZE    100
+
 /**
  * xmlShell:
  * @doc:  the initial document
@@ -2795,10 +2799,10 @@ void
 xmlShell(xmlDocPtr doc, const char *filename, xmlShellReadlineFunc input,
          FILE * output)
 {
-    char prompt[500] = "/ > ";
+    char prompt[MAX_PROMPT_SIZE] = "/ > ";
     char *cmdline = NULL, *cur;
-    char command[100];
-    char arg[400];
+    char command[MAX_COMMAND_SIZE];
+    char arg[MAX_ARG_SIZE];
     int i;
     xmlShellCtxtPtr ctxt;
     xmlXPathObjectPtr list;
@@ -2856,7 +2860,8 @@ xmlShell(xmlDocPtr doc, const char *filename, xmlShellReadlineFunc input,
             cur++;
         i = 0;
         while ((*cur != ' ') && (*cur != '\t') &&
-               (*cur != '\n') && (*cur != '\r')) {
+               (*cur != '\n') && (*cur != '\r') &&
+               (i < (MAX_COMMAND_SIZE - 1))) {
             if (*cur == 0)
                 break;
             command[i++] = *cur++;
@@ -2871,7 +2876,7 @@ xmlShell(xmlDocPtr doc, const char *filename, xmlShellReadlineFunc input,
         while ((*cur == ' ') || (*cur == '\t'))
             cur++;
         i = 0;
-        while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
+        while ((*cur != '\n') && (*cur != '\r') && (*cur != 0) && (i < (MAX_ARG_SIZE-1))) {
             if (*cur == 0)
                 break;
             arg[i++] = *cur++;
diff --git a/xmllint.c b/xmllint.c
--- a/xmllint.c
+++ b/xmllint.c
@@ -724,6 +724,9 @@ xmlHTMLValidityWarning(void *ctx, const char *msg, ...)
  ************************************************************************/
 #ifdef LIBXML_DEBUG_ENABLED
 #ifdef LIBXML_XPATH_ENABLED
+
+#define MAX_PROMPT_SIZE     500
+
 /**
  * xmlShellReadline:
  * @prompt:  the prompt value
@@ -754,9 +757,9 @@ xmlShellReadline(char *prompt) {
     if (prompt != NULL)
 	fprintf(stdout, "%s", prompt);
     fflush(stdout);
-    if (!fgets(line_read, 500, stdin))
+    if (!fgets(line_read, MAX_PROMPT_SIZE, stdin))
         return(NULL);
-    line_read[500] = 0;
+    line_read[MAX_PROMPT_SIZE] = 0;
     len = strlen(line_read);
     ret = (char *) malloc(len + 1);
     if (ret != NULL) {


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

[User]
# CVE
CVE-2025-64503: Out-of-bounds write (CWE-787) in libcupsfilters 2.1.1 cfFilterPDFToRaster() via the bundled PDF-to-raster filter. Reported as GHSA-893j-2wr2-wrh9.

# Vulnerable source (cupsfilters/pdftoraster.c)
```c
               "cfFilterPDFToRaster: cropbox = [ %f %f %f %f ]; rotate = %d",
               cropBox.x1, cropBox.x2, cropBox.y1, cropBox.y2,
               rotate);

  // Enter input page dimensions in header, so that if no page size got
  // specified for the job, the input size gets used via the header
  l = cropBox.x2 - cropBox.x1;
  if (l<0)
    l = -l;

  if (rotate == 90 || rotate == 270)
  doc->header.cupsPageSize[1] = l;
  else
  doc->header.cupsPageSize[0] = l;

  l = cropBox.y2 - cropBox.y1;
  if (l < 0)
    l = -l;
  if (rotate == 90 || rotate == 270)
    doc->header.cupsPageSize[0] = l;
  else
    doc->header.cupsPageSize[1] = l;
  if (rotate == 90 || rotate == 270)
  {
    doc->header.cupsImagingBBox[0] =
      doc->header.cupsPageSize[0] - cropBox.y1;
    doc->header.cupsImagingBBox[1] = cropBox.x2;
    doc->header.cupsImagingBBox[2] =
      doc->header.cupsPageSize[0] - cropBox.y2;
    doc->header.cupsImagingBBox[3] = cropBox.x1;
  }
 else
  {
    doc->header.cupsImagingBBox[0] = cropBox.x1;
    doc->header.cupsImagingBBox[1] =
      doc->header.cupsPageSize[1] - cropBox.y1;
    doc->header.cupsImagingBBox[2] = cropBox.x2;
    doc->header.cupsImagingBBox[3] =
      doc->header.cupsPageSize[1] - cropBox.y2;
  }
```

[Assistant]
diff --git a/cupsfilters/pdftoraster.c b/cupsfilters/pdftoraster.c
index fca1b48..56616c2 100644
--- a/cupsfilters/pdftoraster.c
+++ b/cupsfilters/pdftoraster.c
@@ -1814,6 +1814,20 @@ out_page(pdftoraster_doc_t *doc,
     doc->header.cupsPageSize[0] = l;
   else
     doc->header.cupsPageSize[1] = l;
+
+  //
+  // Maximum allowed page size for PDF is 200x200 inches (~ 5x5 m), or 14400x14400 pt
+  // https://community.adobe.com/t5/indesign-discussions/maximum-width-of-a-pdf/td-p/9217372
+  //
+  if (doc->header.cupsPageSize[0] > 14400) {
+    fprintf(stderr, "ERROR: Page width is %.2fpt, too large, cropping to 14400pt\n", doc->header.cupsPageSize[0]);
+    doc->header.cupsPageSize[0] = 14400;
+  }
+  if (doc->header.cupsPageSize[1] > 14400) {
+    fprintf(stderr, "ERROR: Page height is %.2fpt, too large, cropping to 14400pt\n", doc->header.cupsPageSize[1]);
+    doc->header.cupsPageSize[1] = 14400;
+  }
+
   if (rotate == 90 || rotate == 270)
   {
     doc->header.cupsImagingBBox[0] =


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

[User]
# CVE
CVE-2025-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]
diff --git a/libxslt/xsltutils.h b/libxslt/xsltutils.h
index 2514774b3f11a..1e753eebadd98 100644
--- a/libxslt/xsltutils.h
+++ b/libxslt/xsltutils.h
@@ -261,6 +261,10 @@ XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL
 #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
@@ -268,6 +272,10 @@ xsltSetSourceNodeFlags(xsltTransformContextPtr ctxt, xmlNodePtr node,
                        int flags);
 int
 xsltClearSourceNodeFlags(xmlNodePtr node, int flags);
+int
+xsltSetSourceNodeValue(xmlNodePtr node, int value);
+int
+xsltGetSourceNodeValue(xmlNodePtr node);
 void **
 xsltGetPSVIPtr(xmlNodePtr cur);
 /** DOC_ENABLE */


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

[User]
# CVE
CVE-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]
diff --git a/include/libxml/relaxng.h b/include/libxml/relaxng.h
index eafc660..099dacd 100644
--- a/include/libxml/relaxng.h
+++ b/include/libxml/relaxng.h
@@ -136,6 +136,10 @@ XMLPUBFUN int
 		    xmlRelaxParserSetFlag	(xmlRelaxNGParserCtxt *ctxt,
 						 int flag);

+XMLPUBFUN int
+		    xmlRelaxParserSetIncLImit	(xmlRelaxNGParserCtxt *ctxt,
+						 int limit);
+
 XMLPUBFUN void
 		    xmlRelaxNGFreeParserCtxt	(xmlRelaxNGParserCtxt *ctxt);
 XMLPUBFUN void
diff --git a/relaxng.c b/relaxng.c
index 1d74ba9..c0e94a3 100644
--- a/relaxng.c
+++ b/relaxng.c
@@ -18,6 +18,8 @@

 #ifdef LIBXML_RELAXNG_ENABLED

+#include <errno.h>
+#include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <stddef.h>
@@ -44,6 +46,12 @@
 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) &&					\
@@ -218,6 +226,7 @@ struct _xmlRelaxNGParserCtxt {
     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 */

@@ -1342,6 +1351,23 @@ xmlRelaxParserSetFlag(xmlRelaxNGParserCtxt *ctxt, int flags)
     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				*
@@ -1397,7 +1423,7 @@ xmlRelaxReadMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *buf, int size) {
  *
  * @param ctxt  the parser context
  * @param value  the element doc
- * @returns 0 in case of error, the index in the stack otherwise
+ * @returns -1 in case of error, the index in the stack otherwise
  */
 static int
 xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
@@ -1411,9 +1437,15 @@ xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
                                                sizeof(ctxt->incTab[0]));
         if (ctxt->incTab == NULL) {
             xmlRngPErrMemory(ctxt);
-            return (0);
+            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 =
@@ -1422,7 +1454,7 @@ xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
                                                 sizeof(ctxt->incTab[0]));
         if (ctxt->incTab == NULL) {
             xmlRngPErrMemory(ctxt);
-            return (0);
+            return (-1);
         }
     }
     ctxt->incTab[ctxt->incNr] = value;
@@ -1586,7 +1618,9 @@ xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL,
     /*
      * push it on the stack
      */
-    xmlRelaxNGIncludePush(ctxt, ret);
+    if (xmlRelaxNGIncludePush(ctxt, ret) < 0) {
+        return (NULL);
+    }

     /*
      * Some preprocessing of the document content, this include recursing
@@ -7261,11 +7295,32 @@ xmlRelaxNGParse(xmlRelaxNGParserCtxt *ctxt)
     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
      */


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

[User]
# CVE
CVE-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]
diff --git a/catalog.c b/catalog.c
index 46b877e..fa6d77c 100644
--- a/catalog.c
+++ b/catalog.c
@@ -1223,9 +1223,27 @@ xmlParseXMLCatalogNode(xmlNodePtr cur, xmlCatalogPrefer prefer,
 		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) {


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

[User]
# CVE
CVE-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]
diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c
--- a/src/tools/pkcs11-tool.c
+++ b/src/tools/pkcs11-tool.c
@@ -1342,6 +1342,8 @@ int main(int argc, char * argv[])
 		}
 		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);
 		}
 	}
@@ -9608,6 +9610,10 @@ static CK_SESSION_HANDLE test_kpgen_certwrite(CK_SLOT_ID slot, CK_SESSION_HANDLE
 		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 */


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

[User]
# CVE
CVE-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]
diff --git a/lib/Bytes/Random/Secure.pm b/lib/Bytes/Random/Secure.pm
index 65fbfe2..5bd3714 100644
--- a/lib/Bytes/Random/Secure.pm
+++ b/lib/Bytes/Random/Secure.pm
@@ -156,6 +156,7 @@ sub _build_attributes {
       $self->{$arg} = exists $args->{$arg} ? $args->{$arg} : $default;
     }

+    $self->{_pid} = $$;
     $self->{_RNG} = undef;    # Lazy initialization.
     return $self;
 }
@@ -171,6 +172,8 @@ sub _instantiate_rng {
     my @seeds = $self->_generate_seed( %seed_opts );
     $self->{_RNG} = Math::Random::ISAAC->new(@seeds);

+    $self->{_pid} = $$;
+
     return $self->{_RNG};
 }

@@ -224,7 +227,7 @@ sub bytes {
   $bytes = defined $bytes ? $bytes : 0; # Default to zero bytes.
   $self->_validate_int( $bytes ); # Throws on violation.

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

   my $str = '';

@@ -302,7 +305,7 @@ sub _ranged_randoms {
     $count = defined $count ? $count : 0;

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

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

@@ -354,7 +357,7 @@ sub _closest_divisor {

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


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

[User]
# CVE
CVE-2026-2903: Null pointer dereference in re2c 4.4: check_and_merge_special_rules() in src/parse/ast.cc does not verify whether a grammar block has any rules before proceeding with determinization, allowing crafted input that specifies entry, pre-rule, or post-rule hooks without any rules to reach the determinization phase with a null root TNFA node and crash the re2c process.

# Vulnerable source (src/parse/ast.cc)
```cpp
Ret check_and_merge_special_rules(AstGrams& grams, const opt_t* opts, Msg& msg, Ast& ast) {
    if (grams.empty()) return Ret::OK;

    for (const AstGram& g : grams) {
        // Check for redundant special rules and actions.
#define CHECK_SPECIAL(what, str) \
        if (g.what.size() > 1) { \
            RET_FAIL(msg.error(g.what[1]->loc, "%s %sis already defined at line %u", \
                str, incond(g.name).c_str(), g.what[0]->loc.line)); \
        }
        CHECK_SPECIAL(defs, "default rule");
        CHECK_SPECIAL(entry, "entry action");
        CHECK_SPECIAL(pre_rule, "pre-rule action");
        CHECK_SPECIAL(post_rule, "post-rule action");
#undef CHECK_SPECIAL
    }

    if (!opts->start_conditions) {
        // normal mode: there must be no named grams corresponding to conditions
        for (const AstGram& g : grams) {
            if (!g.name.empty()) { // found named gram
                RET_FAIL(msg.error(find_rule_location(g),
                    "conditions are only allowed with '-c', '--conditions' option"));
            }
        }
    } else if (grams.size() == 1 && grams[0].name.empty()) {
        // condition mode, a single unnamed gram => ok, normal blocks are allowed
    } else {
        // condition mode, at least one named gram => this is a block with conditions
        for (const AstGram& g : grams) {
            if (g.name.empty()) { // found unnamed gram
                RET_FAIL(msg.error(find_rule_location(g),
                    "cannot mix conditions with normal rules"));
            }
        }

        // Check for redundant actions in `<*>` condiiton or nonexistent conditions.
#define CHECK_ACTION(action, str) do { \
        bool all_conds_have_it = true; \
        const SemAct* star_action = nullptr; \
        for (const AstGram& g : grams) { \
            if (g.action.empty()) { \
                all_conds_have_it = false; \
            } else if (g.name == STAR_COND) { \
                star_action = g.action[0]; \
            } else if (g.rules.empty()) { \
                RET_FAIL(msg.error(g.action[0]->loc, \
                    "%s action for non-existing condition `%s` found", \
                    str, g.name.c_str())); \
            } \
```

[Assistant]
--- a/src/parse/ast.cc
+++ b/src/parse/ast.cc
@@ -332,10 +332,6 @@ Ret check_and_merge_special_rules(AstGrams& grams, const opt_t* opts, Msg& msg,
             all_conds_have_it = false; \
         } else if (g.name == STAR_COND) { \
             star_action = g.action[0]; \
-            } else if (g.rules.empty()) { \
-                RET_FAIL(msg.error(g.action[0]->loc, \
-                    "%s action for non-existing condition `%s` found", \
-                    str, g.name.c_str())); \
         } \
         if (star_action && all_conds_have_it) { \
@@ -422,6 +418,21 @@ Ret check_and_merge_special_rules(AstGrams& grams, const opt_t* opts, Msg& msg,
         }
     }

+    for (const AstGram& g : grams) {
+        if (g.rules.empty()) {
+#define CHECK_ACTION(action, str) do { \
+            if (!g.action.empty()) { \
+                RET_FAIL(msg.error(g.action[0]->loc, \
+                    "%s action %sbut no rules found", str, incond(g.name).c_str())); \
+            } \
+} while(0)
+            CHECK_ACTION(entry, "entry");
+            CHECK_ACTION(pre_rule, "pre-rule");
+            CHECK_ACTION(post_rule, "post-rule");
+#undef CHECK_ACTION
+        }
+    }
+


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

[User]
# CVE
CVE-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]
--- a/src/reqs.c
+++ b/src/reqs.c
@@ -847,7 +847,7 @@ static int is_chunked_transfer (pseudomap *hashofheaders)
 {
         char *data;
         data = pseudomap_find (hashofheaders, "transfer-encoding");
-        return data ? !strcmp (data, "chunked") : 0;
+        return data ? !strcasecmp (data, "chunked") : 0;
 }


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

[User]
# CVE
CVE-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]
diff --git a/src/jv.c b/src/jv.c
index 722a539391..2a62b48419 100644
--- a/src/jv.c
+++ b/src/jv.c
@@ -1114,7 +1114,12 @@ 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
+  // 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;
@@ -1174,6 +1179,10 @@ static uint32_t jvp_string_remaining_space(jvp_string* s) {
 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) {


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

[User]
# CVE
CVE-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]
diff --git a/telnetd/pty.c b/telnetd/pty.c
index c727e7be..f3518049 100644
--- a/telnetd/pty.c
+++ b/telnetd/pty.c
@@ -129,6 +129,14 @@ start_login (char *host, int autologin, char *name)
   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);


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

[User]
# CVE
CVE-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]
diff --git a/nltk/downloader.py b/nltk/downloader.py
index a8010f5cd2..c181b94361 100644
--- a/nltk/downloader.py
+++ b/nltk/downloader.py
@@ -216,10 +216,22 @@ def __init__(
         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."""

@@ -677,6 +689,18 @@ def _download_package(self, info, download_dir, force):

         # 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)