db-d2/primevul-codebert-embeddings huggingface dataset:
Commit message: None
CVE: CVE-2010-3855
CWE: CWE-119
Vulnerability description: Buffer overflow in the ft_var_readpackedpoints function in truetype/ttgxvar.c in FreeType 2.4.3 and earlier allows remote attackers to cause a denial of service (application crash) or possibly execute arbitrary code via a crafted TrueType GX font.

Project: savannah

  ft_var_readpackedpoints( FT_Stream  stream,
                           FT_UInt   *point_cnt )
  {
    FT_UShort *points;
    FT_Int     n;
    FT_Int     runcnt;
    FT_Int     i;
     FT_Int     j;
     FT_Int     first;
     FT_Memory  memory = stream->memory;
    FT_Error   error  = TT_Err_Ok;
 
     FT_UNUSED( error );
 

    *point_cnt = n = FT_GET_BYTE();
    if ( n == 0 )
      return ALL_POINTS;

    if ( n & GX_PT_POINTS_ARE_WORDS )
      n = FT_GET_BYTE() | ( ( n & GX_PT_POINT_RUN_COUNT_MASK ) << 8 );

    if ( FT_NEW_ARRAY( points, n ) )
      return NULL;

    i = 0;
    while ( i < n )
    {
      runcnt = FT_GET_BYTE();
      if ( runcnt & GX_PT_POINTS_ARE_WORDS )
      {
         runcnt = runcnt & GX_PT_POINT_RUN_COUNT_MASK;
         first  = points[i++] = FT_GET_USHORT();
 
        if ( runcnt < 1 || i + runcnt >= n )
           goto Exit;
 
         /* first point not included in runcount */
        for ( j = 0; j < runcnt; ++j )
          points[i++] = (FT_UShort)( first += FT_GET_USHORT() );
      }
      else
       {
         first = points[i++] = FT_GET_BYTE();
 
        if ( runcnt < 1 || i + runcnt >= n )
           goto Exit;
 
         for ( j = 0; j < runcnt; ++j )
          points[i++] = (FT_UShort)( first += FT_GET_BYTE() );
      }
    }

  Exit:
    return points;
  }
Commit message: None
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: ghostscript

 set_text_distance(gs_point *pdist, double dx, double dy, const gs_matrix *pmat)
 {
    int code;
     double rounded;
 
    if (dx > 1e38 || dy > 1e38)
        code = gs_error_undefinedresult;
    else
        code = gs_distance_transform_inverse(dx, dy, pmat, pdist);

     if (code == gs_error_undefinedresult) {
         /* The CTM is degenerate.
            Can't know the distance in user space.
    } 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: None
CVE: CVE-2016-7944
CWE: CWE-190
Vulnerability description: Integer overflow in X.org libXfixes before 5.0.3 on 32-bit platforms might allow remote X servers to gain privileges via a length value of INT_MAX, which triggers the client to stop reading data and get out of sync.

Project: libXfixes

XFixesFetchRegionAndBounds (Display	    *dpy,
			    XserverRegion   region,
			    int		    *nrectanglesRet,
			    XRectangle	    *bounds)
{
    XFixesExtDisplayInfo	*info = XFixesFindDisplay (dpy);
    xXFixesFetchRegionReq	*req;
    xXFixesFetchRegionReply	rep;
    XRectangle			*rects;
    int    			nrects;
    long    			nbytes;
    long			nread;

    XFixesCheckExtension (dpy, info, NULL);
    LockDisplay (dpy);
    GetReq (XFixesFetchRegion, req);
    req->reqType = info->codes->major_opcode;
    req->xfixesReqType = X_XFixesFetchRegion;
    req->region = region;
    *nrectanglesRet = 0;
    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
    {
	UnlockDisplay (dpy);
	SyncHandle ();
	return NULL;
    }
    bounds->x = rep.x;
    bounds->y = rep.y;
     bounds->y = rep.y;
     bounds->width = rep.width;
     bounds->height = rep.height;

    if (rep.length < (INT_MAX >> 2)) {
	nbytes = (long) rep.length << 2;
	nrects = rep.length >> 1;
	rects = Xmalloc (nrects * sizeof (XRectangle));
    } else {
	nbytes = 0;
	nrects = 0;
	rects = NULL;
    }

     if (!rects)
     {
 	_XEatDataWords(dpy, rep.length);
	_XEatData (dpy, (unsigned long) (nbytes - nread));
    }
    UnlockDisplay (dpy);
    SyncHandle();
    *nrectanglesRet = nrects;
    return rects;
}
Commit message: mpegvideo_motion: Handle edge emulation even without unrestricted_mv

Fix out of bounds read.

Bug-Id: 962
Found by: F4B3CD@STARLAB and Agostino Sarubbo
Signed-off-by: Vittorio Giovara <vittorio.giovara@gmail.com>
CVE: CVE-2016-7424
CWE: CWE-476
Vulnerability description: The put_no_rnd_pixels8_xy2_mmx function in x86/rnd_template.c in libav 11.7 and earlier allows remote attackers to cause a denial of service (NULL pointer dereference and crash) via a crafted MP3 file.

Project: libav
File: mpegvideo_motion.c

static inline int hpel_motion(MpegEncContext *s,
                              uint8_t *dest, uint8_t *src,
                              int src_x, int src_y,
                              op_pixels_func *pix_op,
                              int motion_x, int motion_y)
{
    int dxy = 0;
    int emu = 0;

    src_x += motion_x >> 1;
    src_y += motion_y >> 1;

    /* WARNING: do no forget half pels */
    src_x = av_clip(src_x, -16, s->width); // FIXME unneeded for emu?
    if (src_x != s->width)
        dxy |= motion_x & 1;
    src_y = av_clip(src_y, -16, s->height);
    if (src_y != s->height)
         dxy |= (motion_y & 1) << 1;
     src += src_y * s->linesize + src_x;
 
    if ((unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x & 1) - 8, 0) ||
        (unsigned)src_y > FFMAX(s->v_edge_pos - (motion_y & 1) - 8, 0)) {
        s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, src,
                                 s->linesize, s->linesize,
                                 9, 9, src_x, src_y,
                                 s->h_edge_pos, s->v_edge_pos);
        src = s->sc.edge_emu_buffer;
        emu = 1;
     }
     pix_op[dxy](dest, src, s->linesize, 8);
     return emu;
    }
