[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-2011-10007: 2-argument open() injection (CWE-78/CWE-73) in the Perl module File::Find::Rule (<= 0.34). Perl's 2-arg open interprets a leading '>', '>>', or '|' in the string as a mode/pipe, so a file whose basename is e.g. Merely running File::Find::Rule->grep over a directory that contains an attacker-named file therefore yields arbitrary file write or command execution. nixpkgs ships File::Find::Rule 0.34 (perlPackages.FileFindRule).

# Vulnerable source (lib/File/Find/Rule.pm)
```perl
them in anonymous arrays.  Should a negative specifier match the
iteration is aborted and the clause is failed.  For example:

 $rule->grep( qr/^#!.*\bperl/, [ sub { 1 } ] );

Is a passing clause if the first line of a file looks like a perl
shebang line.

=cut

sub grep {
    my $self = _force_object shift;
    my @pattern = map {
        ref $_
          ? ref $_ eq 'ARRAY'
            ? map { [ ( ref $_ ? $_ : qr/$_/ ) => 0 ] } @$_
            : [ $_ => 1 ]
          : [ qr/$_/ => 1 ]
      } @_;

    $self->exec( sub {
        local *FILE;
        open FILE, $_ or return;
        local ($_, $.);
        while (<FILE>) {
            for my $p (@pattern) {
                my ($rule, $ret) = @$p;
                return $ret
                  if ref $rule eq 'Regexp'
                    ? /$rule/
                      : $rule->(@_);
            }
        }
        return;
    } );
}

=item C<maxdepth( $level )>

Descend at most C<$level> (a non-negative integer) levels of directories
```

[Assistant]
diff --git a/lib/File/Find/Rule.pm b/lib/File/Find/Rule.pm
--- a/lib/File/Find/Rule.pm
+++ b/lib/File/Find/Rule.pm
@@ -420,7 +420,7 @@ sub grep {

     $self->exec( sub {
         local *FILE;
-        open FILE, $_ or return;
+        open FILE, '<', $_ or return;
         local ($_, $.);
         while (<FILE>) {
             for my $p (@pattern) {


[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-2014-9913: unzip list_files() uses a 4-byte output slot for the algorithm label in its file listing; the unpatched code writes a 3-digit decimal string without checking if the algorithm index has grown beyond the 3-digit range, so an oversized index overruns the 4-byte slot and corrupts an adjacent byte on the heap.

# Vulnerable source (list.c)
```c
            } else
#endif /* USE_EF_UT_TIME */
            {
                yr = ((((unsigned)(G.crec.last_mod_dos_datetime >> 25) & 0x7f)
                       + 1980));
                mo = ((unsigned)(G.crec.last_mod_dos_datetime >> 21) & 0x0f);
                dy = ((unsigned)(G.crec.last_mod_dos_datetime >> 16) & 0x1f);
                hh = (((unsigned)G.crec.last_mod_dos_datetime >> 11) & 0x1f);
                mm = (((unsigned)G.crec.last_mod_dos_datetime >> 5) & 0x3f);
            }
            /* permute date so it displays according to nat'l convention
             * ('methnum' is not yet set, it is used as temporary buffer) */
            switch (date_format) {
                case DF_YMD:
                    methnum = mo;
                    mo = yr; yr = dy; dy = methnum;
                    break;
                case DF_DMY:
                    methnum = mo;
                    mo = dy; dy = methnum;
            }

            csiz = G.crec.csize;
            if (G.crec.general_purpose_bit_flag & 1)
                csiz -= 12;   /* if encrypted, don't count encryption header */
            if ((cfactor = ratio(G.crec.ucsize, csiz)) < 0) {
#ifndef WINDLL
                sgn = '-';
#endif
                cfactor = (-cfactor + 5) / 10;
            } else {
#ifndef WINDLL
                sgn = ' ';
#endif
                cfactor = (cfactor + 5) / 10;
            }

            methnum = find_compr_idx(G.crec.compression_method);
            zfstrcpy(methbuf, method[methnum]);
            if (G.crec.compression_method == DEFLATED ||
                G.crec.compression_method == ENHDEFLATED) {
                methbuf[5] = dtype[(G.crec.general_purpose_bit_flag>>1) & 3];
            } else if (methnum >= NUM_METHODS) {
                sprintf(&methbuf[4], "%03u", G.crec.compression_method);
            }

#if 0       /* GRR/Euro:  add this? */
#if defined(DOS_FLX_NLM_OS2_W32) || defined(THEOS) || defined(UNIX)
            for (p = G.filename;  *p;  ++p)
                if (!isprint(*p))
                    *p = '?';  /* change non-printable chars to '?' */
#endif /* DOS_FLX_NLM_OS2_W32 || THEOS || UNIX */
#endif /* 0 */

#ifdef WINDLL
            /* send data to application for formatting and printing */
            if (G.lpUserFunctions->SendApplicationMessage != NULL)
                (*G.lpUserFunctions->SendApplicationMessage)(G.crec.ucsize,
                  csiz, (unsigned)cfactor, mo, dy, yr, hh, mm,
                  (char)(G.pInfo->lcflag ? '^' : ' '),
                  (LPCSTR)fnfilter(G.filename, slide, (WSIZE>>1)),
                  (LPCSTR)methbuf, G.crec.crc32,
                  (char)((G.crec.general_purpose_bit_flag & 1) ? 'E' : ' '));
            else if (G.lpUserFunctions->SendApplicationMessage_i32 != NULL) {
                unsigned long ucsize_lo, csiz_lo;
                unsigned long ucsize_hi=0L, csiz_hi=0L;
                ucsize_lo = (unsigned long)(G.crec.ucsize);
                csiz_lo = (unsigned long)(csiz);
#ifdef ZIP64_SUPPORT
                ucsize_hi = (unsigned long)(G.crec.ucsize >> 32);
                csiz_hi = (unsigned long)(csiz >> 32);
#endif /* ZIP64_SUPPORT */
                (*G.lpUserFunctions->SendApplicationMessage_i32)(ucsize_lo,
                    ucsize_hi, csiz_lo, csiz_hi, (unsigned)cfactor,
                    mo, dy, yr, hh, mm,
                    (char)(G.pInfo->lcflag ? '^' : ' '),
                    (LPCSTR)fnfilter(G.filename, slide, (WSIZE>>1)),
                    (LPCSTR)methbuf, G.crec.crc32,
                    (char)((G.crec.general_purpose_bit_flag & 1) ? 'E' : ' '));
            }
#else /* !WINDLL */
            if (cfactor == 100)
                sprintf(cfactorstr, LoadFarString(CompFactor100));
            else
                sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
            if (longhdr)
                Info(slide, 0, ((char *)slide, LoadFarString(LongHdrStats),
```

[Assistant]
diff --git a/list.c b/list.c
--- a/list.c
+++ b/list.c
@@ -339,7 +339,18 @@
                 G.crec.compression_method == ENHDEFLATED) {
                 methbuf[5] = dtype[(G.crec.general_purpose_bit_flag>>1) & 3];
             } else if (methnum >= NUM_METHODS) {
-                sprintf(&methbuf[4], "%03u", G.crec.compression_method);
+                /* 2013-02-26 SMS.
+                 * http://sourceforge.net/p/infozip/bugs/27/  CVE-2014-9913.
+                 * Unexpectedly large compression methods overflow
+                 * &methbuf[].  Use the old, three-digit decimal format
+                 * for values which fit.  Otherwise, sacrifice the
+                 * colon, and use four-digit hexadecimal.
+                 */
+                if (G.crec.compression_method <= 999) {
+                    sprintf( &methbuf[ 4], "%03u", G.crec.compression_method);
+                } else {
+                    sprintf( &methbuf[ 3], "%04X", G.crec.compression_method);
+                }
             }

 #if 0       /* GRR/Euro:  add this? */


[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-2015-1419: vsftpd vsf_filename_passes_filter() compares the deny-file pattern against the raw FTP-supplied filename without first resolving symlinks; a user can point a symlink at a forbidden destination and bypass the block entirely since the matcher sees only the link name, not the resolved absolute location.

# Vulnerable source (ls.c)
```c
/*
 * Part of Very Secure FTPd
 * Licence: GPL v2
 * Author: Chris Evans
 * ls.c
 *
 * Would you believe, code to handle directory listing.
 */

#include "ls.h"
#include "access.h"
#include "defs.h"
#include "str.h"
#include "strlist.h"
#include "sysstr.h"
#include "sysutil.h"
#include "tunables.h"

static void build_dir_line(struct mystr* p_str,
                           const struct mystr* p_filename_str,
                           const struct vsf_sysutil_statbuf* p_stat,
                           long curr_time);

void
vsf_ls_populate_dir_list(struct mystr_list* p_list,
                         struct mystr_list* p_subdir_list,
                         struct vsf_sysutil_dir* p_dir,
                         const struct mystr* p_base_dir_str,
                         const struct mystr* p_option_str,
                         const struct mystr* p_filter_str,
                         int is_verbose)
{
  struct mystr dirline_str = INIT_MYSTR;
  struct mystr normalised_base_dir_str = INIT_MYSTR;
  struct str_locate_result loc_result;
  int a_option;
  int r_option;
  int t_option;
  int F_option;
  int do_stat = 0;
  long curr_time = 0;
  loc_result = str_locate_char(p_option_str, 'a');
  a_option = loc_result.found;
  loc_result = str_locate_char(p_option_str, 'r');
  r_option = loc_result.found;
  loc_result = str_locate_char(p_option_str, 't');
  t_option = loc_result.found;
  loc_result = str_locate_char(p_option_str, 'F');
  F_option = loc_result.found;
  loc_result = str_locate_char(p_option_str, 'l');
  if (loc_result.found)
  {
    is_verbose = 1;
  }
  /* Invert "reverse" arg for "-t", the time sorting */
  if (t_option)
  {
    r_option = !r_option;
  }
  if (is_verbose || t_option || F_option || p_subdir_list != 0)
  {
    do_stat = 1;
  }
  /* If the filter starts with a . then implicitly enable -a */
  if (!str_isempty(p_filter_str) && str_get_char_at(p_filter_str, 0) == '.')
  {
    a_option = 1;
  }
  /* "Normalise" the incoming base directory string by making sure it
   * ends in a '/' if it is nonempty
   */
  if (!str_equal_text(p_base_dir_str, "."))
  {
    str_copy(&normalised_base_dir_str, p_base_dir_str);
  }
  if (!str_isempty(&normalised_base_dir_str))
  {
    unsigned int len = str_getlen(&normalised_base_dir_str);
    if (str_get_char_at(&normalised_base_dir_str, len - 1) != '/')
    {
      str_append_char(&normalised_base_dir_str, '/');
    }
  }
  /* If we're going to need to do time comparisions, cache the local time */
  if (is_verbose)
  {
    curr_time = vsf_sysutil_get_time_sec();
  }
  while (1)
  {
    static struct mystr s_next_filename_str;
    static struct mystr s_next_path_and_filename_str;
    static struct vsf_sysutil_statbuf* s_p_statbuf;
    str_next_dirent(&s_next_filename_str, p_dir);
    if (str_isempty(&s_next_filename_str))
    {
      break;
    }
    {
      unsigned int len = str_getlen(&s_next_filename_str);
      if (len > 0 && str_get_char_at(&s_next_filename_str, 0) == '.')
      {
        if (!a_option && !tunable_force_dot_files)
        {
          continue;
        }
        if (!a_option &&
            ((len == 2 && str_get_char_at(&s_next_filename_str, 1) == '.') ||
             len == 1))
        {
          continue;
        }
      }
    }
    /* Don't show hidden directory entries */
    if (!vsf_access_check_file_visible(&s_next_filename_str))
    {
      continue;
    }
    /* If we have an ls option which is a filter, apply it */
    if (!str_isempty(p_filter_str))
    {
      unsigned int iters = 0;
      if (!vsf_filename_passes_filter(&s_next_filename_str, p_filter_str,
                                      &iters))
      {
        continue;
      }
    }
    /* Calculate the full path (relative to CWD) for lstat() and
     * output purposes
     */
    str_copy(&s_next_path_and_filename_str, &normalised_base_dir_str);
    str_append_str(&s_next_path_and_filename_str, &s_next_filename_str);
    if (do_stat)
    {
      /* lstat() the file. Of course there's a race condition - the
       * directory entry may have gone away whilst we read it, so
       * ignore failure to stat
       */
      int retval = str_lstat(&s_next_path_and_filename_str, &s_p_statbuf);
      if (vsf_sysutil_retval_is_error(retval))
      {
        continue;
      }
    }
    if (is_verbose)
    {
      static struct mystr s_final_file_str;
      /* If it's a damn symlink, we need to append the target */
      str_copy(&s_final_file_str, &s_next_filename_str);
      if (vsf_sysutil_statbuf_is_symlink(s_p_statbuf))
      {
        static struct mystr s_temp_str;
        int retval = str_readlink(&s_temp_str, &s_next_path_and_filename_str);
        if (retval == 0 && !str_isempty(&s_temp_str))
        {
          str_append_text(&s_final_file_str, " -> ");
          str_append_str(&s_final_file_str, &s_temp_str);
        }
      }
      if (F_option && vsf_sysutil_statbuf_is_dir(s_p_statbuf))
      {
        str_append_char(&s_final_file_str, '/');
      }
      build_dir_line(&dirline_str, &s_final_file_str, s_p_statbuf, curr_time);
    }
    else
    {
      /* Just emit the filenames - note, we prepend the directory for NLST
       * but not for LIST
       */
      str_copy(&dirline_str, &s_next_path_and_filename_str);
      if (F_option)
      {
        if (vsf_sysutil_statbuf_is_dir(s_p_statbuf))
        {
          str_append_char(&dirline_str, '/');
        }
        else if (vsf_sysutil_statbuf_is_symlink(s_p_statbuf))
        {
          str_append_char(&dirline_str, '@');
        }
      }
      str_append_text(&dirline_str, "\r\n");
    }
    /* Add filename into our sorted list - sorting by filename or time. Also,
     * if we are required to, maintain a distinct list of direct
     * subdirectories.
     */
    {
      static struct mystr s_temp_str;
      const struct mystr* p_sort_str = 0;
      const struct mystr* p_sort_subdir_str = 0;
      if (!t_option)
      {
        p_sort_str = &s_next_filename_str;
      }
      else
      {
        str_alloc_text(&s_temp_str,
                       vsf_sysutil_statbuf_get_sortkey_mtime(s_p_statbuf));
        p_sort_str = &s_temp_str;
        p_sort_subdir_str = &s_temp_str;
      }
      str_list_add(p_list, &dirline_str, p_sort_str);
      if (p_subdir_list != 0 && vsf_sysutil_statbuf_is_dir(s_p_statbuf))
      {
        str_list_add(p_subdir_list, &s_next_filename_str, p_sort_subdir_str);
      }
    }
  } /* END: while(1) */
  str_list_sort(p_list, r_option);
  if (p_subdir_list != 0)
  {
    str_list_sort(p_subdir_list, r_option);
  }
  str_free(&dirline_str);
  str_free(&normalised_base_dir_str);
}

int
vsf_filename_passes_filter(const struct mystr* p_filename_str,
                           const struct mystr* p_filter_str,
                           unsigned int* iters)
{
  /* A simple routine to match a filename against a pattern.
   * This routine is used instead of e.g. fnmatch(3), because we should be
   * reluctant to trust the latter. fnmatch(3) involves _lots_ of string
   * parsing and handling. There is broad potential for any given fnmatch(3)
   * implementation to be buggy.
   *
   * Currently supported pattern(s):
   * - any number of wildcards, "*" or "?"
   * - {,} syntax (not nested)
   *
   * Note that pattern matching is only supported within the last path
   * component. For example, searching for /a/b/? will work, but searching
   * for /a/?/c will not.
   */
  struct mystr filter_remain_str = INIT_MYSTR;
  struct mystr name_remain_str = INIT_MYSTR;
  struct mystr temp_str = INIT_MYSTR;
  struct mystr brace_list_str = INIT_MYSTR;
  struct mystr new_filter_str = INIT_MYSTR;
  int ret = 0;
  char last_token = 0;
  int must_match_at_current_pos = 1;
  str_copy(&filter_remain_str, p_filter_str);
  str_copy(&name_remain_str, p_filename_str);

  while (!str_isempty(&filter_remain_str) && *iters < VSFTP_MATCHITERS_MAX)
  {
    static struct mystr s_match_needed_str;
    /* Locate next special token */
    struct str_locate_result locate_result =
      str_locate_chars(&filter_remain_str, "*?{");
    (*iters)++;
    /* Isolate text leading up to token (if any) - needs to be matched */
    if (locate_result.found)
    {
      unsigned int indexx = locate_result.index;
      str_left(&filter_remain_str, &s_match_needed_str, indexx);
      str_mid_to_end(&filter_remain_str, &temp_str, indexx + 1);
      str_copy(&filter_remain_str, &temp_str);
      last_token = locate_result.char_found;
    }
    else
    {
      /* No more tokens. Must match remaining filter string exactly. */
      str_copy(&s_match_needed_str, &filter_remain_str);
      str_empty(&filter_remain_str);
      last_token = 0;
    }
    if (!str_isempty(&s_match_needed_str))
    {
      /* Need to match something.. could be a match which has to start at
       * current position, or we could allow it to start anywhere
       */
      unsigned int indexx;
      locate_result = str_locate_str(&name_remain_str, &s_match_needed_str);
      if (!locate_result.found)
      {
        /* Fail */
        goto out;
      }
      indexx = locate_result.index;
      if (must_match_at_current_pos && indexx > 0)
      {
        goto out;
      }
      /* Chop matched string out of remainder */
      str_mid_to_end(&name_remain_str, &temp_str,
                     indexx + str_getlen(&s_match_needed_str));
      str_copy(&name_remain_str, &temp_str);
    }
    if (last_token == '?')
    {
      if (str_isempty(&name_remain_str))
      {
        goto out;
      }
      str_right(&name_remain_str, &temp_str, str_getlen(&name_remain_str) - 1);
      str_copy(&name_remain_str, &temp_str);
      must_match_at_current_pos = 1;
    }
    else if (last_token == '{')
    {
      struct str_locate_result end_brace =
        str_locate_char(&filter_remain_str, '}');
      must_match_at_current_pos = 1;
      if (end_brace.found)
      {
        str_split_char(&filter_remain_str, &temp_str, '}');
        str_copy(&brace_list_str, &filter_remain_str);
        str_copy(&filter_remain_str, &temp_str);
        str_split_char(&brace_list_str, &temp_str, ',');
        while (!str_isempty(&brace_list_str))
        {
          str_copy(&new_filter_str, &brace_list_str);
          str_append_str(&new_filter_str, &filter_remain_str);
          if (vsf_filename_passes_filter(&name_remain_str, &new_filter_str,
                                         iters))
          {
            ret = 1;
            goto out;
          }
          str_copy(&brace_list_str, &temp_str);
          str_split_char(&brace_list_str, &temp_str, ',');
        }
        goto out;
      }
      else if (str_isempty(&name_remain_str) ||
               str_get_char_at(&name_remain_str, 0) != '{')
      {
        goto out;
      }
      else
      {
        str_right(&name_remain_str, &temp_str,
                  str_getlen(&name_remain_str) - 1);
        str_copy(&name_remain_str, &temp_str);
      }
    }
    else
    {
      must_match_at_current_pos = 0;
    }
  }
  /* Any incoming string left means no match unless we ended on the correct
   * type of wildcard.
   */
  if (str_getlen(&name_remain_str) > 0 && last_token != '*')
  {
    goto out;
  }
  /* OK, a match */
  ret = 1;
  if (*iters == VSFTP_MATCHITERS_MAX) {
    ret = 0;
  }
out:
  str_free(&filter_remain_str);
  str_free(&name_remain_str);
  str_free(&temp_str);
  str_free(&brace_list_str);
  str_free(&new_filter_str);
  return ret;
}

static void
build_dir_line(struct mystr* p_str, const struct mystr* p_filename_str,
               const struct vsf_sysutil_statbuf* p_stat, long curr_time)
{
  static struct mystr s_tmp_str;
  filesize_t size = vsf_sysutil_statbuf_get_size(p_stat);
  /* Permissions */
  str_alloc_text(p_str, vsf_sysutil_statbuf_get_perms(p_stat));
  str_append_char(p_str, ' ');
  /* Hard link count */
  str_alloc_ulong(&s_tmp_str, vsf_sysutil_statbuf_get_links(p_stat));
  str_lpad(&s_tmp_str, 4);
  str_append_str(p_str, &s_tmp_str);
  str_append_char(p_str, ' ');
  /* User */
  if (tunable_hide_ids)
  {
    str_alloc_text(&s_tmp_str, "ftp");
  }
  else
  {
    int uid = vsf_sysutil_statbuf_get_uid(p_stat);
    struct vsf_sysutil_user* p_user = 0;
    if (tunable_text_userdb_names)
    {
      p_user = vsf_sysutil_getpwuid(uid);
    }
    if (p_user == 0)
    {
      str_alloc_ulong(&s_tmp_str, (unsigned long) uid);
    }
    else
    {
      str_alloc_text(&s_tmp_str, vsf_sysutil_user_getname(p_user));
    }
  }
  str_rpad(&s_tmp_str, 8);
  str_append_str(p_str, &s_tmp_str);
  str_append_char(p_str, ' ');
  /* Group */
  if (tunable_hide_ids)
  {
    str_alloc_text(&s_tmp_str, "ftp");
  }
  else
  {
    int gid = vsf_sysutil_statbuf_get_gid(p_stat);
    struct vsf_sysutil_group* p_group = 0;
    if (tunable_text_userdb_names)
    {
      p_group = vsf_sysutil_getgrgid(gid);
    }
    if (p_group == 0)
    {
```

[Assistant]
diff --git a/ls.c b/ls.c
--- a/ls.c
+++ b/ls.c
@@ -7,6 +7,7 @@
  * Would you believe, code to handle directory listing.
  */

+#include <stdlib.h>
 #include "ls.h"
 #include "access.h"
 #include "defs.h"
@@ -243,11 +244,42 @@ vsf_filename_passes_filter(const struct
   struct mystr temp_str = INIT_MYSTR;
   struct mystr brace_list_str = INIT_MYSTR;
   struct mystr new_filter_str = INIT_MYSTR;
+  struct mystr normalize_filename_str = INIT_MYSTR;
+  const char *normname;
+  const char *path;
   int ret = 0;
   char last_token = 0;
   int must_match_at_current_pos = 1;
+
   str_copy(&filter_remain_str, p_filter_str);
-  str_copy(&name_remain_str, p_filename_str);
+
+  /* normalize filepath */
+  path = str_strdup(p_filename_str);
+  normname = realpath(path, NULL);
+  if (normname == NULL)
+     goto out;
+  str_alloc_text(&normalize_filename_str, normname);
+
+  if (!str_isempty (&filter_remain_str) && !str_isempty(&normalize_filename_str)) {
+    if (str_get_char_at(p_filter_str, 0) == '/') {
+      if (str_get_char_at(&normalize_filename_str, 0) != '/') {
+        str_getcwd (&name_remain_str);
+
+        if (str_getlen(&name_remain_str) > 1) /* cwd != root dir */
+          str_append_char (&name_remain_str, '/');
+
+        str_append_str (&name_remain_str, &normalize_filename_str);
+      }
+      else
+       str_copy (&name_remain_str, &normalize_filename_str);
+    } else {
+      if (str_get_char_at(p_filter_str, 0) != '{')
+        str_basename (&name_remain_str, &normalize_filename_str);
+      else
+        str_copy (&name_remain_str, &normalize_filename_str);
+    }
+  } else
+    str_copy(&name_remain_str, &normalize_filename_str);

   while (!str_isempty(&filter_remain_str) && *iters < VSFTP_MATCHITERS_MAX)
   {
@@ -379,6 +411,9 @@ vsf_filename_passes_filter(const struct
     ret = 0;
   }
 out:
+  free((char*) normname);
+  free((char*) path);
+  str_free(&normalize_filename_str);
   str_free(&filter_remain_str);
   str_free(&name_remain_str);
   str_free(&temp_str);


[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-2016-9844: unzip zipinfo mode uses a 4-byte output slot for the algorithm label; the unpatched code writes a 3-digit decimal string without checking if the algorithm index has grown beyond the 3-digit range, so an oversized index overruns the slot and corrupts an adjacent byte.

# Vulnerable source (zipinfo.c)
```c
#endif
    int         k, error, error_in_archive=PK_COOL;
    unsigned    hostnum, hostver, methid, methnum, xattr;
    char        *p, workspace[12], attribs[16];
    char        methbuf[5];
    static ZCONST char dtype[5]="NXFS"; /* normal, maximum, fast, superfast */
    static ZCONST char Far os[NUM_HOSTS+1][4] = {
        "fat", "ami", "vms", "unx", "cms", "atr", "hpf", "mac", "zzz",
        "cpm", "t20", "ntf", "qds", "aco", "vft", "mvs", "be ", "nsk",
        "ths", "osx", "???", "???", "???", "???", "???", "???", "???",
        "???", "???", "???", "ath", "???"
    };
#ifdef OLD_THEOS_EXTRA
    static ZCONST char Far os_TheosOld[] = "tho";
#endif
    static ZCONST char Far method[NUM_METHODS+1][5] = {
        "stor", "shrk", "re:1", "re:2", "re:3", "re:4", "i#:#", "tokn",
        "def#", "d64#", "dcli", "bzp2", "lzma", "ters", "lz77", "wavp",
        "ppmd", "u###"
    };

/*---------------------------------------------------------------------------
    Print out various interesting things about the compressed file.
  ---------------------------------------------------------------------------*/

    methid = (unsigned)(G.crec.compression_method);
    methnum = find_compr_idx(G.crec.compression_method);
    hostnum = (unsigned)(G.pInfo->hostnum);
    hostver = (unsigned)(G.pInfo->hostver);
/*
    extnum = (unsigned)MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS);
    extver = (unsigned)G.crec.version_needed_to_extract[0];
 */

    zfstrcpy(methbuf, method[methnum]);
    if (methid == IMPLODED) {
        methbuf[1] = (char)((G.crec.general_purpose_bit_flag & 2)? '8' : '4');
        methbuf[3] = (char)((G.crec.general_purpose_bit_flag & 4)? '3' : '2');
    } else if (methid == DEFLATED || methid == ENHDEFLATED) {
        ush  dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3);
        methbuf[3] = dtype[dnum];
    } else if (methnum >= NUM_METHODS) {   /* unknown */
        sprintf(&methbuf[1], "%03u", G.crec.compression_method);
    }

    for (k = 0;  k < 15;  ++k)
        attribs[k] = ' ';
    attribs[15] = 0;

    xattr = (unsigned)((G.crec.external_file_attributes >> 16) & 0xFFFF);
    switch (hostnum) {
        case VMS_:
            {   int    i, j;

                for (k = 0;  k < 12;  ++k)
                    workspace[k] = 0;
                if (xattr & VMS_IRUSR)
                    workspace[0] = 'R';
                if (xattr & VMS_IWUSR) {
                    workspace[1] = 'W';
                    workspace[3] = 'D';
                }
                if (xattr & VMS_IXUSR)
                    workspace[2] = 'E';
                if (xattr & VMS_IRGRP)
                    workspace[4] = 'R';
                if (xattr & VMS_IWGRP) {
                    workspace[5] = 'W';
                    workspace[7] = 'D';
                }
                if (xattr & VMS_IXGRP)
                  workspace[6] = 'E';
                if (xattr & VMS_IROTH)
                    workspace[8] = 'R';
                if (xattr & VMS_IWOTH) {
                    workspace[9] = 'W';
                    workspace[11] = 'D';
                }
                if (xattr & VMS_IXOTH)
                    workspace[10] = 'E';

                p = attribs;
                for (k = j = 0;  j < 3;  ++j) {     /* groups of permissions */
                    for (i = 0;  i < 4;  ++i, ++k)  /* perms within a group */
                        if (workspace[k])
                            *p++ = workspace[k];
```

[Assistant]
diff --git a/zipinfo.c b/zipinfo.c
--- a/zipinfo.c
+++ b/zipinfo.c
@@ -1921,7 +1921,18 @@
         ush  dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3);
         methbuf[3] = dtype[dnum];
     } else if (methnum >= NUM_METHODS) {   /* unknown */
-        sprintf(&methbuf[1], "%03u", G.crec.compression_method);
+        /* 2016-12-05 SMS.
+         * https://launchpad.net/bugs/1643750
+         * Unexpectedly large compression methods overflow
+         * &methbuf[].  Use the old, three-digit decimal format
+         * for values which fit.  Otherwise, sacrifice the "u",
+         * and use four-digit hexadecimal.
+         */
+        if (G.crec.compression_method <= 999) {
+            sprintf( &methbuf[ 1], "%03u", G.crec.compression_method);
+        } else {
+            sprintf( &methbuf[ 0], "%04X", G.crec.compression_method);
+        }
     }

     for (k = 0;  k < 15;  ++k)


[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-2018-18384: unzip list_files() stores a compression-ratio string in a 10-byte on-stack buffer and writes it via an unchecked format call; an archive producing a ratio string longer than 9 bytes overruns the buffer and overwrites adjacent stack data.

# Vulnerable source (list.c)
```c
     "--------  ------  ------- ---- ---------- ----- --------  ----";
   static ZCONST char Far *Headers[][2] =
     { {HeadersS, HeadersS1}, {HeadersL, HeadersL1} };

   static ZCONST char Far CaseConversion[] =
     "%s (\"^\" ==> case\n%s   conversion)\n";
   static ZCONST char Far LongHdrStats[] =
     "%s  %-7s%s %4s %02u%c%02u%c%02u %02u:%02u %08lx %c";
   static ZCONST char Far LongFileTrailer[] =
     "--------          -------  ---                       \
     -------\n%s         %s %4s                            %lu file%s\n";
#ifdef OS2_EAS
   static ZCONST char Far ShortHdrStats[] =
     "%s %6lu %6lu  %02u%c%02u%c%02u %02u:%02u  %c";
   static ZCONST char Far ShortFileTrailer[] =
     "---------  -----  -----                \
     -------\n%s %6lu %6lu                     %lu file%s\n";
   static ZCONST char Far OS2ExtAttrTrailer[] =
     "%lu file%s %lu bytes of OS/2 extended attributes attached.\n";
   static ZCONST char Far OS2ACLTrailer[] =
     "%lu file%s %lu bytes of access control lists attached.\n";
#else
   static ZCONST char Far ShortHdrStats[] =
     "%s  %02u%c%02u%c%02u %02u:%02u  %c";
   static ZCONST char Far ShortFileTrailer[] =
     "---------                     -------\n%s\
                     %lu file%s\n";
#endif /* ?OS2_EAS */
#endif /* !WINDLL */

/*************************/
/* Function list_files() */
/*************************/

int list_files(__G)    /* return PK-type error code */
    __GDEF
{
    int do_this_file=FALSE, cfactor, error, error_in_archive=PK_COOL;
#ifndef WINDLL
    char sgn, cfactorstr[10];
    int longhdr=(uO.vflag>1);
#endif
    int date_format;
    char dt_sepchar;
    ulg members=0L;
    zusz_t j;
    unsigned methnum;
#ifdef USE_EF_UT_TIME
    iztimes z_utime;
    struct tm *t;
#endif
    unsigned yr, mo, dy, hh, mm;
    zusz_t csiz, tot_csize=0L, tot_ucsize=0L;
#ifdef OS2_EAS
    ulg ea_size, tot_easize=0L, tot_eafiles=0L;
    ulg acl_size, tot_aclsize=0L, tot_aclfiles=0L;
#endif
    min_info info;
    char methbuf[8];
    static ZCONST char dtype[]="NXFS";  /* see zi_short() */
    static ZCONST char Far method[NUM_METHODS+1][8] =
        {"Stored", "Shrunk", "Reduce1", "Reduce2", "Reduce3", "Reduce4",
         "Implode", "Token", "Defl:#", "Def64#", "ImplDCL", "BZip2",
         "LZMA", "Terse", "IBMLZ77", "WavPack", "PPMd", "Unk:###"};

/*---------------------------------------------------------------------------
    Unlike extract_or_test_files(), this routine confines itself to the cen-
    tral directory.  Thus its structure is somewhat simpler, since we can do
    just a single loop through the entire directory, listing files as we go.

    So to start off, print the heading line and then begin main loop through
    the central directory.  The results will look vaguely like the following:

 Length   Method    Size  Ratio   Date   Time   CRC-32    Name ("^" ==> case
--------  ------  ------- -----   ----   ----   ------    ----   conversion)
   44004  Implode   13041  71%  11-02-89 19:34  8b4207f7  Makefile.UNIX
    3438  Shrunk     2209  36%  09-15-90 14:07  a2394fd8 ^dos-file.ext
   16717  Defl:X     5252  69%  11-03-97 06:40  1ce0f189  WHERE
--------          -------  ---                            -------
   64159            20502  68%                            3 files
  ---------------------------------------------------------------------------*/

    G.pInfo = &info;
    date_format = DATE_FORMAT;
    dt_sepchar = DATE_SEPCHAR;

#ifndef WINDLL
    if (uO.qflag < 2) {
        if (uO.L_flag)
            Info(slide, 0, ((char *)slide, LoadFarString(CaseConversion),
              LoadFarStringSmall(Headers[longhdr][0]),
              LoadFarStringSmall2(Headers[longhdr][1])));
        else
            Info(slide, 0, ((char *)slide, "%s\n%s\n",
               LoadFarString(Headers[longhdr][0]),
               LoadFarStringSmall(Headers[longhdr][1])));
    }
#endif /* !WINDLL */

    for (j = 1L;;j++) {

        if (readbuf(__G__ G.sig, 4) == 0)
            return PK_EOF;
        if (memcmp(G.sig, central_hdr_sig, 4)) {  /* is it a CentDir entry? */
            /* no new central directory entry
             * -> is the number of processed entries compatible with the
             *    number of entries as stored in the end_central record?
             */
            if (((j - 1) &
                 (ulg)(G.ecrec.have_ecr64 ? MASK_ZUCN64 : MASK_ZUCN16))
                == (ulg)G.ecrec.total_entries_central_dir)
            {
                /* "j modulus 4T/64k" matches the reported 64/16-bit-unsigned
                 * number of directory entries -> probably, the regular
                 * end of the central directory has been reached
                 */
                break;
            } else {
                Info(slide, 0x401,
                     ((char *)slide, LoadFarString(CentSigMsg), j));
                Info(slide, 0x401,
                     ((char *)slide, LoadFarString(ReportMsg)));
                return PK_BADERR;   /* sig not found */
            }
        }
        /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag, ...: */
        if ((error = process_cdir_file_hdr(__G)) != PK_COOL)
            return error;       /* only PK_EOF defined */

        /*
         * We could DISPLAY the filename instead of storing (and possibly trun-
         * cating, in the case of a very long name) and printing it, but that
         * has the disadvantage of not allowing case conversion--and it's nice
         * to be able to see in the listing precisely how you have to type each
         * filename in order for unzip to consider it a match.  Speaking of
         * which, if member names were specified on the command line, check in
         * with match() to see if the current file is one of them, and make a
         * note of it if it is.
         */

        if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=
             PK_COOL)   /*  ^--(uses pInfo->lcflag) */
        {
            error_in_archive = error;
            if (error > PK_WARN)   /* fatal:  can't continue */
                return error;
        }
        if (G.extra_field != (uch *)NULL) {
            free(G.extra_field);
            G.extra_field = (uch *)NULL;
        }
        if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD))
            != 0)
        {
            error_in_archive = error;
            if (error > PK_WARN)      /* fatal */
                return error;
        }
        if (!G.process_all_files) {   /* check if specified on command line */
            unsigned i;

            if (G.filespecs == 0)
                do_this_file = TRUE;
            else {  /* check if this entry matches an `include' argument */
                do_this_file = FALSE;
                for (i = 0; i < G.filespecs; i++)
                    if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) {
                        do_this_file = TRUE;
                        break;       /* found match, so stop looping */
                    }
            }
            if (do_this_file) {  /* check if this is an excluded file */
                for (i = 0; i < G.xfilespecs; i++)
                    if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) {
                        do_this_file = FALSE;  /* ^-- ignore case in match */
                        break;
                    }
            }
        }
        /*
         * If current file was specified on command line, or if no names were
         * specified, do the listing for this file.  Otherwise, get rid of the
         * file comment and go back for the next file.
         */

        if (G.process_all_files || do_this_file) {

#ifdef OS2DLL
            /* this is used by UzpFileTree() to allow easy processing of lists
             * of zip directory contents */
            if (G.processExternally) {
                if ((G.processExternally)(G.filename, &G.crec))
                    break;
                ++members;
            } else {
#endif
#ifdef OS2_EAS
            {
                uch *ef_ptr = G.extra_field;
                int ef_size, ef_len = G.crec.extra_field_length;
                ea_size = acl_size = 0;

                while (ef_len >= EB_HEADSIZE) {
                    ef_size = makeword(&ef_ptr[EB_LEN]);
                    switch (makeword(&ef_ptr[EB_ID])) {
                        case EF_OS2:
                            ea_size = makelong(&ef_ptr[EB_HEADSIZE]);
                            break;
                        case EF_ACL:
                            acl_size = makelong(&ef_ptr[EB_HEADSIZE]);
                            break;
                    }
                    ef_ptr += (ef_size + EB_HEADSIZE);
                    ef_len -= (ef_size + EB_HEADSIZE);
                }
            }
#endif
#ifdef USE_EF_UT_TIME
            if (G.extra_field &&
#ifdef IZ_CHECK_TZ
                G.tz_is_valid &&
#endif
                (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
                                  G.crec.last_mod_dos_datetime, &z_utime, NULL)
                 & EB_UT_FL_MTIME))
            {
                TIMET_TO_NATIVE(z_utime.mtime)   /* NOP unless MSC 7.0, Mac */
                t = localtime(&(z_utime.mtime));
            } else
                t = (struct tm *)NULL;
            if (t != (struct tm *)NULL) {
                mo = (unsigned)(t->tm_mon + 1);
                dy = (unsigned)(t->tm_mday);
                yr = (unsigned)(t->tm_year + 1900);
                hh = (unsigned)(t->tm_hour);
                mm = (unsigned)(t->tm_min);
            } else
#endif /* USE_EF_UT_TIME */
            {
                yr = ((((unsigned)(G.crec.last_mod_dos_datetime >> 25) & 0x7f)
                       + 1980));
                mo = ((unsigned)(G.crec.last_mod_dos_datetime >> 21) & 0x0f);
                dy = ((unsigned)(G.crec.last_mod_dos_datetime >> 16) & 0x1f);
                hh = (((unsigned)G.crec.last_mod_dos_datetime >> 11) & 0x1f);
                mm = (((unsigned)G.crec.last_mod_dos_datetime >> 5) & 0x3f);
            }
            /* permute date so it displays according to nat'l convention
             * ('methnum' is not yet set, it is used as temporary buffer) */
            switch (date_format) {
                case DF_YMD:
                    methnum = mo;
                    mo = yr; yr = dy; dy = methnum;
                    break;
                case DF_DMY:
                    methnum = mo;
                    mo = dy; dy = methnum;
            }

            csiz = G.crec.csize;
            if (G.crec.general_purpose_bit_flag & 1)
                csiz -= 12;   /* if encrypted, don't count encryption header */
            if ((cfactor = ratio(G.crec.ucsize, csiz)) < 0) {
#ifndef WINDLL
                sgn = '-';
#endif
                cfactor = (-cfactor + 5) / 10;
            } else {
#ifndef WINDLL
                sgn = ' ';
#endif
                cfactor = (cfactor + 5) / 10;
            }

            methnum = find_compr_idx(G.crec.compression_method);
            zfstrcpy(methbuf, method[methnum]);
            if (G.crec.compression_method == DEFLATED ||
                G.crec.compression_method == ENHDEFLATED) {
                methbuf[5] = dtype[(G.crec.general_purpose_bit_flag>>1) & 3];
            } else if (methnum >= NUM_METHODS) {
                sprintf(&methbuf[4], "%03u", G.crec.compression_method);
            }

#if 0       /* GRR/Euro:  add this? */
#if defined(DOS_FLX_NLM_OS2_W32) || defined(THEOS) || defined(UNIX)
            for (p = G.filename;  *p;  ++p)
                if (!isprint(*p))
                    *p = '?';  /* change non-printable chars to '?' */
#endif /* DOS_FLX_NLM_OS2_W32 || THEOS || UNIX */
#endif /* 0 */

#ifdef WINDLL
            /* send data to application for formatting and printing */
            if (G.lpUserFunctions->SendApplicationMessage != NULL)
                (*G.lpUserFunctions->SendApplicationMessage)(G.crec.ucsize,
                  csiz, (unsigned)cfactor, mo, dy, yr, hh, mm,
                  (char)(G.pInfo->lcflag ? '^' : ' '),
                  (LPCSTR)fnfilter(G.filename, slide, (WSIZE>>1)),
                  (LPCSTR)methbuf, G.crec.crc32,
                  (char)((G.crec.general_purpose_bit_flag & 1) ? 'E' : ' '));
            else if (G.lpUserFunctions->SendApplicationMessage_i32 != NULL) {
                unsigned long ucsize_lo, csiz_lo;
                unsigned long ucsize_hi=0L, csiz_hi=0L;
                ucsize_lo = (unsigned long)(G.crec.ucsize);
                csiz_lo = (unsigned long)(csiz);
#ifdef ZIP64_SUPPORT
                ucsize_hi = (unsigned long)(G.crec.ucsize >> 32);
                csiz_hi = (unsigned long)(csiz >> 32);
#endif /* ZIP64_SUPPORT */
                (*G.lpUserFunctions->SendApplicationMessage_i32)(ucsize_lo,
                    ucsize_hi, csiz_lo, csiz_hi, (unsigned)cfactor,
                    mo, dy, yr, hh, mm,
                    (char)(G.pInfo->lcflag ? '^' : ' '),
                    (LPCSTR)fnfilter(G.filename, slide, (WSIZE>>1)),
                    (LPCSTR)methbuf, G.crec.crc32,
                    (char)((G.crec.general_purpose_bit_flag & 1) ? 'E' : ' '));
            }
#else /* !WINDLL */
            if (cfactor == 100)
                sprintf(cfactorstr, LoadFarString(CompFactor100));
            else
                sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
            if (longhdr)
                Info(slide, 0, ((char *)slide, LoadFarString(LongHdrStats),
                  FmZofft(G.crec.ucsize, "8", "u"), methbuf,
                  FmZofft(csiz, "8", "u"), cfactorstr,
                  mo, dt_sepchar, dy, dt_sepchar, yr, hh, mm,
                  G.crec.crc32, (G.pInfo->lcflag? '^':' ')));
            else
#ifdef OS2_EAS
                Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats),
                  FmZofft(G.crec.ucsize, "9", "u"), ea_size, acl_size,
                  mo, dt_sepchar, dy, dt_sepchar, yr, hh, mm,
                  (G.pInfo->lcflag? '^':' ')));
#else
                Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats),
                  FmZofft(G.crec.ucsize, "9", "u"),
                  mo, dt_sepchar, dy, dt_sepchar, yr, hh, mm,
                  (G.pInfo->lcflag? '^':' ')));
