db-d2/primevul-codebert-embeddings huggingface dataset:
Commit message: ext4: never move the system.data xattr out of the inode body

When expanding the extra isize space, we must never move the
system.data xattr out of the inode body.  For performance reasons, it
doesn't make any sense, and the inline data implementation assumes
that system.data xattr is never in the external xattr block.

This addresses CVE-2018-10880

https://bugzilla.kernel.org/show_bug.cgi?id=200005

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@kernel.org
CVE: CVE-2018-10880
CWE: CWE-787
Vulnerability description: Linux kernel is vulnerable to a stack-out-of-bounds write in the ext4 filesystem code when mounting and writing to a crafted ext4 image in ext4_update_inline_data(). An attacker could use this to cause a system crash and a denial of service.

Project: linux
File: xattr.c

static int ext4_xattr_make_inode_space(handle_t *handle, struct inode *inode,
				       struct ext4_inode *raw_inode,
				       int isize_diff, size_t ifree,
				       size_t bfree, int *total_ino)
{
	struct ext4_xattr_ibody_header *header = IHDR(inode, raw_inode);
	struct ext4_xattr_entry *small_entry;
	struct ext4_xattr_entry *entry;
	struct ext4_xattr_entry *last;
	unsigned int entry_size;	/* EA entry size */
	unsigned int total_size;	/* EA entry size + value size */
	unsigned int min_total_size;
	int error;

	while (isize_diff > ifree) {
		entry = NULL;
		small_entry = NULL;
		min_total_size = ~0U;
		last = IFIRST(header);
		/* Find the entry best suited to be pushed into EA block */
		for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
			total_size = EXT4_XATTR_LEN(last->e_name_len);
			if (!last->e_value_inum)
				total_size += EXT4_XATTR_SIZE(
					       le32_to_cpu(last->e_value_size));
			if (total_size <= bfree &&
			    total_size < min_total_size) {
				if (total_size + ifree < isize_diff) {
					small_entry = last;
				} else {
					entry = last;
					min_total_size = total_size;
				}
			}
		}

		if (entry == NULL) {
			if (small_entry == NULL)
				return -ENOSPC;
			entry = small_entry;
		}

		entry_size = EXT4_XATTR_LEN(entry->e_name_len);
		total_size = entry_size;
		if (!entry->e_value_inum)
			total_size += EXT4_XATTR_SIZE(
					      le32_to_cpu(entry->e_value_size));
		error = ext4_xattr_move_to_block(handle, inode, raw_inode,
						 entry);
		if (error)
			return error;

		*total_ino -= entry_size;
		ifree += total_size;
		bfree -= total_size;
	}

	return 0;
}
Commit message: Fix bug #72749: wddx_deserialize allows illegal memory access
CVE: CVE-2016-7129
CWE: CWE-20
Vulnerability description: The php_wddx_process_data function in ext/wddx/wddx.c in PHP before 5.6.25 and 7.x before 7.0.10 allows remote attackers to cause a denial of service (segmentation fault) or possibly have unspecified other impact via an invalid ISO 8601 time value, as demonstrated by a wddx_deserialize call that mishandles a dateTime element in a wddxPacket XML document.

Project: php-src
File: wddx.c

 */