Commit message: Add some sanity checks when checking CRL scores

Note: this was accidentally omitted from OpenSSL 1.0.2 branch.
Without this fix any attempt to use CRLs will crash.

CVE-2016-7052

Thanks to Bruce Stephens and Thomas Jakobi for reporting this issue.

Reviewed-by: Stephen Henson <steve@openssl.org>
Reviewed-by: Rich Salz <rsalz@openssl.org>
CVE: CVE-2016-7052
CWE: CWE-476
Vulnerability description: crypto/x509/x509_vfy.c in OpenSSL 1.0.2i allows remote attackers to cause a denial of service (NULL pointer dereference and application crash) by triggering a CRL operation.

Project: openssl

static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl,
                      X509 **pissuer, int *pscore, unsigned int *preasons,
                      STACK_OF(X509_CRL) *crls)
{
    int i, crl_score, best_score = *pscore;
    unsigned int reasons, best_reasons = 0;
    X509 *x = ctx->current_cert;
    X509_CRL *crl, *best_crl = NULL;
    X509 *crl_issuer = NULL, *best_crl_issuer = NULL;

    for (i = 0; i < sk_X509_CRL_num(crls); i++) {
         crl = sk_X509_CRL_value(crls, i);
         reasons = *preasons;
         crl_score = get_crl_score(ctx, &crl_issuer, &reasons, crl, x);
        if (crl_score < best_score || crl_score == 0)
             continue;
         /* If current CRL is equivalent use it if it is newer */
        if (crl_score == best_score && best_crl != NULL) {
             int day, sec;
             if (ASN1_TIME_diff(&day, &sec, X509_CRL_get_lastUpdate(best_crl),
                                X509_CRL_get_lastUpdate(crl)) == 0)
                continue;
            /*
             * ASN1_TIME_diff never returns inconsistent signs for |day|
             * and |sec|.
             */
            if (day <= 0 && sec <= 0)
                continue;
        }
        best_crl = crl;
        best_crl_issuer = crl_issuer;
        best_score = crl_score;
        best_reasons = reasons;
    }

    if (best_crl) {
        if (*pcrl)
            X509_CRL_free(*pcrl);
        *pcrl = best_crl;
        *pissuer = best_crl_issuer;
        *pscore = best_score;
        *preasons = best_reasons;
        CRYPTO_add(&best_crl->references, 1, CRYPTO_LOCK_X509_CRL);
        if (*pdcrl) {
            X509_CRL_free(*pdcrl);
            *pdcrl = NULL;
        }
        get_delta_sk(ctx, pdcrl, pscore, best_crl, crls);
    }

    if (best_score >= CRL_SCORE_VALID)
        return 1;

    return 0;
}
Commit message: None
CVE: CVE-2017-6414
CWE: CWE-772
Vulnerability description: Memory leak in the vcard_apdu_new function in card_7816.c in libcacard before 2.5.3 allows local guest OS users to cause a denial of service (host memory consumption) via vectors related to allocating a new APDU object.