#endif
            fnprint(__G);
#endif /* ?WINDLL */

            if ((error = do_string(__G__ G.crec.file_comment_length,
                                   QCOND? DISPL_8 : SKIP)) != 0)
            {
                error_in_archive = error;  /* might be just warning */
                if (error > PK_WARN)       /* fatal */
                    return error;
            }
            tot_ucsize += G.crec.ucsize;
            tot_csize += csiz;
            ++members;
#ifdef OS2_EAS
            if (ea_size) {
                tot_easize += ea_size;
                ++tot_eafiles;
            }
            if (acl_size) {
                tot_aclsize += acl_size;
                ++tot_aclfiles;
            }
#endif
#ifdef OS2DLL
            } /* end of "if (G.processExternally) {...} else {..." */
#endif
        } else {        /* not listing this file */
            SKIP_(G.crec.file_comment_length)
        }
    } /* end for-loop (j: files in central directory) */

/*---------------------------------------------------------------------------
    Print footer line and totals (compressed size, uncompressed size, number
    of members in zipfile).
  ---------------------------------------------------------------------------*/

    if (uO.qflag < 2
#ifdef OS2DLL
                     && !G.processExternally
#endif
                                            ) {
        if ((cfactor = ratio(tot_ucsize, tot_csize)) < 0) {
#ifndef WINDLL
            sgn = '-';
#endif
            cfactor = (-cfactor + 5) / 10;
        } else {
#ifndef WINDLL
            sgn = ' ';
#endif
            cfactor = (cfactor + 5) / 10;
        }
#ifdef WINDLL
        /* pass the totals back to the calling application */
        G.lpUserFunctions->TotalSizeComp = tot_csize;
        G.lpUserFunctions->TotalSize = tot_ucsize;
        G.lpUserFunctions->CompFactor = (ulg)cfactor;
        G.lpUserFunctions->NumMembers = members;

#else /* !WINDLL */
        if (cfactor == 100)
            sprintf(cfactorstr, LoadFarString(CompFactor100));
        else
            sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
        if (longhdr) {
            Info(slide, 0, ((char *)slide, LoadFarString(LongFileTrailer),
              FmZofft(tot_ucsize, "8", "u"), FmZofft(tot_csize, "8", "u"),
              cfactorstr, members, members==1? "":"s"));
#ifdef OS2_EAS
            if (tot_easize || tot_aclsize)
                Info(slide, 0, ((char *)slide, "\n"));
            if (tot_eafiles && tot_easize)
                Info(slide, 0, ((char *)slide, LoadFarString(OS2ExtAttrTrailer),
                  tot_eafiles, tot_eafiles == 1? " has" : "s have a total of",
                  tot_easize));
            if (tot_aclfiles && tot_aclsize)
                Info(slide, 0, ((char *)slide, LoadFarString(OS2ACLTrailer),
                  tot_aclfiles,
                  tot_aclfiles == 1 ? " has" : "s have a total of",
                  tot_aclsize));
#endif /* OS2_EAS */
        } else
#ifdef OS2_EAS
            Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer),
              FmZofft(tot_ucsize, "9", "u"), tot_easize, tot_aclsize,
              members, members == 1 ? "" : "s"));