static void php_wddx_process_data(void *user_data, const XML_Char *s, int len)
{
	st_entry *ent;
	wddx_stack *stack = (wddx_stack *)user_data;
	TSRMLS_FETCH();

	if (!wddx_stack_is_empty(stack) && !stack->done) {
		wddx_stack_top(stack, (void**)&ent);
		switch (ent->type) {
			case ST_STRING:
				if (Z_STRLEN_P(ent->data) == 0) {
					STR_FREE(Z_STRVAL_P(ent->data));
					Z_STRVAL_P(ent->data) = estrndup(s, len);
					Z_STRLEN_P(ent->data) = len;
				} else {
					Z_STRVAL_P(ent->data) = erealloc(Z_STRVAL_P(ent->data), Z_STRLEN_P(ent->data) + len + 1);
					memcpy(Z_STRVAL_P(ent->data) + Z_STRLEN_P(ent->data), s, len);
					Z_STRLEN_P(ent->data) += len;
					Z_STRVAL_P(ent->data)[Z_STRLEN_P(ent->data)] = '\0';
				}
				break;

			case ST_BINARY:
				if (Z_STRLEN_P(ent->data) == 0) {
					STR_FREE(Z_STRVAL_P(ent->data));
					Z_STRVAL_P(ent->data) = estrndup(s, len + 1);
				} else {
					Z_STRVAL_P(ent->data) = erealloc(Z_STRVAL_P(ent->data), Z_STRLEN_P(ent->data) + len + 1);
					memcpy(Z_STRVAL_P(ent->data) + Z_STRLEN_P(ent->data), s, len);
				}
				Z_STRLEN_P(ent->data) += len;
				Z_STRVAL_P(ent->data)[Z_STRLEN_P(ent->data)] = '\0';
				break;

			case ST_NUMBER:
				Z_TYPE_P(ent->data) = IS_STRING;
				Z_STRLEN_P(ent->data) = len;
				Z_STRVAL_P(ent->data) = estrndup(s, len);
				convert_scalar_to_number(ent->data TSRMLS_CC);
				break;

			case ST_BOOLEAN:
				if(!ent->data) {
					break;
				}
				if (!strcmp(s, "true")) {
					Z_LVAL_P(ent->data) = 1;
				} else if (!strcmp(s, "false")) {
					Z_LVAL_P(ent->data) = 0;
				} else {
					zval_ptr_dtor(&ent->data);
					if (ent->varname) {
						efree(ent->varname);
						ent->varname = NULL;
					}
					ent->data = NULL;
				}
				break;

			case ST_DATETIME: {
				char *tmp;

				tmp = emalloc(len + 1);
				memcpy(tmp, s, len);
				tmp[len] = '\0';

				Z_LVAL_P(ent->data) = php_parse_date(tmp, NULL);
				/* date out of range < 1969 or > 2038 */
				if (Z_LVAL_P(ent->data) == -1) {
					Z_TYPE_P(ent->data) = IS_STRING;
					Z_STRLEN_P(ent->data) = len;
					Z_STRVAL_P(ent->data) = estrndup(s, len);
				}
				efree(tmp);
			}
				break;

			default:
				break;
		}
	}
Commit message: Allow only primitive types/enums in RuntimeHelpers.InitializeArray ().
CVE: CVE-2011-0989
CWE: CWE-264
Vulnerability description: The RuntimeHelpers.InitializeArray method in metadata/icall.c in Mono, when Moonlight 2.x before 2.4.1 or 3.x before 3.99.3 is used, does not properly restrict data types, which allows remote attackers to modify internal read-only data structures, and cause a denial of service (plugin crash) or corrupt the internal state of the security manager, via a crafted media file, as demonstrated by modifying a C# struct.

Project: mono
File: icall.c

ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
{
	MonoClass *klass = array->obj.vtable->klass;
	guint32 size = mono_array_element_size (klass);
	MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
	int align;
	const char *field_data;

	if (MONO_TYPE_IS_REFERENCE (type) ||
			(type->type == MONO_TYPE_VALUETYPE &&
				(!mono_type_get_class (type) ||
				mono_type_get_class (type)->has_references))) {
		MonoException *exc = mono_get_exception_argument("array",
			"Cannot initialize array containing references");
		mono_raise_exception (exc);
	}

	if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
		MonoException *exc = mono_get_exception_argument("field_handle",
			"Field doesn't have an RVA");
		mono_raise_exception (exc);
	}

	size *= array->max_length;
	field_data = mono_field_get_data (field_handle);

	if (size > mono_type_size (field_handle->type, &align)) {
		MonoException *exc = mono_get_exception_argument("field_handle",
			"Field not large enough to fill array");
		mono_raise_exception (exc);
	}

#if G_BYTE_ORDER != G_LITTLE_ENDIAN
#define SWAP(n) {\
	guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
	guint ## n *src = (guint ## n *) field_data; \
	guint ## n *end = (guint ## n *)((char*)src + size); \
\
	for (; src < end; data++, src++) { \
		*data = read ## n (src); \
	} \
}

	/* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */

	switch (type->type) {
	case MONO_TYPE_CHAR:
	case MONO_TYPE_I2:
	case MONO_TYPE_U2:
		SWAP (16);
		break;
	case MONO_TYPE_I4:
	case MONO_TYPE_U4:
	case MONO_TYPE_R4:
		SWAP (32);
		break;
	case MONO_TYPE_I8:
	case MONO_TYPE_U8:
	case MONO_TYPE_R8:
		SWAP (64);
		break;
	default:
		memcpy (mono_array_addr (array, char, 0), field_data, size);
		break;
	}