Project: spice

vcard_apdu_new(unsigned char *raw_apdu, int len, vcard_7816_status_t *status)
{
    VCardAPDU *new_apdu;

    *status = VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE;
    if (len < 4) {
        *status = VCARD7816_STATUS_ERROR_WRONG_LENGTH;
        return NULL;
    }

    new_apdu = g_new(VCardAPDU, 1);
    new_apdu->a_data = g_memdup(raw_apdu, len);
     new_apdu->a_len = len;
     *status = vcard_apdu_set_class(new_apdu);
     if (*status != VCARD7816_STATUS_SUCCESS) {
        vcard_apdu_delete(new_apdu);
         return NULL;
     }
     *status = vcard_apdu_set_length(new_apdu);
     if (*status != VCARD7816_STATUS_SUCCESS) {
        vcard_apdu_delete(new_apdu);
         new_apdu = NULL;
     }
     return new_apdu;
}
Commit message: vrend: never destroy context 0 in vrend_renderer_context_destroy

There will be a crash if the guest destroy context 0. As the context 0 is
allocate in renderer init, not destroy in vrend_renderer_context_destroy.
The context will be freed in renderer fini by calling vrend_decode_reset.

Signed-off-by: Li Qiang <liq3ea@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
CVE: CVE-2017-6210
CWE: CWE-476
Vulnerability description: The vrend_decode_reset function in vrend_decode.c in virglrenderer before 0.6.0 allows local guest OS users to cause a denial of service (NULL pointer dereference and QEMU process crash) by destroying context 0 (zero).

Project: virglrenderer

void vrend_renderer_context_destroy(uint32_t handle)
{
   struct vrend_decode_ctx *ctx;
   bool ret;

    if (handle >= VREND_MAX_CTX)
       return;
 
   /* never destroy context 0 here, it will be destroyed in vrend_decode_reset()*/
   if (handle == 0) {
      return;
   }

    ctx = dec_ctx[handle];
    if (!ctx)
       return;
      vrend_hw_switch_context(dec_ctx[0]->grctx, true);
}
Commit message: vrend: fix memory leak in int blit context

The 'blit_ctx->initialised' is not setted to true.
Every time init blit context, it will create a new
'blit_ctx->gl_context' thus causing a memory leak.
This patch avoid this.

Signed-off-by: Li Qiang <liq3ea@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
CVE: CVE-2017-5993
CWE: CWE-772
Vulnerability description: Memory leak in the vrend_renderer_init_blit_ctx function in vrend_blitter.c in virglrenderer before 0.6.0 allows local guest OS users to cause a denial of service (host memory consumption) via a large number of VIRGL_CCMD_BLIT commands.

Project: virglrenderer

static void vrend_renderer_init_blit_ctx(struct vrend_blitter_ctx *blit_ctx)
{
   struct virgl_gl_ctx_param ctx_params;
   int i;
   if (blit_ctx->initialised) {
      vrend_clicbs->make_current(0, blit_ctx->gl_context);
       return;
    }
 
   blit_ctx->initialised = true;
    ctx_params.shared = true;
    ctx_params.major_ver = VREND_GL_VER_MAJOR;
    ctx_params.minor_ver = VREND_GL_VER_MINOR;

   vrend_clicbs->make_current(0, blit_ctx->gl_context);
   glGenVertexArrays(1, &blit_ctx->vaoid);
   glGenFramebuffers(1, &blit_ctx->fb_id);

   glGenBuffers(1, &blit_ctx->vbo_id);
   blit_build_vs_passthrough(blit_ctx);

   for (i = 0; i < 4; i++)
      blit_ctx->vertices[i][0][3] = 1; /*v.w*/
   glBindVertexArray(blit_ctx->vaoid);
   glBindBuffer(GL_ARRAY_BUFFER, blit_ctx->vbo_id);
}
Commit message: vrend: add sanity check for vertext buffer index