#else
            Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer),
              FmZofft(tot_ucsize, "9", "u"),
              members, members == 1 ? "" : "s"));
#endif /* OS2_EAS */
#endif /* ?WINDLL */
    }

    /* Skip the following checks in case of a premature listing break. */
    if (error_in_archive <= PK_WARN) {

/*---------------------------------------------------------------------------
    Double check that we're back at the end-of-central-directory record.
  ---------------------------------------------------------------------------*/

        if ( (memcmp(G.sig,
                     (G.ecrec.have_ecr64 ?
                      end_central64_sig : end_central_sig),
                     4) != 0)
            && (!G.ecrec.is_zip64_archive)
            && (memcmp(G.sig, end_central_sig, 4) != 0)
           ) {          /* just to make sure again */
            Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
            error_in_archive = PK_WARN;   /* didn't find sig */
        }

        /* Set specific return code when no files have been found. */
        if (members == 0L && error_in_archive <= PK_WARN)
            error_in_archive = PK_FIND;

    }

```

[Assistant]
diff --git a/list.c b/list.c
--- a/list.c
+++ b/list.c
@@ -97,7 +97,7 @@ int list_files(__G)    /* return PK-type
 {
     int do_this_file=FALSE, cfactor, error, error_in_archive=PK_COOL;
 #ifndef WINDLL
-    char sgn, cfactorstr[10];
+    char sgn, cfactorstr[1+10+1+1];	/* <sgn><int>%NUL */
     int longhdr=(uO.vflag>1);
 #endif
     int date_format;
@@ -389,9 +389,9 @@ int list_files(__G)    /* return PK-type
             }
 #else /* !WINDLL */
             if (cfactor == 100)
-                sprintf(cfactorstr, LoadFarString(CompFactor100));
+                snprintf(cfactorstr, sizeof(cfactorstr), LoadFarString(CompFactor100));
             else
-                sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
+                snprintf(cfactorstr, sizeof(cfactorstr), LoadFarString(CompFactorStr), sgn, cfactor);
             if (longhdr)
                 Info(slide, 0, ((char *)slide, LoadFarString(LongHdrStats),
                   FmZofft(G.crec.ucsize, "8", "u"), methbuf,
@@ -471,9 +471,9 @@ int list_files(__G)    /* return PK-type

 #else /* !WINDLL */
         if (cfactor == 100)
-            sprintf(cfactorstr, LoadFarString(CompFactor100));
+            snprintf(cfactorstr, sizeof(cfactorstr), LoadFarString(CompFactor100));
         else
-            sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
+            snprintf(cfactorstr, sizeof(cfactorstr), LoadFarString(CompFactorStr), sgn, cfactor);
         if (longhdr) {
             Info(slide, 0, ((char *)slide, LoadFarString(LongFileTrailer),
               FmZofft(tot_ucsize, "8", "u"), FmZofft(tot_csize, "8", "u"),


[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-2021-28918: Improper input validation (CWE-20) in the Perl module Net::CIDR::Lite before 0.22. When parsing a dotted-quad IPv4 address, each octet was accepted as long as it was one to three digits and numerically at most 255, with no check on a leading zero. An octet written with a leading zero, such as the first octet of 010.0.0.0/8, therefore passed and was interpreted as the decimal value 10, whereas many other network stacks read a zero-padded octet as octal. A CIDR allow-list or deny-list built from attacker-influenced input consequently covers a different address range than the author intended, enabling an access-control or SSRF-filter bypass. Affects perlPackages.NetCIDRLite.

# Vulnerable source (Lite.pm)
```perl
    } elsif (_pack_ipv6($ip)) {
        $nbits = 136;
        $pack = \&_pack_ipv6;
        $unpack = \&_unpack_ipv6;
    } else {
        return;
    }
    $$self{PACK}  = $pack;
    $$self{UNPACK}  = $unpack;
    $$self{NBITS} = $nbits;
    $$self{MASKS} = $masks{$nbits} ||= [
      map { pack("B*", substr("1" x $_ . "0" x $nbits, 0, $nbits))
          } 0..$nbits
    ];
    $$self{RANGES} = {};
    $self;
}

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

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