#else
	memcpy (mono_array_addr (array, char, 0), field_data, size);
#ifdef ARM_FPU_FPA
	if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
		gint i;
		double tmp;
		double *data = (double*)mono_array_addr (array, double, 0);

		for (i = 0; i < size; i++, data++) {
			readr8 (data, &tmp);
			*data = tmp;
		}
	}
#endif
#endif
}
Commit message: Fix incorrect bounds check, from Alexander Cherepanov
CVE: CVE-2014-9653
CWE: CWE-20
Vulnerability description: readelf.c in file before 5.22, as used in the Fileinfo component in PHP before 5.4.37, 5.5.x before 5.5.21, and 5.6.x before 5.6.5, does not consider that pread calls sometimes read only a subset of the available data, which allows remote attackers to cause a denial of service (uninitialized memory access) or possibly have unspecified other impact via a crafted ELF file.

Project: file
File: funcs.c

file_printable(char *buf, size_t bufsiz, const char *str)
{
	char *ptr, *eptr;
	const unsigned char *s = (const unsigned char *)str;

	for (ptr = buf, eptr = ptr + bufsiz - 1; ptr < eptr && *s; s++) {
		if (isprint(*s)) {
			*ptr++ = *s;
			continue;
		}
		if (ptr >= eptr + 4)
			break;
		*ptr++ = '\\';
		*ptr++ = ((*s >> 6) & 7) + '0';
		*ptr++ = ((*s >> 3) & 7) + '0';
		*ptr++ = ((*s >> 0) & 7) + '0';
	}
	*ptr = '\0';
	return buf;
}
Commit message: libsepol/cil: Destroy classperm list when resetting map perms

Map perms share the same struct as regular perms, but only the
map perms use the classperms field. This field is a pointer to a
list of classperms that is created and added to when resolving
classmapping rules, so the map permission doesn't own any of the
data in the list and this list should be destroyed when the AST is
reset.

When resetting a perm, destroy the classperms list without destroying
the data in the list.

Signed-off-by: James Carter <jwcart2@gmail.com>
CVE: CVE-2021-36085
CWE: CWE-416
Vulnerability description: The CIL compiler in SELinux 3.2 has a use-after-free in __cil_verify_classperms (called from __verify_map_perm_classperms and hashtab_map).

Project: selinux
File: cil_reset_ast.c

static void cil_reset_perm(struct cil_perm *perm)
{
	cil_reset_classperms_list(perm->classperms);
}
Commit message: Detect xref pointer infinite loop (fixes #149)
CVE: CVE-2017-18186
CWE: CWE-399
Vulnerability description: An issue was discovered in QPDF before 7.0.0. There is an infinite loop due to looping xref tables in QPDF.cc.

Project: qpdf
File: QPDF.cc

QPDF::read_xref(qpdf_offset_t xref_offset)
{
    std::map<int, int> free_table;
    while (xref_offset)
    {
        char buf[7];
        memset(buf, 0, sizeof(buf));
	this->m->file->seek(xref_offset, SEEK_SET);
	this->m->file->read(buf, sizeof(buf) - 1);
        // The PDF spec says xref must be followed by a line
        // terminator, but files exist in the wild where it is
        // terminated by arbitrary whitespace.
        if ((strncmp(buf, "xref", 4) == 0) &&
            QUtil::is_space(buf[4]))
	{
            QTC::TC("qpdf", "QPDF xref space",
                    ((buf[4] == '\n') ? 0 :
                     (buf[4] == '\r') ? 1 :
                     (buf[4] == ' ') ? 2 : 9999));
            int skip = 4;
            // buf is null-terminated, and QUtil::is_space('\0') is
            // false, so this won't overrun.
            while (QUtil::is_space(buf[skip]))
            {
                ++skip;
            }
            xref_offset = read_xrefTable(xref_offset + skip);
	}
	else
	{
	    xref_offset = read_xrefStream(xref_offset);
	}
    }

    if (! this->m->trailer.isInitialized())
    {
        throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), "", 0,
                      "unable to find trailer while reading xref");
    }
    int size = this->m->trailer.getKey("/Size").getIntValue();
    int max_obj = 0;
    if (! this->m->xref_table.empty())
    {
	max_obj = (*(this->m->xref_table.rbegin())).first.getObj();
    }
    if (! this->m->deleted_objects.empty())
    {
	max_obj = std::max(max_obj, *(this->m->deleted_objects.rbegin()));
    }
    if (size != max_obj + 1)
    {
	QTC::TC("qpdf", "QPDF xref size mismatch");
	warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), "", 0,
		     std::string("reported number of objects (") +
		     QUtil::int_to_string(size) +
		     ") inconsistent with actual number of objects (" +
		     QUtil::int_to_string(max_obj + 1) + ")"));
    }

    // We no longer need the deleted_objects table, so go ahead and
    // clear it out to make sure we never depend on its being set.
    this->m->deleted_objects.clear();
}
Commit message: pdfwrite - Guard against trying to output an infinite number