The vertext_buffer_index is read from guest and then used
to index the 'vbo' array in struct 'vrend_sub_context'.
Add sanity check for this to avoid oob issue.

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Li Qiang <liq3ea@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
CVE: CVE-2017-5956
CWE: CWE-125
Vulnerability description: The vrend_draw_vbo function in virglrenderer before 0.6.0 allows local guest OS users to cause a denial of service (out-of-bounds array access and QEMU process crash) via vectors involving vertext_buffer_index.

Project: virglrenderer

static int vrend_decode_create_ve(struct vrend_decode_ctx *ctx, uint32_t handle, uint16_t length)
{
   struct pipe_vertex_element *ve = NULL;
   int num_elements;
   int i;
   int ret;

   if (length < 1)
      return EINVAL;

   if ((length - 1) % 4)
      return EINVAL;

   num_elements = (length - 1) / 4;

   if (num_elements) {
      ve = calloc(num_elements, sizeof(struct pipe_vertex_element));

      if (!ve)
         return ENOMEM;

      for (i = 0; i < num_elements; i++) {
          ve[i].src_offset = get_buf_entry(ctx, VIRGL_OBJ_VERTEX_ELEMENTS_V0_SRC_OFFSET(i));
          ve[i].instance_divisor = get_buf_entry(ctx, VIRGL_OBJ_VERTEX_ELEMENTS_V0_INSTANCE_DIVISOR(i));
          ve[i].vertex_buffer_index = get_buf_entry(ctx, VIRGL_OBJ_VERTEX_ELEMENTS_V0_VERTEX_BUFFER_INDEX(i));

         if (ve[i].vertex_buffer_index >= PIPE_MAX_ATTRIBS)
            return EINVAL;

          ve[i].src_format = get_buf_entry(ctx, VIRGL_OBJ_VERTEX_ELEMENTS_V0_SRC_FORMAT(i));
       }
    }
   return ret;
}
Commit message: None
CVE: CVE-2012-3291
CWE: CWE-119
Vulnerability description: Heap-based buffer overflow in OpenConnect 3.18 allows remote servers to cause a denial of service via a crafted greeting banner.

Project: infradead

static void set_banner(struct openconnect_info *vpninfo)
{
        char *banner, *q;
        const char *p;
 
       if (!vpninfo->banner || !(banner = malloc(strlen(vpninfo->banner)+1))) {
                unsetenv("CISCO_BANNER");
                return;
        }
	p = vpninfo->banner;
	q = banner;
	
	while (*p) {
		if (*p == '%' && isxdigit((int)(unsigned char)p[1]) &&
		    isxdigit((int)(unsigned char)p[2])) {
			*(q++) = unhex(p + 1);
			p += 3;
		} else 
			*(q++) = *(p++);
	}
	*q = 0;
	setenv("CISCO_BANNER", banner, 1);

	free(banner);
}
Commit message: ntpd: respond only to client and symmetric active packets

The busybox NTP implementation doesn't check the NTP mode of packets
received on the server port and responds to any packet with the right
size. This includes responses from another NTP server. An attacker can
send a packet with a spoofed source address in order to create an
infinite loop of responses between two busybox NTP servers. Adding
more packets to the loop increases the traffic between the servers
until one of them has a fully loaded CPU and/or network.

Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
CVE: CVE-2016-6301
CWE: CWE-399
Vulnerability description: The recv_and_process_client_pkt function in networking/ntpd.c in busybox allows remote attackers to cause a denial of service (CPU and bandwidth consumption) via a forged NTP packet, which triggers a communication loop.

Project: busybox