sub _pack_ipv6 {
    my $ip = shift;
    $ip =~ s/^::$/::0/;
    return if $ip =~ /^:/ and $ip !~ s/^::/:/;
    return if $ip =~ /:$/ and $ip !~ s/::$/:/;
    my @nums = split /:/, $ip, -1;
    return unless @nums <= 8;
    my ($empty, $ipv4, $str) = (0,'','');
    for (@nums) {
```

[Assistant]
diff --git a/Lite.pm b/Lite.pm
--- a/Lite.pm
+++ b/Lite.pm
@@ -181,7 +181,7 @@ sub _pack_ipv4 {
     my @nums = split /\./, shift(), -1;
     return unless @nums == 4;
     for (@nums) {
-        return unless /^\d{1,3}$/ and $_ <= 255;
+        return unless /^\d{1,3}$/ and !/^0\d{1,2}$/ and $_ <= 255;
     }
     pack("CC*", 0, @nums);
 }


[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-2021-40633: giflib 5.2.2 gif2rgb tool leaked heap memory when processing GIF images: after rendering a GIF to RGB bitmap data, the row-level allocations for the image height were released only at the outer container level but not individually, causing an unbounded memory accumulation in long-running processes that handle attacker-supplied GIF files.

# Vulnerable source (gif2rgb.c)
```c
				}
			}
			break;
		case EXTENSION_RECORD_TYPE:
			/* Skip any extension blocks in file: */
			if (DGifGetExtension(GifFile, &ExtCode, &Extension) ==
			    GIF_ERROR) {
				PrintGifError(GifFile->Error);
				exit(EXIT_FAILURE);
			}
			while (Extension != NULL) {
				if (DGifGetExtensionNext(GifFile, &Extension) ==
				    GIF_ERROR) {
					PrintGifError(GifFile->Error);
					exit(EXIT_FAILURE);
				}
			}
			break;
		case TERMINATE_RECORD_TYPE:
			break;
		default: /* Should be trapped by DGifGetRecordType. */
			break;
		}
	} while (RecordType != TERMINATE_RECORD_TYPE);

	/* Lets dump it - set the global variables required and do it: */
	ColorMap = (GifFile->Image.ColorMap ? GifFile->Image.ColorMap
	                                    : GifFile->SColorMap);
	if (ColorMap == NULL) {
		fprintf(stderr, "Gif Image does not have a colormap\n");
		exit(EXIT_FAILURE);
	}

	/* check that the background color isn't garbage (SF bug #87) */
	if (GifFile->SBackGroundColor < 0 ||
	    GifFile->SBackGroundColor >= ColorMap->ColorCount) {
		fprintf(stderr, "Background color out of range for colormap\n");
		exit(EXIT_FAILURE);
	}

	DumpScreen2RGB(OutFileName, OneFileFlag, ColorMap, ScreenBuffer,
	               GifFile->SWidth, GifFile->SHeight);

	(void)free(ScreenBuffer);

	{
		int Error;
		if (DGifCloseFile(GifFile, &Error) == GIF_ERROR) {
			PrintGifError(Error);
			exit(EXIT_FAILURE);
		}
	}
}