Bug #699255 " Buffer overflow on pprintg1 due to mishandle postscript file data to pdf"

The file uses an enormous parameter to xyxhow, causing an overflow in
the calculation of text positioning (value > 1e39).

Since this is basically a nonsense value, and PostScript only supports
real values up to 1e38, this patch follows the same approach as for
a degenerate CTM, and treats it as 0.

Adobe Acrobat Distiller throws a limitcheck error, so we could do that
instead if this approach proves to be a problem.
CVE: CVE-2018-10194
CWE: CWE-119
Vulnerability description: The set_text_distance function in devices/vector/gdevpdts.c in the pdfwrite component in Artifex Ghostscript through 9.22 does not prevent overflows in text-positioning calculation, which allows remote attackers to cause a denial of service (application crash) or possibly have unspecified other impact via a crafted PDF document.

Project: ghostpdl
File: gdevpdts.c

set_text_distance(gs_point *pdist, double dx, double dy, const gs_matrix *pmat)
{
    int code = gs_distance_transform_inverse(dx, dy, pmat, pdist);
    double rounded;

    if (code == gs_error_undefinedresult) {
        /* The CTM is degenerate.
           Can't know the distance in user space.
           Set zero because we believe it is not important for rendering.
           We want to copy the text to PDF to make it searchable.
           Bug 689006.
         */
        pdist->x = pdist->y = 0;
    } else if (code < 0)
        return code;
    /* If the distance is very close to integers, round it. */
    if (fabs(pdist->x - (rounded = floor(pdist->x + 0.5))) < 0.0005)
        pdist->x = rounded;
    if (fabs(pdist->y - (rounded = floor(pdist->y + 0.5))) < 0.0005)
        pdist->y = rounded;
    return 0;
}
Commit message: Merge branch 'table_resolver'
CVE: CVE-2014-8184
CWE: CWE-119
Vulnerability description: A vulnerability was found in liblouis, versions 2.5.x before 2.5.4. A stack-based buffer overflow was found in findTable() in liblouis. An attacker could create a malicious file that would cause applications that use liblouis (such as Orca) to crash, or potentially execute arbitrary code when opened.

Project: liblouis

findTable (const char *tableName)
{
/* Search paths for tables */
  FILE *tableFile;
  char *pathList;
  char pathEnd[2];
  char trialPath[MAXSTRING];
  if (tableName == NULL || tableName[0] == 0)
    return NULL;
  strcpy (trialPath, tablePath);
  strcat (trialPath, tableName);
  if ((tableFile = fopen (trialPath, "rb")))
    return tableFile;
  pathEnd[0] = DIR_SEP;
  pathEnd[1] = 0;
  /* See if table is on environment path LOUIS_TABLEPATH */
  pathList = getenv ("LOUIS_TABLEPATH");
  if (pathList)
    while (1)
      {
	int k;
	int listLength;
	int currentListPos = 0;
	listLength = strlen (pathList);
	for (k = 0; k < listLength; k++)
	  if (pathList[k] == ',')
	    break;
	if (k == listLength || k == 0)
	  {			/* Only one file */
	    strcpy (trialPath, pathList);
	    strcat (trialPath, pathEnd);
	    strcat (trialPath, tableName);
	    if ((tableFile = fopen (trialPath, "rb")))
	      break;
	  }
	else
	  {			/* Compile a list of files */
	    strncpy (trialPath, pathList, k);
	    trialPath[k] = 0;
	    strcat (trialPath, pathEnd);
	    strcat (trialPath, tableName);
	    currentListPos = k + 1;
	    if ((tableFile = fopen (trialPath, "rb")))
	      break;
	    while (currentListPos < listLength)
	      {
		for (k = currentListPos; k < listLength; k++)
		  if (pathList[k] == ',')
		    break;
		strncpy (trialPath,
			 &pathList[currentListPos], k - currentListPos);
		trialPath[k - currentListPos] = 0;
		strcat (trialPath, pathEnd);
		strcat (trialPath, tableName);
		if ((tableFile = fopen (trialPath, "rb")))
		  currentListPos = k + 1;
		break;
	      }
	  }
	break;
      }
  if (tableFile)
    return tableFile;
  /* See if table in current directory or on a path in 
   * the table name*/
  if ((tableFile = fopen (tableName, "rb")))
    return tableFile;
/* See if table on dataPath. */
  pathList = lou_getDataPath ();
  if (pathList)
    {
      strcpy (trialPath, pathList);
      strcat (trialPath, pathEnd);
#ifdef _WIN32
      strcat (trialPath, "liblouis\\tables\\");
#else
      strcat (trialPath, "liblouis/tables/");
#endif
      strcat (trialPath, tableName);
      if ((tableFile = fopen (trialPath, "rb")))
	return tableFile;
    }
  /* See if table on installed or program path. */
#ifdef _WIN32
  strcpy (trialPath, lou_getProgramPath ());
  strcat (trialPath, "\\share\\liblouis\\tables\\");
#else
  strcpy (trialPath, TABLESDIR);
  strcat (trialPath, pathEnd);
#endif
  strcat (trialPath, tableName);
  if ((tableFile = fopen (trialPath, "rb")))
    return tableFile;
  return NULL;
}
Commit message: SERVER-17264: improve bson validation for utf-8 strings