recv_and_process_client_pkt(void /*int fd*/)
{
	ssize_t          size;
	len_and_sockaddr *to;
	struct sockaddr  *from;
	msg_t            msg;
	uint8_t          query_status;
	l_fixedpt_t      query_xmttime;

	to = get_sock_lsa(G_listen_fd);
	from = xzalloc(to->len);

	size = recv_from_to(G_listen_fd, &msg, sizeof(msg), MSG_DONTWAIT, from, &to->u.sa, to->len);
	if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) {
		char *addr;
		if (size < 0) {
			if (errno == EAGAIN)
				goto bail;
			bb_perror_msg_and_die("recv");
		}
		addr = xmalloc_sockaddr2dotted_noport(from);
		bb_error_msg("malformed packet received from %s: size %u", addr, (int)size);
		free(addr);
 		goto bail;
 	}
 
	/* Respond only to client and symmetric active packets */
	if ((msg.m_status & MODE_MASK) != MODE_CLIENT
	 && (msg.m_status & MODE_MASK) != MODE_SYM_ACT
	) {
		goto bail;
	}

 	query_status = msg.m_status;
 	query_xmttime = msg.m_xmttime;
	msg.m_ppoll = G.poll_exp;
	msg.m_precision_exp = G_precision_exp;
	/* this time was obtained between poll() and recv() */
	msg.m_rectime = d_to_lfp(G.cur_time);
	msg.m_xmttime = d_to_lfp(gettime1900d()); /* this instant */
	if (G.peer_cnt == 0) {
		/* we have no peers: "stratum 1 server" mode. reftime = our own time */
		G.reftime = G.cur_time;
	}
	msg.m_reftime = d_to_lfp(G.reftime);
	msg.m_orgtime = query_xmttime;
	msg.m_rootdelay = d_to_sfp(G.rootdelay);
	msg.m_rootdisp = d_to_sfp(G.rootdisp);
	msg.m_refid = G.refid; // (version > (3 << VERSION_SHIFT)) ? G.refid : G.refid3;

	/* We reply from the local address packet was sent to,
	 * this makes to/from look swapped here: */
	do_sendto(G_listen_fd,
		/*from:*/ &to->u.sa, /*to:*/ from, /*addrlen:*/ to->len,
		&msg, size);

 bail:
	free(to);
	free(from);
}
Commit message: None
CVE: CVE-2010-2805
CWE: CWE-20
Vulnerability description: The FT_Stream_EnterFrame function in base/ftstream.c in FreeType before 2.4.2 does not properly validate certain position values, which allows remote attackers to cause a denial of service (application crash) or possibly execute arbitrary code via a crafted font file.

Project: savannah

  FT_Stream_EnterFrame( FT_Stream  stream,
                        FT_ULong   count )
  {
    FT_Error  error = FT_Err_Ok;
    FT_ULong  read_bytes;


    /* check for nested frame access */
    FT_ASSERT( stream && stream->cursor == 0 );

    if ( stream->read )
    {
      /* allocate the frame in memory */
      FT_Memory  memory = stream->memory;


      /* simple sanity check */
      if ( count > stream->size )
      {
        FT_ERROR(( "FT_Stream_EnterFrame:"
                   " frame size (%lu) larger than stream size (%lu)\n",
                   count, stream->size ));

        error = FT_Err_Invalid_Stream_Operation;
        goto Exit;
      }

#ifdef FT_DEBUG_MEMORY
      /* assume _ft_debug_file and _ft_debug_lineno are already set */
      stream->base = (unsigned char*)ft_mem_qalloc( memory, count, &error );
      if ( error )
        goto Exit;
#else
      if ( FT_QALLOC( stream->base, count ) )
        goto Exit;
#endif
      /* read it */
      read_bytes = stream->read( stream, stream->pos,
                                 stream->base, count );
      if ( read_bytes < count )
      {
        FT_ERROR(( "FT_Stream_EnterFrame:"
                   " invalid read; expected %lu bytes, got %lu\n",
                   count, read_bytes ));

        FT_FREE( stream->base );
        error = FT_Err_Invalid_Stream_Operation;
      }
      stream->cursor = stream->base;
      stream->limit  = stream->cursor + count;
      stream->pos   += read_bytes;
    }
    else
     {
       /* check current and new position */
       if ( stream->pos >= stream->size        ||
           stream->size - stream->pos < count )
       {
         FT_ERROR(( "FT_Stream_EnterFrame:"
                    " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n",
                   stream->pos, count, stream->size ));

        error = FT_Err_Invalid_Stream_Operation;
        goto Exit;
      }

      /* set cursor */
      stream->cursor = stream->base + stream->pos;
      stream->limit  = stream->cursor + count;
      stream->pos   += count;
    }

  Exit:
    return error;
  }
Commit message: None
CVE: CVE-2017-5330
CWE: CWE-78
Vulnerability description: ark before 16.12.1 might allow remote attackers to execute arbitrary code via an executable in an archive, related to associated applications.