/******************************************************************************
 * Interpret the command line and scan the given GIF file.
 ******************************************************************************/
int main(int argc, char **argv) {
	bool Error, OutFileFlag = false, ColorFlag = false, SizeFlag = false,
	            GifNoisyPrint = false;
	int NumFiles, Width = 0, Height = 0, ExpNumOfColors = 8;
	char *OutFileName, **FileName = NULL;
	static bool OneFileFlag = false, HelpFlag = false;

	if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifNoisyPrint, &ColorFlag,
	                       &ExpNumOfColors, &SizeFlag, &Width, &Height,
	                       &OneFileFlag, &OutFileFlag, &OutFileName,
	                       &HelpFlag, &NumFiles, &FileName)) != false ||
	    (NumFiles > 1 && !HelpFlag)) {
		if (Error) {
			GAPrintErrMsg(Error);
		} else if (NumFiles > 1) {
			GIF_MESSAGE("Error in command line parsing - one input "
			            "file please.");
		}
		GAPrintHowTo(CtrlStr);
		exit(EXIT_FAILURE);
	}

	if (HelpFlag) {
		(void)fprintf(stderr, VersionStr, GIFLIB_MAJOR, GIFLIB_MINOR);
		GAPrintHowTo(CtrlStr);
		exit(EXIT_SUCCESS);
	}
	if (!OutFileFlag) {
		OutFileName = NULL;
```

[Assistant]
diff --git a/gif2rgb.c b/gif2rgb.c
index d51226d..fc2e683 100644
--- a/gif2rgb.c
+++ b/gif2rgb.c
@@ -517,6 +517,9 @@ static void GIF2RGB(int NumFiles, char *FileName, bool OneFileFlag,
 	DumpScreen2RGB(OutFileName, OneFileFlag, ColorMap, ScreenBuffer,
 	               GifFile->SWidth, GifFile->SHeight);

+	for (i = 0; i < GifFile->SHeight; i++) {
+        	(void)free(ScreenBuffer[i]);
+	}
 	(void)free(ScreenBuffer);

 	{
--
2.44.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-2021-41581: Stack buffer over-read (CWE-125) in LibreSSL 3.4.0 reachable through X.509 name-constraint email handling. x509_constraints_parse_mailbox() copies the mailbox address into a fixed 256-byte stack buffer one character at a time, but the per-character index guard is off by one, so a mailbox whose domain part is exactly 256 characters long fills the entire buffer with no room left for a terminating NUL byte. When the parser then calls strdup() on that buffer it scans past the end of the stack array looking for a NUL, reading adjacent stack memory beyond the object. This is triggered while validating a certificate or mailbox against email name constraints. Affects the libressl 3.4.0 package.

# Vulnerable source (lib/libcrypto/x509/x509_constraints.c)
```c
	int quoted = 0;

	if (candidate == NULL)
		return 0;

	/* It can't be bigger than the local part, domain part and the '@' */
	if (len > LOCAL_PART_MAX_LEN + DOMAIN_PART_MAX_LEN + 1)
		return 0;

	for (i = 0; i < len; i++) {
		char c = candidate[i];
		/* non ascii, cr, lf, or nul is never allowed */
		if (!isascii(c) || c == '\r' || c == '\n' || c == '\0')
			goto bad;
		if (i == 0) {
			/* local part is quoted part */
			if (c == '"')
				quoted = 1;
			/* can not start with a . */
			if (c == '.')
				goto bad;
		}
		if (wi > DOMAIN_PART_MAX_LEN)
			goto bad;
		if (accept) {
			working[wi++] = c;
			accept = 0;
			continue;
		}
		if (candidate_local != NULL) {
			/* We are looking for the domain part */
			if (wi > DOMAIN_PART_MAX_LEN)
				goto bad;
			working[wi++] = c;
			if (i == len - 1) {
				if (wi == 0)
					goto bad;
				if (candidate_domain != NULL)
					goto bad;
				candidate_domain = strdup(working);
				if (candidate_domain == NULL)
					goto bad;
			}
			continue;
		}
		/* We are looking for the local part */
		if (wi > LOCAL_PART_MAX_LEN)
			break;

		if (quoted) {
			if (c == '\\') {
				accept = 1;
				continue;
			}
			if (c == '"' && i != 0) {
				/* end the quoted part. @ must be next */
				if (i + 1 == len || candidate[i + 1] != '@')
					goto bad;
				quoted = 0;
			}
			/*
			 * XXX Go strangely permits sp but forbids ht
			 * mimic that for now
			 */
			if (c == 9)
				goto bad;
			working[wi++] = c;
			continue; /* all's good inside our quoted string */
		}
		if (c == '@') {
			if (wi == 0)
				goto bad;;
			if (candidate_local != NULL)
				goto bad;
			candidate_local = strdup(working);
			if (candidate_local == NULL)
				goto bad;
			memset(working, 0, sizeof(working));
			wi = 0;
			continue;
		}
		if (c == '\\') {
			/*
			 * RFC 3936 hints these can happen outside of
			 * quotend string. don't include the \ but
			 * next character must be ok.
			 */
			if (i + 1 == len)
				goto bad;
			if (!local_part_ok(candidate[i + 1]))
				goto bad;
			accept = 1;
		}
		if (!local_part_ok(c))
			goto bad;
		working[wi++] = c;
	}
	if (candidate_local == NULL || candidate_domain == NULL)
		goto bad;
	if (!x509_constraints_valid_host(candidate_domain,
	    strlen(candidate_domain)))
		goto bad;

	name->local = candidate_local;
	name->name = candidate_domain;
	name->type = GEN_EMAIL;
	return 1;
 bad:
	free(candidate_local);
	free(candidate_domain);
	return 0;
}