(cherry picked from commit 394a8569ff14a215c0691aa34440227b2e62a4de)

Conflicts:
	src/mongo/bson/bson_validate_test.cpp
CVE: CVE-2015-1609
CWE: CWE-20
Vulnerability description: MongoDB before 2.4.13 and 2.6.x before 2.6.8 allows remote attackers to cause a denial of service via a crafted UTF-8 string in a BSON request.

Project: mongo

            Status readUTF8String( StringData* out ) {
                int sz;
                if ( !readNumber<int>( &sz ) )
                    return Status( ErrorCodes::InvalidBSON, "invalid bson" );

                if ( out ) {
                    *out = StringData( _buffer + _position, sz );
                }

                if ( !skip( sz - 1 ) )
                    return Status( ErrorCodes::InvalidBSON, "invalid bson" );

                char c;
                if ( !readNumber<char>( &c ) )
                    return Status( ErrorCodes::InvalidBSON, "invalid bson" );

                if ( c != 0 )
                    return Status( ErrorCodes::InvalidBSON, "not null terminate string" );

                return Status::OK();
            }
Commit message: https://github.com/ImageMagick/ImageMagick/issues/793
CVE: CVE-2017-18250
CWE: CWE-476
Vulnerability description: An issue was discovered in ImageMagick 7.0.7. A NULL pointer dereference vulnerability was found in the function LogOpenCLBuildFailure in MagickCore/opencl.c, which allows attackers to cause a denial of service via a crafted file.

Project: ImageMagick
File: opencl.c

static void LogOpenCLBuildFailure(MagickCLDevice device,const char *kernel,
  ExceptionInfo *exception)
{
  char
    filename[MagickPathExtent],
    *log;

  size_t
    log_size;

  (void) FormatLocaleString(filename,MagickPathExtent,"%s%s%s",
    GetOpenCLCacheDirectory(),DirectorySeparator,"magick_badcl.cl");

  (void) remove_utf8(filename);
  (void) BlobToFile(filename,kernel,strlen(kernel),exception);

  openCL_library->clGetProgramBuildInfo(device->program,device->deviceID,
    CL_PROGRAM_BUILD_LOG,0,NULL,&log_size);
  log=(char*)AcquireMagickMemory(log_size);
  openCL_library->clGetProgramBuildInfo(device->program,device->deviceID,
    CL_PROGRAM_BUILD_LOG,log_size,log,&log_size);

  (void) FormatLocaleString(filename,MagickPathExtent,"%s%s%s",
    GetOpenCLCacheDirectory(),DirectorySeparator,"magick_badcl.log");

  (void) remove_utf8(filename);
  (void) BlobToFile(filename,log,log_size,exception);
  log=(char*)RelinquishMagickMemory(log);
}
Commit message: Bug 704834: Fix division by zero for zero width pages in muraster.
CVE: CVE-2021-4216
CWE: CWE-22
Vulnerability description: A Floating point exception (division-by-zero) flaw was found in Mupdf for zero width pages in muraster.c. It is fixed in Mupdf-1.20.0-rc1 upstream.