Project: kde

void Part::slotOpenExtractedEntry(KJob *job)
{
    if (!job->error()) {

        OpenJob *openJob = qobject_cast<OpenJob*>(job);
        Q_ASSERT(openJob);

        m_tmpExtractDirList << openJob->tempDir();

        const QString fullName = openJob->validatedFilePath();

        bool isWritable = m_model->archive() && !m_model->archive()->isReadOnly();

        if (!isWritable) {
            QFile::setPermissions(fullName, QFileDevice::ReadOwner | QFileDevice::ReadGroup | QFileDevice::ReadOther);
        }

        if (isWritable) {
            m_fileWatcher = new QFileSystemWatcher;
            connect(m_fileWatcher, &QFileSystemWatcher::fileChanged, this, &Part::slotWatchedFileModified);
            m_fileWatcher->addPath(fullName);
        }

        if (qobject_cast<OpenWithJob*>(job)) {
            const QList<QUrl> urls = {QUrl::fromUserInput(fullName, QString(), QUrl::AssumeLocalFile)};
            KRun::displayOpenWithDialog(urls, widget());
         } else {
             KRun::runUrl(QUrl::fromUserInput(fullName, QString(), QUrl::AssumeLocalFile),
                          QMimeDatabase().mimeTypeForFile(fullName).name(),
                         widget(), false, false);
         }
     } else if (job->error() != KJob::KilledJobError) {
         KMessageBox::error(widget(), job->errorString());
    }
    setReadyGui();
}
Commit message: None
CVE: CVE-2010-2520
CWE: CWE-119
Vulnerability description: Heap-based buffer overflow in the Ins_IUP function in truetype/ttinterp.c in FreeType before 2.4.0, when TrueType bytecode support is enabled, allows remote attackers to cause a denial of service (application crash) or possibly execute arbitrary code via a crafted font file.

Project: savannah

  Ins_IUP( INS_ARG )
  {
    IUP_WorkerRec  V;
    FT_Byte        mask;

    FT_UInt   first_point;   /* first point of contour        */
    FT_UInt   end_point;     /* end point (last+1) of contour */

    FT_UInt   first_touched; /* first touched point in contour   */
    FT_UInt   cur_touched;   /* current touched point in contour */

    FT_UInt   point;         /* current point   */
    FT_Short  contour;       /* current contour */

    FT_UNUSED_ARG;


    /* ignore empty outlines */
    if ( CUR.pts.n_contours == 0 )
      return;

    if ( CUR.opcode & 1 )
    {
      mask   = FT_CURVE_TAG_TOUCH_X;
      V.orgs = CUR.pts.org;
      V.curs = CUR.pts.cur;
      V.orus = CUR.pts.orus;
    }
    else
    {
      mask   = FT_CURVE_TAG_TOUCH_Y;
      V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );
      V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );
      V.orus = (FT_Vector*)( (FT_Pos*)CUR.pts.orus + 1 );
    }
    V.max_points = CUR.pts.n_points;

    contour = 0;
    point   = 0;

    do
    {
       end_point   = CUR.pts.contours[contour] - CUR.pts.first_point;
       first_point = point;
 
      if ( BOUNDS ( end_point, CUR.pts.n_points ) )
        end_point = CUR.pts.n_points - 1;
 
       while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 )
         point++;

      if ( point <= end_point )
      {
        first_touched = point;
        cur_touched   = point;

        point++;

        while ( point <= end_point )
        {
          if ( ( CUR.pts.tags[point] & mask ) != 0 )
          {
            if ( point > 0 )
              _iup_worker_interpolate( &V,
                                       cur_touched + 1,
                                       point - 1,
                                       cur_touched,
                                       point );
            cur_touched = point;
          }

          point++;
        }

        if ( cur_touched == first_touched )
          _iup_worker_shift( &V, first_point, end_point, cur_touched );
        else
        {
          _iup_worker_interpolate( &V,
                                   (FT_UShort)( cur_touched + 1 ),
                                   end_point,
                                   cur_touched,
                                   first_touched );

          if ( first_touched > 0 )
            _iup_worker_interpolate( &V,
                                     first_point,
                                     first_touched - 1,
                                     cur_touched,
                                     first_touched );
        }
      }
      contour++;
    } while ( contour < CUR.pts.n_contours );
  }