```

[Assistant]
diff --git a/lib/libcrypto/x509/x509_constraints.c b/lib/libcrypto/x509/x509_constraints.c
--- a/lib/libcrypto/x509/x509_constraints.c
+++ b/lib/libcrypto/x509/x509_constraints.c
@@ -339,16 +339,16 @@
 			if (c == '.')
 				goto bad;
 		}
-		if (wi > DOMAIN_PART_MAX_LEN)
-			goto bad;
 		if (accept) {
+			if (wi >= DOMAIN_PART_MAX_LEN)
+				goto bad;
 			working[wi++] = c;
 			accept = 0;
 			continue;
 		}
 		if (candidate_local != NULL) {
 			/* We are looking for the domain part */
-			if (wi > DOMAIN_PART_MAX_LEN)
+			if (wi >= DOMAIN_PART_MAX_LEN)
 				goto bad;
 			working[wi++] = c;
 			if (i == len - 1) {
@@ -363,7 +363,7 @@
 			continue;
 		}
 		/* We are looking for the local part */
-		if (wi > LOCAL_PART_MAX_LEN)
+		if (wi >= LOCAL_PART_MAX_LEN)
 			break;

 		if (quoted) {
@@ -383,6 +383,8 @@
 			 */
 			if (c == 9)
 				goto bad;
+			if (wi >= LOCAL_PART_MAX_LEN)
+				goto bad;
 			working[wi++] = c;
 			continue; /* all's good inside our quoted string */
 		}
@@ -412,6 +414,8 @@
 		}
 		if (!local_part_ok(c))
 			goto bad;
+		if (wi >= LOCAL_PART_MAX_LEN)
+			goto bad;
 		working[wi++] = c;
 	}
 	if (candidate_local == NULL || candidate_domain == 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-2021-4217: unzip do_string() reads extra data from a ZIP archive entry into an internal storage area; the code accepts any non-zero result from the read call as success even if fewer octets than requested were obtained, causing the parser to interpret stale heap content beyond the actually-read data as part of the ZIP metadata.

# Vulnerable source (fileio.c)
```c
     */

    case SKIP:
        /* cur_zipfile_bufstart already takes account of extra_bytes, so don't
         * correct for it twice: */
        seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes +
                  (G.inptr-G.inbuf) + length);
        break;

    /*
     * Fourth case:  assume we're at the start of an "extra field"; malloc
     * storage for it and read data into the allocated space.
     */

    case EXTRA_FIELD:
        if (G.extra_field != (uch *)NULL)
            free(G.extra_field);
        if ((G.extra_field = (uch *)malloc(length)) == (uch *)NULL) {
            Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong),
              length));
            /* cur_zipfile_bufstart already takes account of extra_bytes,
             * so don't correct for it twice: */
            seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes +
                      (G.inptr-G.inbuf) + length);
        } else {
            if (readbuf(__G__ (char *)G.extra_field, length) == 0)
                return PK_EOF;
            /* Looks like here is where extra fields are read */
            getZip64Data(__G__ G.extra_field, length);
#ifdef UNICODE_SUPPORT
            G.unipath_filename = NULL;
            if (G.UzO.U_flag < 2) {
              /* check if GPB11 (General Purpuse Bit 11) is set indicating
                 the standard path and comment are UTF-8 */
              if (G.pInfo->GPFIsUTF8) {
                /* if GPB11 set then filename_full is untruncated UTF-8 */
                G.unipath_filename = G.filename_full;
              } else {
                /* Get the Unicode fields if exist */
                getUnicodeData(__G__ G.extra_field, length);
                if (G.unipath_filename && strlen(G.unipath_filename) == 0) {
                  /* the standard filename field is UTF-8 */
                  free(G.unipath_filename);
                  G.unipath_filename = G.filename_full;
                }
              }
              if (G.unipath_filename) {
# ifdef UTF8_MAYBE_NATIVE
                if (G.native_is_utf8
#  ifdef UNICODE_WCHAR
                    && (!G.unicode_escape_all)
#  endif
                   ) {
                  strncpy(G.filename, G.unipath_filename, FILNAMSIZ - 1);
                  /* make sure filename is short enough */
                  if (strlen(G.unipath_filename) >= FILNAMSIZ) {
                    G.filename[FILNAMSIZ - 1] = '\0';
                    Info(slide, 0x401, ((char *)slide,
                      LoadFarString(UFilenameTooLongTrunc)));
                    error = PK_WARN;
                  }
                }
#  ifdef UNICODE_WCHAR
                else
#  endif
# endif /* UTF8_MAYBE_NATIVE */
# ifdef UNICODE_WCHAR
                {
                  char *fn;

                  /* convert UTF-8 to local character set */
                  fn = utf8_to_local_string(G.unipath_filename,
                                            G.unicode_escape_all);
                  /* make sure filename is short enough */
                  if (strlen(fn) >= FILNAMSIZ) {
                    fn[FILNAMSIZ - 1] = '\0';
                    Info(slide, 0x401, ((char *)slide,
                      LoadFarString(UFilenameTooLongTrunc)));
                    error = PK_WARN;
                  }
                  /* replace filename with converted UTF-8 */
                  strcpy(G.filename, fn);
                  free(fn);
                }
# endif /* UNICODE_WCHAR */
                if (G.unipath_filename != G.filename_full)
                  free(G.unipath_filename);
                G.unipath_filename = NULL;
```

[Assistant]
diff --git a/fileio.c b/fileio.c
--- a/fileio.c
+++ b/fileio.c
@@ -2310,8 +2310,11 @@ int do_string(__G__ length, option)   /*
             seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes +
                       (G.inptr-G.inbuf) + length);
         } else {
-            if (readbuf(__G__ (char *)G.extra_field, length) == 0)
+            unsigned bytes_read = readbuf(__G__ (char *)G.extra_field, length);
+            if (bytes_read == 0)
                 return PK_EOF;
+            if (bytes_read != length)
+                return PK_ERR;
             /* Looks like here is where extra fields are read */
             if (getZip64Data(__G__ G.extra_field, length) != PK_COOL)
             {


[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-2021-45340: When libsixel falls back to its built-in loader (load_with_builtin -> stbi__load_and_postprocess_8bit), a crafted Softimage PICT image is parsed by stbi__pic_load, which reads the image dimensions (e.g. 39168 x 5888) directly from the file. A remote attacker can therefore cause a denial of service by feeding img2sixel a malformed PICT file.

# Vulnerable source (src/stb_image.h)
```c
//    individual types do this automatically as much as possible (e.g. jpeg
//    does all cases internally since it needs to colorspace convert anyway,
//    and it never has alpha, so very few cases ). png can automatically
//    interleave an alpha=255 channel, but falls back to this for other cases
//
//  assume data buffer is malloced, so malloc a new one and free that one
//  only failure mode is malloc failing

static stbi_uc stbi__compute_y(int r, int g, int b)
{
   return (stbi_uc) (((r*77) + (g*150) +  (29*b)) >> 8);
}
#endif

#if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
// nothing
#else
static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y)
{
   int i,j;
   unsigned char *good;

   if (req_comp == img_n) return data;
   STBI_ASSERT(req_comp >= 1 && req_comp <= 4);

   good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0);
   if (good == NULL) {
      STBI_FREE(data);
      return stbi__errpuc("outofmem", "Out of memory");
   }

   for (j=0; j < (int) y; ++j) {
      unsigned char *src  = data + j * x * img_n   ;
      unsigned char *dest = good + j * x * req_comp;

      #define STBI__COMBO(a,b)  ((a)*8+(b))
      #define STBI__CASE(a,b)   case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)
      // convert source image with img_n components to one with req_comp components;
      // avoid switch per pixel, so use switch per scanline and massive macros
      switch (STBI__COMBO(img_n, req_comp)) {
```

[Assistant]
diff --git a/src/stb_image.h b/src/stb_image.h
index 9eedabe..e62bf73 100644
--- a/src/stb_image.h
+++ b/src/stb_image.h
@@ -1757,6 +1757,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
    int i,j;
    unsigned char *good;

+   if (data == NULL) return data;
    if (req_comp == img_n) return data;
    STBI_ASSERT(req_comp >= 1 && req_comp <= 4);


[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-2022-28805: lua 5.2.4 parser has an out-of-bounds memory access in the variable lookup path: when resolving a global identifier inside a function block, the environment table reference was not promoted to a register or upvalue before being indexed, leaving the VM in an invalid state if the environment was stored as a literal, which a crafted Lua script can exploit to trigger a parser assertion failure or memory corruption.

# Vulnerable source (src/lparser.c)
```c
  BlockCnt *bl = fs->bl;
  while (bl->nactvar > level) bl = bl->previous;
  bl->upval = 1;
}

/*
  Find variable with given name 'n'. If it is an upvalue, add this
  upvalue into all intermediate functions.
*/
static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
  if (fs == NULL)  /* no more levels? */
    return VVOID;  /* default is global */
  else {
    int v = searchvar(fs, n);  /* look up locals at current level */
    if (v >= 0) {  /* found? */
      init_exp(var, VLOCAL, v);  /* variable is local */
      if (!base)
        markupval(fs, v);  /* local will be used as an upval */
      return VLOCAL;
    }
    else {  /* not found as local at current level; try upvalues */
      int idx = searchupvalue(fs, n);  /* try existing upvalues */
      if (idx < 0) {  /* not found? */
        if (singlevaraux(fs->prev, n, var, 0) == VVOID) /* try upper levels */
          return VVOID;  /* not found; is a global */
        /* else was LOCAL or UPVAL */
        idx  = newupvalue(fs, n, var);  /* will be a new upvalue */
      }
      init_exp(var, VUPVAL, idx);
      return VUPVAL;
    }
  }
}

static void singlevar (LexState *ls, expdesc *var) {
  TString *varname = str_checkname(ls);
  FuncState *fs = ls->fs;
  if (singlevaraux(fs, varname, var, 1) == VVOID) {  /* global name? */
    expdesc key;
    singlevaraux(fs, ls->envn, var, 1);  /* get environment variable */
    lua_assert(var->k == VLOCAL || var->k == VUPVAL);
    codestring(ls, &key, varname);  /* key is variable name */
    luaK_indexed(fs, var, &key);  /* env[varname] */
  }
}

static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
  FuncState *fs = ls->fs;
  int extra = nvars - nexps;
  if (hasmultret(e->k)) {
    extra++;  /* includes call itself */
    if (extra < 0) extra = 0;
    luaK_setreturns(fs, e, extra);  /* last exp. provides the difference */
    if (extra > 1) luaK_reserveregs(fs, extra-1);
  }
  else {
    if (e->k != VVOID) luaK_exp2nextreg(fs, e);  /* close last expression */
    if (extra > 0) {
      int reg = fs->freereg;
      luaK_reserveregs(fs, extra);
      luaK_nil(fs, reg, extra);
    }
  }
}

static void enterlevel (LexState *ls) {
  lua_State *L = ls->L;
  ++L->nCcalls;
  checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels");
}

#define leavelevel(ls)	((ls)->L->nCcalls--)

static void closegoto (LexState *ls, int g, Labeldesc *label) {
  int i;
  FuncState *fs = ls->fs;
  Labellist *gl = &ls->dyd->gt;
  Labeldesc *gt = &gl->arr[g];
  lua_assert(luaS_eqstr(gt->name, label->name));
  if (gt->nactvar < label->nactvar) {
```

[Assistant]
diff --git a/src/lparser.c b/src/lparser.c
--- a/src/lparser.c
+++ b/src/lparser.c
@@ -301,6 +301,7 @@
     expdesc key;
     singlevaraux(fs, ls->envn, var, 1);  /* get environment variable */
     lua_assert(var->k == VLOCAL || var->k == VUPVAL);
+    luaK_exp2anyregup(fs, var);  /* but could be a constant */
     codestring(ls, &key, varname);  /* key is variable name */
     luaK_indexed(fs, var, &key);  /* env[varname] */
   }


[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-2022-35920: Directory-traversal / arbitrary-file disclosure (CWE-22) in the Sanic web framework's static file route. A request whose path encodes the traversal (e.g. The result is disclosure of files outside the directory the application intended to serve.

# Vulnerable source (sanic/mixins/routes.py)
```python
from ast import NodeVisitor, Return, parse
from contextlib import suppress
from functools import partial, wraps
from inspect import getsource, signature
from mimetypes import guess_type
from os import path
from pathlib import PurePath
from re import sub
from textwrap import dedent
from time import gmtime, strftime
from typing import (
    Any,
    Callable,
    Iterable,
    List,
    Optional,
    Set,
    Tuple,
    Union,
    cast,
)
from urllib.parse import unquote

        /* ... */
                        continue
                else:
                    break

        if not name:  # noqa
            raise ValueError("Could not generate a name for handler")

        if not name.startswith(f"{self.name}."):
            name = f"{self.name}.{name}"

        return name

    async def _static_request_handler(
        self,
        file_or_directory,
        use_modified_since,
        use_content_range,
        stream_large_files,
        request,
        content_type=None,
        __file_uri__=None,
    ):
        # Using this to determine if the URL is trying to break out of the path
        # served.  os.path.realpath seems to be very slow
        if __file_uri__ and "../" in __file_uri__:
            raise BadRequest("Invalid URL")
        # Merge served directory and requested file if provided
        # Strip all / that in the beginning of the URL to help prevent python
        # from herping a derp and treating the uri as an absolute path
        root_path = file_path = file_or_directory
        if __file_uri__:
            file_path = path.join(
                file_or_directory, sub("^[/]*", "", __file_uri__)
            )

        # URL decode the path sent by the browser otherwise we won't be able to
        # match filenames which got encoded (filenames with spaces etc)
        file_path = path.abspath(unquote(file_path))
        if not file_path.startswith(path.abspath(unquote(root_path))):
            error_logger.exception(
```

[Assistant]
diff --git a/sanic/mixins/routes.py b/sanic/mixins/routes.py
index 425b29e..8a5f10c 100644
--- a/sanic/mixins/routes.py
+++ b/sanic/mixins/routes.py
@@ -3,9 +3,8 @@ from contextlib import suppress
 from functools import partial, wraps
 from inspect import getsource, signature
 from mimetypes import guess_type
-from os import path
+from os import path, sep
 from pathlib import PurePath
-from re import sub
 from textwrap import dedent
 from time import gmtime, strftime
 from typing import (
@@ -806,23 +805,23 @@ class RouteMixin(metaclass=SanicMeta):
         content_type=None,
         __file_uri__=None,
     ):
-        # Using this to determine if the URL is trying to break out of the path
-        # served.  os.path.realpath seems to be very slow
-        if __file_uri__ and "../" in __file_uri__:
-            raise BadRequest("Invalid URL")
         # Merge served directory and requested file if provided
-        # Strip all / that in the beginning of the URL to help prevent python
-        # from herping a derp and treating the uri as an absolute path
-        root_path = file_path = file_or_directory
+        root_path = file_path = path.abspath(unquote(file_or_directory))
+
         if __file_uri__:
-            file_path = path.join(
-                file_or_directory, sub("^[/]*", "", __file_uri__)
-            )
+            # Strip all / that in the beginning of the URL to help prevent
+            # python from herping a derp and treating the uri as an
+            # absolute path
+            unquoted_file_uri = unquote(__file_uri__).lstrip("/")
+
+            segments = unquoted_file_uri.split("/")
+            if ".." in segments or any(sep in segment for segment in segments):
+                raise BadRequest("Invalid URL")
+
+            file_path = path.join(file_or_directory, unquoted_file_uri)
+            file_path = path.abspath(file_path)

-        # URL decode the path sent by the browser otherwise we won't be able to
-        # match filenames which got encoded (filenames with spaces etc)
-        file_path = path.abspath(unquote(file_path))
-        if not file_path.startswith(path.abspath(unquote(root_path))):
+        if not file_path.startswith(root_path):
             error_logger.exception(
                 f"File not found: path={file_or_directory}, "
                 f"relative_url={__file_uri__}"


[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-2022-47016: Null pointer dereference (CWE-476) in tmux 3.3a. The upstream patch does not apply cleanly to tmux 3.3a; nixpkgs carries an adapted cherry-pick.

# Vulnerable source (control.c, file.c, window.c)
```c
/* ==== file: control.c ==== */

/* Initialize for control mode. */
void
control_start(struct client *c)
{
	struct control_state	*cs;

	if (c->flags & CLIENT_CONTROLCONTROL) {
		close(c->out_fd);
		c->out_fd = -1;
	} else
		setblocking(c->out_fd, 0);
	setblocking(c->fd, 0);

	cs = c->control_state = xcalloc(1, sizeof *cs);
	RB_INIT(&cs->panes);
	TAILQ_INIT(&cs->pending_list);
	TAILQ_INIT(&cs->all_blocks);
	RB_INIT(&cs->subs);

	cs->read_event = bufferevent_new(c->fd, control_read_callback,
	    control_write_callback, control_error_callback, c);

	if (c->flags & CLIENT_CONTROLCONTROL)
		cs->write_event = cs->read_event;
	else {
		cs->write_event = bufferevent_new(c->out_fd, NULL,
		    control_write_callback, control_error_callback, c);
	}
	bufferevent_setwatermark(cs->write_event, EV_WRITE, CONTROL_BUFFER_LOW,
	    0);

	if (c->flags & CLIENT_CONTROLCONTROL) {
		bufferevent_write(cs->write_event, "\033P1000p", 7);
		bufferevent_enable(cs->write_event, EV_WRITE);
	}
}

/* Control client ready. */
void

/* ==== file: file.c ==== */
	}

	cf->fd = -1;
	if (msg->fd == -1)
		cf->fd = open(path, msg->flags|flags, 0644);
	else if (allow_streams) {
		if (msg->fd != STDOUT_FILENO && msg->fd != STDERR_FILENO)
			errno = EBADF;
		else {
			cf->fd = dup(msg->fd);
			if (close_received)
				close(msg->fd); /* can only be used once */
		}
	} else
	      errno = EBADF;
	if (cf->fd == -1) {
		error = errno;
		goto reply;
	}

	cf->event = bufferevent_new(cf->fd, NULL, file_write_callback,
	    file_write_error_callback, cf);
	bufferevent_enable(cf->event, EV_WRITE);
	goto reply;

reply:
	reply.stream = msg->stream;
	reply.error = error;
	proc_send(peer, MSG_WRITE_READY, -1, &reply, sizeof reply);
}

/* Handle a file write data message (client). */
void
file_write_data(struct client_files *files, struct imsg *imsg)
{
	struct msg_write_data	*msg = imsg->data;
	size_t			 msglen = imsg->hdr.len - IMSG_HEADER_SIZE;
	struct client_file	 find, *cf;
	size_t			 size = msglen - sizeof *msg;

        /* ... */
	}

	cf->fd = -1;
	if (msg->fd == -1)
		cf->fd = open(path, flags);
	else if (allow_streams) {
		if (msg->fd != STDIN_FILENO)
			errno = EBADF;
		else {
			cf->fd = dup(msg->fd);
			if (close_received)
				close(msg->fd); /* can only be used once */
		}
	} else
		errno = EBADF;
	if (cf->fd == -1) {
		error = errno;
		goto reply;
	}

	cf->event = bufferevent_new(cf->fd, file_read_callback, NULL,
	    file_read_error_callback, cf);
	bufferevent_enable(cf->event, EV_READ);
	return;

reply:
	reply.stream = msg->stream;
	reply.error = error;
	proc_send(peer, MSG_READ_DONE, -1, &reply, sizeof reply);
}

/* Handle a write ready message (server). */
void
file_write_ready(struct client_files *files, struct imsg *imsg)
{
	struct msg_write_ready	*msg = imsg->data;
	size_t			 msglen = imsg->hdr.len - IMSG_HEADER_SIZE;
	struct client_file	 find, *cf;

	if (msglen != sizeof *msg)

/* ==== file: window.c ==== */
}

static void
window_pane_error_callback(__unused struct bufferevent *bufev,
    __unused short what, void *data)
{
	struct window_pane *wp = data;

	log_debug("%%%u error", wp->id);
	wp->flags |= PANE_EXITED;

	if (window_pane_destroy_ready(wp))
		server_destroy_pane(wp, 1);
}

void
window_pane_set_event(struct window_pane *wp)
{
	setblocking(wp->fd, 0);

	wp->event = bufferevent_new(wp->fd, window_pane_read_callback,
	    NULL, window_pane_error_callback, wp);
	wp->ictx = input_init(wp, wp->event, &wp->palette);

	bufferevent_enable(wp->event, EV_READ|EV_WRITE);
}

void
window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
{
	struct window_mode_entry	*wme;
	struct window_pane_resize	*r;

	if (sx == wp->sx && sy == wp->sy)
		return;

	r = xmalloc(sizeof *r);
	r->sx = sx;
	r->sy = sy;
	r->osx = wp->sx;
```

[Assistant]
diff --git a/control.c b/control.c
index f75035e..8b44a27 100644
--- a/control.c
+++ b/control.c
@@ -776,12 +776,16 @@ control_start(struct client *c)

 	cs->read_event = bufferevent_new(c->fd, control_read_callback,
 	    control_write_callback, control_error_callback, c);
+	if (cs->read_event == NULL)
+		fatalx("out of memory");

 	if (c->flags & CLIENT_CONTROLCONTROL)
 		cs->write_event = cs->read_event;
 	else {
 		cs->write_event = bufferevent_new(c->out_fd, NULL,
 		    control_write_callback, control_error_callback, c);
+		if (cs->write_event == NULL)
+			fatalx("out of memory");
 	}
 	bufferevent_setwatermark(cs->write_event, EV_WRITE, CONTROL_BUFFER_LOW,
 	    0);
diff --git a/file.c b/file.c
index 7b95612..280f354 100644
--- a/file.c
+++ b/file.c
@@ -588,6 +588,8 @@ file_write_open(struct client_files *files, struct tmuxpeer *peer,

 	cf->event = bufferevent_new(cf->fd, NULL, file_write_callback,
 	    file_write_error_callback, cf);
+	if (cf->event == NULL)
+		fatalx("out of memory");
 	bufferevent_enable(cf->event, EV_WRITE);
 	goto reply;

@@ -747,6 +749,8 @@ file_read_open(struct client_files *files, struct tmuxpeer *peer,

 	cf->event = bufferevent_new(cf->fd, file_read_callback, NULL,
 	    file_read_error_callback, cf);
+	if (cf->event == NULL)
+		fatalx("out of memory");
 	bufferevent_enable(cf->event, EV_READ);
 	return;

diff --git a/window.c b/window.c
index 2be5d5e..1b0066c 100644
--- a/window.c
+++ b/window.c
@@ -1033,6 +1033,8 @@ window_pane_set_event(struct window_pane *wp)

 	wp->event = bufferevent_new(wp->fd, window_pane_read_callback,
 	    NULL, window_pane_error_callback, wp);
+	if (wp->event == NULL)
+		fatalx("out of memory");
 	wp->ictx = input_init(wp, wp->event, &wp->palette);

 	bufferevent_enable(wp->event, EV_READ|EV_WRITE);


[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-2023-28484: When xmlSchemaFixupComplexType() processes a complex type that derives by complexContent extension from a base type whose own content model is absent (a base declared with simpleContent carries no element content model), the fixup code that splices the base type's content model into the derived type reads the base type's content-model pointer without first checking that it is present. Affects the libxml2 2.10.3 package.

# Vulnerable source (xmlschemas.c)
```c
			NULL, NULL);

		} else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
		    (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
		    ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
			XML_SCHEMA_TYPE_ALL))
		{
		    /*
		    * SPEC cos-all-limited (1)
		    */
		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
			/* TODO: error code */
			XML_SCHEMAP_COS_ALL_LIMITED,
			WXS_ITEM_NODE(type), NULL,
			"A type cannot be derived by extension from a type "
			"which has an 'all' model group in its "
			"{content type}, since this would produce a "
			"'sequence' model group containing the 'all' "
			"model group; 'all' model groups are not "
			"allowed to appear inside other model groups",
			NULL, NULL);

		} else if (! dummySequence) {
		    xmlSchemaTreeItemPtr effectiveContent =
			(xmlSchemaTreeItemPtr) type->subtypes;
		    /*
		    * Create the particle.
		    */
		    particle = xmlSchemaAddParticle(pctxt,
			type->node, 1, 1);
		    if (particle == NULL)
			goto exit_failure;
		    /*
		    * Create the "sequence" model group.
		    */
		    particle->children = (xmlSchemaTreeItemPtr)
			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
			XML_SCHEMA_TYPE_SEQUENCE, type->node);
		    if (particle->children == NULL)
			goto exit_failure;