Project: mupdf

initialise_banding(fz_context *ctx, render_details *render, int color)
{
	size_t min_band_mem;
	int bpp, h, w, reps;

	render->colorspace = output_cs;
	render->format = output_format;
#if GREY_FALLBACK != 0
	if (color == 0)
	{
		if (render->colorspace == CS_RGB)
		{
			/* Fallback from PPM to PGM */
			render->colorspace = CS_GRAY;
			render->format = OUT_PGM;
		}
		else if (render->colorspace == CS_CMYK)
		{
			render->colorspace = CS_GRAY;
			if (render->format == OUT_PKM)
				render->format = OUT_PBM;
			else
				render->format = OUT_PGM;
		}
	}
#endif

	switch (render->colorspace)
	{
	case CS_GRAY:
		bpp = 1;
		break;
	case CS_RGB:
		bpp = 2;
		break;
	default:
	case CS_CMYK:
		bpp = 3;
		break;
	}

	w = render->ibounds.x1 - render->ibounds.x0;
	min_band_mem = (size_t)bpp * w * min_band_height;
	reps = (int)(max_band_memory / min_band_mem);
	if (reps < 1)
		reps = 1;

	/* Adjust reps to even out the work between threads */
	if (render->num_workers > 0)
	{
		int runs, num_bands;
		h = render->ibounds.y1 - render->ibounds.y0;
		num_bands = (h + min_band_height - 1) / min_band_height;
		/* num_bands = number of min_band_height bands */
		runs = (num_bands + reps-1) / reps;
		/* runs = number of worker runs of reps min_band_height bands */
		runs = ((runs + render->num_workers - 1) / render->num_workers) * render->num_workers;
		/* runs = number of worker runs rounded up to make use of all our threads */
		reps = (num_bands + runs - 1) / runs;
	}

	render->band_height_multiple = reps;
	render->bands_rendered = 0;

	if (output_format == OUT_PGM || output_format == OUT_PPM)
	{
		render->bander = fz_new_pnm_band_writer(ctx, out);
		render->n = output_format == OUT_PGM ? 1 : 3;
	}
	else if (output_format == OUT_PAM)
	{
		render->bander = fz_new_pam_band_writer(ctx, out);
		render->n = 4;
	}
	else if (output_format == OUT_PBM)
	{
		render->bander = fz_new_pbm_band_writer(ctx, out);
		render->n = 1;
	}
	else if (output_format == OUT_PKM)
	{
		render->bander = fz_new_pkm_band_writer(ctx, out);
		render->n = 4;
	}
}
Commit message: do not follow symlinks when deleting a folder recursively

[bug #698554]
CVE: CVE-2016-7162
CWE: CWE-20
Vulnerability description: The _g_file_remove_directory function in file-utils.c in File Roller 3.5.4 through 3.20.2 allows remote attackers to delete arbitrary files via a symlink attack on a folder in an archive.

Project: file-roller

_g_file_remove_directory (GFile         *directory,
			  GCancellable  *cancellable,
			  GError       **error)
{
	GFileEnumerator *enumerator;
	GFileInfo       *info;
	gboolean         error_occurred = FALSE;

	if (directory == NULL)
		return TRUE;

	enumerator = g_file_enumerate_children (directory,
					        G_FILE_ATTRIBUTE_STANDARD_NAME ","
					        G_FILE_ATTRIBUTE_STANDARD_TYPE,
					        0,
					        cancellable,
					        error);

	while (! error_occurred && (info = g_file_enumerator_next_file (enumerator, cancellable, error)) != NULL) {
		GFile *child;

		child = g_file_get_child (directory, g_file_info_get_name (info));
		switch (g_file_info_get_file_type (info)) {
		case G_FILE_TYPE_DIRECTORY:
			if (! _g_file_remove_directory (child, cancellable, error))
				error_occurred = TRUE;
			break;
		default:
			if (! g_file_delete (child, cancellable, error))
				error_occurred = TRUE;
			break;
		}

		g_object_unref (child);
		g_object_unref (info);
	}

	if (! error_occurred && ! g_file_delete (directory, cancellable, error))
 		error_occurred = TRUE;

	g_object_unref (enumerator);

	return ! error_occurred;
}