```

[Assistant]
diff --git a/xmlschemas.c b/xmlschemas.c
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -18632,7 +18632,7 @@ xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
 			"allowed to appear inside other model groups",
 			NULL, NULL);

-		} else if (! dummySequence) {
+		} else if ((!dummySequence) && (baseType->subtypes != NULL)) {
 		    xmlSchemaTreeItemPtr effectiveContent =
 			(xmlSchemaTreeItemPtr) type->subtypes;
 		    /*


[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-2023-40890: Stack-based buffer overflow in zbar 0.23.92: the lookup_sequence() function in databar.c uses an unbounded loop counter variable that can exceed the seq[] array capacity when scanning DataBar encoded barcodes, allowing a crafted barcode to trigger out-of-bounds memory access.

# Vulnerable source (zbar/decoder/databar.c)
```c
 *  This file is part of the ZBar Bar Code Reader.
 *
 *  The ZBar Bar Code Reader is free software; you can redistribute it
 *  and/or modify it under the terms of the GNU Lesser Public License as
 *  published by the Free Software Foundation; either version 2.1 of
 *  the License, or (at your option) any later version.
 *
 *  The ZBar Bar Code Reader is distributed in the hope that it will be
 *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 *  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser Public License
 *  along with the ZBar Bar Code Reader; if not, write to the Free
 *  Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 *  Boston, MA  02110-1301  USA
 *
 *  http://sourceforge.net/projects/zbar
 *------------------------------------------------------------------------*/

#include <config.h>
#include <zbar.h>

#ifdef DEBUG_DATABAR
# define DEBUG_LEVEL (DEBUG_DATABAR)
#endif
#include "debug.h"
#include "decoder.h"

#define GS ('\035')

enum { SCH_NUM, SCH_ALNUM, SCH_ISO646 };

static const signed char finder_hash[0x20] = {
    0x16, 0x1f, 0x02, 0x00, 0x03, 0x00, 0x06, 0x0b,
    0x1f, 0x0e, 0x17, 0x0c, 0x0b, 0x14, 0x11, 0x0c,
    0x1f, 0x03, 0x13, 0x08, 0x00, 0x0a,   -1, 0x16,
    0x0c, 0x09,   -1, 0x1a, 0x1f, 0x1c, 0x00,   -1,
};

        /* ... */
    const unsigned char *p;
    i = (n + 1) / 2 + 1;
    n += 4;
    i = (i * i) / 4;
    dbprintf(2, " {%d,%d:", i, n);
    p = exp_sequences + i;

    fixed >>= 1;
    seq[0] = 0;
    seq[1] = 1;
    for(i = 2; i < n; ) {
        int s = *p;
        if(!(i & 2)) {
            p++;
            s >>= 4;
        }
        else
            s &= 0xf;
        if(s == fixed)
            fixed = -1;
        s <<= 1;
        dbprintf(2, "%x", s);
        seq[i++] = s++;
        seq[i++] = s;
    }
    dbprintf(2, "}");
    seq[n] = -1;
    return(fixed < 1);
}

#define IDX(s) \
    (((s)->finder << 2) | ((s)->color << 1) | ((s)->color ^ (s)->side))

static inline zbar_symbol_type_t
match_segment_exp (zbar_decoder_t *dcode,
                   databar_segment_t *seg,
                   int dir)
{
    databar_decoder_t *db = &dcode->databar;
    int bestsegs[22], i = 0, segs[22], seq[22];
```

[Assistant]
diff --git a/zbar/decoder/databar.c b/zbar/decoder/databar.c
--- a/zbar/decoder/databar.c
+++ b/zbar/decoder/databar.c
@@ -23,6 +23,8 @@

 #include <config.h>
 #include <zbar.h>
+#include <stdlib.h>
+#include <stdio.h>

 #ifdef DEBUG_DATABAR
 # define DEBUG_LEVEL (DEBUG_DATABAR)
@@ -691,6 +693,12 @@ lookup_sequence (databar_segment_t *seg,
             fixed = -1;
         s <<= 1;
         dbprintf(2, "%x", s);
+
+        if (i > 20) {
+            fprintf(stderr, "Bug: Out-of-bounds condition detected\n");
+            exit(99);
+        }
+
         seq[i++] = s++;
         seq[i++] = s;
     }