slap_modrdn2mods(
	Operation	*op,
	SlapReply	*rs )
{
	int		a_cnt, d_cnt;
	LDAPRDN		old_rdn = NULL;
	LDAPRDN		new_rdn = NULL;

	assert( !BER_BVISEMPTY( &op->oq_modrdn.rs_newrdn ) );

	/* if requestDN is empty, silently reset deleteOldRDN */
	if ( BER_BVISEMPTY( &op->o_req_dn ) ) op->orr_deleteoldrdn = 0;

	if ( ldap_bv2rdn_x( &op->oq_modrdn.rs_newrdn, &new_rdn,
		(char **)&rs->sr_text, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) ) {
		Debug( LDAP_DEBUG_TRACE,
			"%s slap_modrdn2mods: can't figure out "
			"type(s)/value(s) of newrdn\n",
			op->o_log_prefix, 0, 0 );
		rs->sr_err = LDAP_INVALID_DN_SYNTAX;
		rs->sr_text = "unknown type(s)/value(s) used in RDN";
		goto done;
	}

	if ( op->oq_modrdn.rs_deleteoldrdn ) {
		if ( ldap_bv2rdn_x( &op->o_req_dn, &old_rdn,
			(char **)&rs->sr_text, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) ) {
			Debug( LDAP_DEBUG_TRACE,
				"%s slap_modrdn2mods: can't figure out "
				"type(s)/value(s) of oldrdn\n",
				op->o_log_prefix, 0, 0 );
			rs->sr_err = LDAP_OTHER;
			rs->sr_text = "cannot parse RDN from old DN";
			goto done;
		}
	}
	rs->sr_text = NULL;

	/* Add new attribute values to the entry */
	for ( a_cnt = 0; new_rdn[a_cnt]; a_cnt++ ) {
		AttributeDescription	*desc = NULL;
		Modifications 		*mod_tmp;

		rs->sr_err = slap_bv2ad( &new_rdn[a_cnt]->la_attr, &desc, &rs->sr_text );

		if ( rs->sr_err != LDAP_SUCCESS ) {
			Debug( LDAP_DEBUG_TRACE,
				"%s slap_modrdn2mods: %s: %s (new)\n",
				op->o_log_prefix,
				rs->sr_text,
				new_rdn[ a_cnt ]->la_attr.bv_val );
			goto done;
		}

		if ( !desc->ad_type->sat_equality ) {
			Debug( LDAP_DEBUG_TRACE,
				"%s slap_modrdn2mods: %s: %s (new)\n",
				op->o_log_prefix,
				rs->sr_text,
				new_rdn[ a_cnt ]->la_attr.bv_val );
			rs->sr_text = "naming attribute has no equality matching rule";
			rs->sr_err = LDAP_NAMING_VIOLATION;
			goto done;
		}

		/* Apply modification */
		mod_tmp = ( Modifications * )ch_malloc( sizeof( Modifications ) );
		mod_tmp->sml_desc = desc;
		BER_BVZERO( &mod_tmp->sml_type );
		mod_tmp->sml_numvals = 1;
		mod_tmp->sml_values = ( BerVarray )ch_malloc( 2 * sizeof( struct berval ) );
		ber_dupbv( &mod_tmp->sml_values[0], &new_rdn[a_cnt]->la_value );
		mod_tmp->sml_values[1].bv_val = NULL;
		if( desc->ad_type->sat_equality->smr_normalize) {
			mod_tmp->sml_nvalues = ( BerVarray )ch_malloc( 2 * sizeof( struct berval ) );
			rs->sr_err = desc->ad_type->sat_equality->smr_normalize(
				SLAP_MR_EQUALITY|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
				desc->ad_type->sat_syntax,
				desc->ad_type->sat_equality,
				&mod_tmp->sml_values[0],
				&mod_tmp->sml_nvalues[0], NULL );
			if (rs->sr_err != LDAP_SUCCESS) {
				ch_free(mod_tmp->sml_nvalues);
				ch_free(mod_tmp->sml_values[0].bv_val);
				ch_free(mod_tmp->sml_values);
				ch_free(mod_tmp);
				goto done;
			}
			mod_tmp->sml_nvalues[1].bv_val = NULL;
		} else {
			mod_tmp->sml_nvalues = NULL;
		}
		mod_tmp->sml_op = SLAP_MOD_SOFTADD;
		mod_tmp->sml_flags = 0;
		mod_tmp->sml_next = op->orr_modlist;
		op->orr_modlist = mod_tmp;
	}

	/* Remove old rdn value if required */
	if ( op->orr_deleteoldrdn ) {
		for ( d_cnt = 0; old_rdn[d_cnt]; d_cnt++ ) {
			AttributeDescription	*desc = NULL;
			Modifications 		*mod_tmp;

			rs->sr_err = slap_bv2ad( &old_rdn[d_cnt]->la_attr, &desc, &rs->sr_text );
			if ( rs->sr_err != LDAP_SUCCESS ) {
				Debug( LDAP_DEBUG_TRACE,
					"%s slap_modrdn2mods: %s: %s (old)\n",
					op->o_log_prefix,
					rs->sr_text,
					old_rdn[d_cnt]->la_attr.bv_val );
				goto done;
			}

			/* Apply modification */
			mod_tmp = ( Modifications * )ch_malloc( sizeof( Modifications ) );
			mod_tmp->sml_desc = desc;
			BER_BVZERO( &mod_tmp->sml_type );
			mod_tmp->sml_numvals = 1;
			mod_tmp->sml_values = ( BerVarray )ch_malloc( 2 * sizeof( struct berval ) );
			ber_dupbv( &mod_tmp->sml_values[0], &old_rdn[d_cnt]->la_value );
			mod_tmp->sml_values[1].bv_val = NULL;
			if( desc->ad_type->sat_equality->smr_normalize) {
				mod_tmp->sml_nvalues = ( BerVarray )ch_malloc( 2 * sizeof( struct berval ) );
				(void) (*desc->ad_type->sat_equality->smr_normalize)(
					SLAP_MR_EQUALITY|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
					desc->ad_type->sat_syntax,
					desc->ad_type->sat_equality,
					&mod_tmp->sml_values[0],
					&mod_tmp->sml_nvalues[0], NULL );
				mod_tmp->sml_nvalues[1].bv_val = NULL;
			} else {
				mod_tmp->sml_nvalues = NULL;
			}
			mod_tmp->sml_op = LDAP_MOD_DELETE;
			mod_tmp->sml_flags = 0;
			mod_tmp->sml_next = op->orr_modlist;
			op->orr_modlist = mod_tmp;
		}
	}

done:

	/* LDAP v2 supporting correct attribute handling. */
	if ( rs->sr_err != LDAP_SUCCESS && op->orr_modlist != NULL ) {
		Modifications *tmp;

		for ( ; op->orr_modlist != NULL; op->orr_modlist = tmp ) {
			tmp = op->orr_modlist->sml_next;
			ch_free( op->orr_modlist );
		}
	}

	if ( new_rdn != NULL ) {
		ldap_rdnfree_x( new_rdn, op->o_tmpmemctx );
	}
	if ( old_rdn != NULL ) {
		ldap_rdnfree_x( old_rdn, op->o_tmpmemctx );
	}

	return rs->sr_err;
}

ITS#9370 check for equality rule on old_rdn

Just skip normalization if there's no equality rule. We accept
DNs without equality rules already.


ex_put(exarg_T *eap)
{
    // ":0put" works like ":1put!".
    if (eap->line2 == 0)
    {
	eap->line2 = 1;
	eap->forceit = TRUE;
    }
    curwin->w_cursor.lnum = eap->line2;
    do_put(eap->regname, NULL, eap->forceit ? BACKWARD : FORWARD, 1L,
						       PUT_LINE|PUT_CURSLINE);
}

patch 8.2.3581: reading character past end of line

Problem:    Reading character past end of line.
Solution:   Correct the cursor column.

static void	ex_autocmd(exarg_T *eap);

static void	ex_doautocmd(exarg_T *eap);

static void	ex_bunload(exarg_T *eap);

static void	ex_buffer(exarg_T *eap);

static void	ex_bmodified(exarg_T *eap);

static void	ex_bnext(exarg_T *eap);

static void	ex_bprevious(exarg_T *eap);

static void	ex_brewind(exarg_T *eap);

static void	ex_blast(exarg_T *eap);

static int	getargopt(exarg_T *eap);

static linenr_T default_address(exarg_T *eap);

static linenr_T get_address(exarg_T *, char_u **, cmd_addr_T addr_type, int skip, int silent, int to_other_file, int address_count);

static void address_default_all(exarg_T *eap);

static void	get_flags(exarg_T *eap);

static void	ex_script_ni(exarg_T *eap);

static char	*invalid_range(exarg_T *eap);

static void	correct_range(exarg_T *eap);

static char_u	*replace_makeprg(exarg_T *eap, char_u *p, char_u **cmdlinep);

static char_u	*repl_cmdline(exarg_T *eap, char_u *src, int srclen, char_u *repl, char_u **cmdlinep);

static void	ex_highlight(exarg_T *eap);

static void	ex_colorscheme(exarg_T *eap);

static void	ex_cquit(exarg_T *eap);

static void	ex_quit_all(exarg_T *eap);

static void	ex_close(exarg_T *eap);

static void	ex_win_close(int forceit, win_T *win, tabpage_T *tp);

static void	ex_only(exarg_T *eap);

static void	ex_resize(exarg_T *eap);

static void	ex_stag(exarg_T *eap);

static void	ex_tabclose(exarg_T *eap);

static void	ex_tabonly(exarg_T *eap);

static void	ex_tabnext(exarg_T *eap);

static void	ex_tabmove(exarg_T *eap);

static void	ex_tabs(exarg_T *eap);

static void	ex_pclose(exarg_T *eap);

static void	ex_ptag(exarg_T *eap);

static void	ex_pedit(exarg_T *eap);

static void	ex_hide(exarg_T *eap);

static void	ex_stop(exarg_T *eap);

static void	ex_exit(exarg_T *eap);

static void	ex_print(exarg_T *eap);

static void	ex_goto(exarg_T *eap);

static void	ex_shell(exarg_T *eap);

static void	ex_preserve(exarg_T *eap);

static void	ex_recover(exarg_T *eap);

static void	ex_mode(exarg_T *eap);

static void	ex_wrongmodifier(exarg_T *eap);

static void	ex_find(exarg_T *eap);

static void	ex_open(exarg_T *eap);

static void	ex_edit(exarg_T *eap);

static void	ex_nogui(exarg_T *eap);

static void	ex_tearoff(exarg_T *eap);

static void	ex_popup(exarg_T *eap);

static void	ex_swapname(exarg_T *eap);

static void	ex_syncbind(exarg_T *eap);

static void	ex_read(exarg_T *eap);

static void	ex_pwd(exarg_T *eap);

static void	ex_equal(exarg_T *eap);

static void	ex_sleep(exarg_T *eap);

static void	ex_winsize(exarg_T *eap);

static void	ex_wincmd(exarg_T *eap);

static void	ex_winpos(exarg_T *eap);


MagickExport Image *WaveImage(const Image *image,const double amplitude,
  const double wave_length,const PixelInterpolateMethod method,
  ExceptionInfo *exception)
{
#define WaveImageTag  "Wave/Image"

  CacheView
    *canvas_image_view,
    *wave_view;

  float
    *sine_map;

  Image
    *canvas_image,
    *wave_image;

  MagickBooleanType
    status;

  MagickOffsetType
    progress;

  ssize_t
    i;

  ssize_t
    y;

  /*
    Initialize wave image attributes.
  */
  assert(image != (Image *) NULL);
  assert(image->signature == MagickCoreSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  canvas_image=CloneImage(image,0,0,MagickTrue,exception);
  if (canvas_image == (Image *) NULL)
    return((Image *) NULL);
  if ((canvas_image->alpha_trait == UndefinedPixelTrait) &&
      (canvas_image->background_color.alpha != OpaqueAlpha))
    (void) SetImageAlpha(canvas_image,OpaqueAlpha,exception);
  wave_image=CloneImage(canvas_image,canvas_image->columns,(size_t)
    (canvas_image->rows+2.0*fabs(amplitude)),MagickTrue,exception);
  if (wave_image == (Image *) NULL)
    {
      canvas_image=DestroyImage(canvas_image);
      return((Image *) NULL);
    }
  if (SetImageStorageClass(wave_image,DirectClass,exception) == MagickFalse)
    {
      canvas_image=DestroyImage(canvas_image);
      wave_image=DestroyImage(wave_image);
      return((Image *) NULL);
    }
  /*
    Allocate sine map.
  */
  sine_map=(float *) AcquireQuantumMemory((size_t) wave_image->columns,
    sizeof(*sine_map));
  if (sine_map == (float *) NULL)
    {
      canvas_image=DestroyImage(canvas_image);
      wave_image=DestroyImage(wave_image);
      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
    }
  for (i=0; i < (ssize_t) wave_image->columns; i++)
    sine_map[i]=(float) fabs(amplitude)+amplitude*sin((double)
      ((2.0*MagickPI*i)/wave_length));
  /*
    Wave image.
  */
  status=MagickTrue;
  progress=0;
  canvas_image_view=AcquireVirtualCacheView(canvas_image,exception);
  wave_view=AcquireAuthenticCacheView(wave_image,exception);
  (void) SetCacheViewVirtualPixelMethod(canvas_image_view,
    BackgroundVirtualPixelMethod);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
  #pragma omp parallel for schedule(static) shared(progress,status) \
    magick_number_threads(canvas_image,wave_image,wave_image->rows,1)
#endif
  for (y=0; y < (ssize_t) wave_image->rows; y++)
  {
    const Quantum
      *magick_restrict p;

    Quantum
      *magick_restrict q;

    ssize_t
      x;

    if (status == MagickFalse)
      continue;
    p=GetCacheViewVirtualPixels(canvas_image_view,0,y,canvas_image->columns,1,
      exception);
    q=QueueCacheViewAuthenticPixels(wave_view,0,y,wave_image->columns,1,
      exception);
    if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
      {
        status=MagickFalse;
        continue;
      }
    for (x=0; x < (ssize_t) wave_image->columns; x++)
    {
      status=InterpolatePixelChannels(canvas_image,canvas_image_view,
        wave_image,method,(double) x,(double) (y-sine_map[x]),q,exception);
      if (status == MagickFalse)
        break;
      p+=GetPixelChannels(canvas_image);
      q+=GetPixelChannels(wave_image);
    }
    if (SyncCacheViewAuthenticPixels(wave_view,exception) == MagickFalse)
      status=MagickFalse;
    if (image->progress_monitor != (MagickProgressMonitor) NULL)
      {
        MagickBooleanType
          proceed;

#if defined(MAGICKCORE_OPENMP_SUPPORT)
        #pragma omp atomic
#endif
        progress++;
        proceed=SetImageProgress(canvas_image,WaveImageTag,progress,
          canvas_image->rows);
        if (proceed == MagickFalse)
          status=MagickFalse;
      }
  }
  wave_view=DestroyCacheView(wave_view);
  canvas_image_view=DestroyCacheView(canvas_image_view);
  canvas_image=DestroyImage(canvas_image);
  sine_map=(float *) RelinquishMagickMemory(sine_map);
  if (status == MagickFalse)
    wave_image=DestroyImage(wave_image);
  return(wave_image);
}

/* No explicit global definitions found. */


static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
		       struct packet_type *pt, struct net_device *orig_dev)
{
	struct sock *sk;
	struct packet_sock *po;
	struct sockaddr_ll *sll;
	union tpacket_uhdr h;
	u8 *skb_head = skb->data;
	int skb_len = skb->len;
	unsigned int snaplen, res;
	unsigned long status = TP_STATUS_USER;
	unsigned short macoff, netoff, hdrlen;
	struct sk_buff *copy_skb = NULL;
	struct timespec64 ts;
	__u32 ts_status;
	bool is_drop_n_account = false;
	unsigned int slot_id = 0;
	bool do_vnet = false;

	/* struct tpacket{2,3}_hdr is aligned to a multiple of TPACKET_ALIGNMENT.
	 * We may add members to them until current aligned size without forcing
	 * userspace to call getsockopt(..., PACKET_HDRLEN, ...).
	 */
	BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h2)) != 32);
	BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h3)) != 48);

	if (skb->pkt_type == PACKET_LOOPBACK)
		goto drop;

	sk = pt->af_packet_priv;
	po = pkt_sk(sk);

	if (!net_eq(dev_net(dev), sock_net(sk)))
		goto drop;

	if (dev->header_ops) {
		if (sk->sk_type != SOCK_DGRAM)
			skb_push(skb, skb->data - skb_mac_header(skb));
		else if (skb->pkt_type == PACKET_OUTGOING) {
			/* Special case: outgoing packets have ll header at head */
			skb_pull(skb, skb_network_offset(skb));
		}
	}

	snaplen = skb->len;

	res = run_filter(skb, sk, snaplen);
	if (!res)
		goto drop_n_restore;

	/* If we are flooded, just give up */
	if (__packet_rcv_has_room(po, skb) == ROOM_NONE) {
		atomic_inc(&po->tp_drops);
		goto drop_n_restore;
	}

	if (skb->ip_summed == CHECKSUM_PARTIAL)
		status |= TP_STATUS_CSUMNOTREADY;
	else if (skb->pkt_type != PACKET_OUTGOING &&
		 (skb->ip_summed == CHECKSUM_COMPLETE ||
		  skb_csum_unnecessary(skb)))
		status |= TP_STATUS_CSUM_VALID;

	if (snaplen > res)
		snaplen = res;

	if (sk->sk_type == SOCK_DGRAM) {
		macoff = netoff = TPACKET_ALIGN(po->tp_hdrlen) + 16 +
				  po->tp_reserve;
	} else {
		unsigned int maclen = skb_network_offset(skb);
		netoff = TPACKET_ALIGN(po->tp_hdrlen +
				       (maclen < 16 ? 16 : maclen)) +
				       po->tp_reserve;
		if (po->has_vnet_hdr) {
			netoff += sizeof(struct virtio_net_hdr);
			do_vnet = true;
		}
		macoff = netoff - maclen;
	}
	if (po->tp_version <= TPACKET_V2) {
		if (macoff + snaplen > po->rx_ring.frame_size) {
			if (po->copy_thresh &&
			    atomic_read(&sk->sk_rmem_alloc) < sk->sk_rcvbuf) {
				if (skb_shared(skb)) {
					copy_skb = skb_clone(skb, GFP_ATOMIC);
				} else {
					copy_skb = skb_get(skb);
					skb_head = skb->data;
				}
				if (copy_skb)
					skb_set_owner_r(copy_skb, sk);
			}
			snaplen = po->rx_ring.frame_size - macoff;
			if ((int)snaplen < 0) {
				snaplen = 0;
				do_vnet = false;
			}
		}
	} else if (unlikely(macoff + snaplen >
			    GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len)) {
		u32 nval;

		nval = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len - macoff;
		pr_err_once("tpacket_rcv: packet too big, clamped from %u to %u. macoff=%u\n",
			    snaplen, nval, macoff);
		snaplen = nval;
		if (unlikely((int)snaplen < 0)) {
			snaplen = 0;
			macoff = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len;
			do_vnet = false;
		}
	}
	spin_lock(&sk->sk_receive_queue.lock);
	h.raw = packet_current_rx_frame(po, skb,
					TP_STATUS_KERNEL, (macoff+snaplen));
	if (!h.raw)
		goto drop_n_account;

	if (po->tp_version <= TPACKET_V2) {
		slot_id = po->rx_ring.head;
		if (test_bit(slot_id, po->rx_ring.rx_owner_map))
			goto drop_n_account;
		__set_bit(slot_id, po->rx_ring.rx_owner_map);
	}

	if (do_vnet &&
	    virtio_net_hdr_from_skb(skb, h.raw + macoff -
				    sizeof(struct virtio_net_hdr),
				    vio_le(), true, 0)) {
		if (po->tp_version == TPACKET_V3)
			prb_clear_blk_fill_status(&po->rx_ring);
		goto drop_n_account;
	}

	if (po->tp_version <= TPACKET_V2) {
		packet_increment_rx_head(po, &po->rx_ring);
	/*
	 * LOSING will be reported till you read the stats,
	 * because it's COR - Clear On Read.
	 * Anyways, moving it for V1/V2 only as V3 doesn't need this
	 * at packet level.
	 */
		if (atomic_read(&po->tp_drops))
			status |= TP_STATUS_LOSING;
	}

	po->stats.stats1.tp_packets++;
	if (copy_skb) {
		status |= TP_STATUS_COPY;
		__skb_queue_tail(&sk->sk_receive_queue, copy_skb);
	}
	spin_unlock(&sk->sk_receive_queue.lock);

	skb_copy_bits(skb, 0, h.raw + macoff, snaplen);

	if (!(ts_status = tpacket_get_timestamp(skb, &ts, po->tp_tstamp)))
		ktime_get_real_ts64(&ts);

	status |= ts_status;

	switch (po->tp_version) {
	case TPACKET_V1:
		h.h1->tp_len = skb->len;
		h.h1->tp_snaplen = snaplen;
		h.h1->tp_mac = macoff;
		h.h1->tp_net = netoff;
		h.h1->tp_sec = ts.tv_sec;
		h.h1->tp_usec = ts.tv_nsec / NSEC_PER_USEC;
		hdrlen = sizeof(*h.h1);
		break;
	case TPACKET_V2:
		h.h2->tp_len = skb->len;
		h.h2->tp_snaplen = snaplen;
		h.h2->tp_mac = macoff;
		h.h2->tp_net = netoff;
		h.h2->tp_sec = ts.tv_sec;
		h.h2->tp_nsec = ts.tv_nsec;
		if (skb_vlan_tag_present(skb)) {
			h.h2->tp_vlan_tci = skb_vlan_tag_get(skb);
			h.h2->tp_vlan_tpid = ntohs(skb->vlan_proto);
			status |= TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
		} else {
			h.h2->tp_vlan_tci = 0;
			h.h2->tp_vlan_tpid = 0;
		}
		memset(h.h2->tp_padding, 0, sizeof(h.h2->tp_padding));
		hdrlen = sizeof(*h.h2);
		break;
	case TPACKET_V3:
		/* tp_nxt_offset,vlan are already populated above.
		 * So DONT clear those fields here
		 */
		h.h3->tp_status |= status;
		h.h3->tp_len = skb->len;
		h.h3->tp_snaplen = snaplen;
		h.h3->tp_mac = macoff;
		h.h3->tp_net = netoff;
		h.h3->tp_sec  = ts.tv_sec;
		h.h3->tp_nsec = ts.tv_nsec;
		memset(h.h3->tp_padding, 0, sizeof(h.h3->tp_padding));
		hdrlen = sizeof(*h.h3);
		break;
	default:
		BUG();
	}

	sll = h.raw + TPACKET_ALIGN(hdrlen);
	sll->sll_halen = dev_parse_header(skb, sll->sll_addr);
	sll->sll_family = AF_PACKET;
	sll->sll_hatype = dev->type;
	sll->sll_protocol = skb->protocol;
	sll->sll_pkttype = skb->pkt_type;
	if (unlikely(po->origdev))
		sll->sll_ifindex = orig_dev->ifindex;
	else
		sll->sll_ifindex = dev->ifindex;

	smp_mb();

#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE == 1
	if (po->tp_version <= TPACKET_V2) {
		u8 *start, *end;

		end = (u8 *) PAGE_ALIGN((unsigned long) h.raw +
					macoff + snaplen);

		for (start = h.raw; start < end; start += PAGE_SIZE)
			flush_dcache_page(pgv_to_page(start));
	}
	smp_wmb();
#endif

	if (po->tp_version <= TPACKET_V2) {
		spin_lock(&sk->sk_receive_queue.lock);
		__packet_set_status(po, h.raw, status);
		__clear_bit(slot_id, po->rx_ring.rx_owner_map);
		spin_unlock(&sk->sk_receive_queue.lock);
		sk->sk_data_ready(sk);
	} else if (po->tp_version == TPACKET_V3) {
		prb_clear_blk_fill_status(&po->rx_ring);
	}

drop_n_restore:
	if (skb_head != skb->data && skb_shared(skb)) {
		skb->data = skb_head;
		skb->len = skb_len;
	}
drop:
	if (!is_drop_n_account)
		consume_skb(skb);
	else
		kfree_skb(skb);
	return 0;

drop_n_account:
	spin_unlock(&sk->sk_receive_queue.lock);
	atomic_inc(&po->tp_drops);
	is_drop_n_account = true;

	sk->sk_data_ready(sk);
	kfree_skb(copy_skb);
	goto drop_n_restore;
}

net/packet: fix overflow in tpacket_rcv

Using tp_reserve to calculate netoff can overflow as
tp_reserve is unsigned int and netoff is unsigned short.

This may lead to macoff receving a smaller value then
sizeof(struct virtio_net_hdr), and if po->has_vnet_hdr
is set, an out-of-bounds write will occur when
calling virtio_net_hdr_from_skb.

The bug is fixed by converting netoff to unsigned int
and checking if it exceeds USHRT_MAX.

This addresses CVE-2020-14386

Fixes: 8913336a7e8d ("packet: add PACKET_RESERVE sockopt")
Signed-off-by: Or Cohen <orcohen@paloaltonetworks.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

struct packet_mreq_max {
	int		mr_ifindex;
	unsigned short	mr_type;
	unsigned short	mr_alen;
	unsigned char	mr_address[MAX_ADDR_LEN];
}

union tpacket_uhdr {
	struct tpacket_hdr  *h1;
	struct tpacket2_hdr *h2;
	struct tpacket3_hdr *h3;
	void *raw;
}

static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
		int closing, int tx_ring);

#define BLK_HDR_LEN	(ALIGN(sizeof(struct tpacket_block_desc), V3_ALIGNMENT))

struct packet_sock

static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
		       struct packet_type *pt, struct net_device *orig_dev);

static void *packet_previous_frame(struct packet_sock *po,
		struct packet_ring_buffer *rb,
		int status);

static void packet_increment_head(struct packet_ring_buffer *buff);

static int prb_curr_blk_in_use(struct tpacket_block_desc *);

static void *prb_dispatch_next_block(struct tpacket_kbdq_core *,
			struct packet_sock *);

static void prb_retire_current_block(struct tpacket_kbdq_core *,
		struct packet_sock *, unsigned int status);

static int prb_queue_frozen(struct tpacket_kbdq_core *);

static void prb_open_block(struct tpacket_kbdq_core *,
		struct tpacket_block_desc *);

static void prb_retire_rx_blk_timer_expired(struct timer_list *);

static void _prb_refresh_rx_retire_blk_timer(struct tpacket_kbdq_core *);

static void prb_fill_rxhash(struct tpacket_kbdq_core *, struct tpacket3_hdr *);

static void prb_clear_rxhash(struct tpacket_kbdq_core *,
		struct tpacket3_hdr *);

static void prb_fill_vlan_info(struct tpacket_kbdq_core *,
		struct tpacket3_hdr *);

static void packet_flush_mclist(struct sock *sk);

static u16 packet_pick_tx_queue(struct sk_buff *skb);

struct packet_skb_cb {
	union {
		struct sockaddr_pkt pkt;
		union {
			/* Trick: alias skb original length with
			 * ll.sll_family and ll.protocol in order
			 * to save room.
			 */
			unsigned int origlen;
			struct sockaddr_ll ll;
		};
	} sa;
}

#define vio_le() virtio_legacy_is_little_endian()

#define PACKET_SKB_CB(__skb)	((struct packet_skb_cb *)((__skb)->cb))

#define GET_PBDQC_FROM_RB(x)	((struct tpacket_kbdq_core *)(&(x)->prb_bdqc))

#define GET_PBLOCK_DESC(x, bid)	\
	((struct tpacket_block_desc *)((x)->pkbdq[(bid)].buffer))

#define GET_CURR_PBLOCK_DESC_FROM_CORE(x)	\
	((struct tpacket_block_desc *)((x)->pkbdq[(x)->kactive_blk_num].buffer))

static void __fanout_unlink(struct sock *sk, struct packet_sock *po);

static void __fanout_link(struct sock *sk, struct packet_sock *po);

#define ROOM_NONE	0x0

static LIST_HEAD(fanout_list);

static u16 fanout_next_id;

static const struct proto_ops packet_ops;

static const struct proto_ops packet_ops_spkt;

static struct proto packet_proto = {
	.name	  = "PACKET",
	.owner	  = THIS_MODULE,
	.obj_size = sizeof(struct packet_sock),
};

static const struct vm_operations_struct packet_mmap_ops = {
	.open	=	packet_mm_open,
	.close	=	packet_mm_close,
};


static void set_pixel_format(VncState *vs,
                             int bits_per_pixel, int depth,
                             int big_endian_flag, int true_color_flag,
                             int red_max, int green_max, int blue_max,
                             int red_shift, int green_shift, int blue_shift)
{
    if (!true_color_flag) {
        vnc_client_error(vs);
        return;
    }

    switch (bits_per_pixel) {
    case 8:
    case 16:
    case 32:
        break;
    default:
        vnc_client_error(vs);
        return;
    }

    vs->client_pf.rmax = red_max;
    vs->client_pf.rbits = hweight_long(red_max);
    vs->client_pf.rshift = red_shift;
    vs->client_pf.rmask = red_max << red_shift;
    vs->client_pf.gmax = green_max;
    vs->client_pf.gbits = hweight_long(green_max);
    vs->client_pf.gshift = green_shift;
    vs->client_pf.gmask = green_max << green_shift;
    vs->client_pf.bmax = blue_max;
    vs->client_pf.bbits = hweight_long(blue_max);
    vs->client_pf.bshift = blue_shift;
    vs->client_pf.bmask = blue_max << blue_shift;
    vs->client_pf.bits_per_pixel = bits_per_pixel;
    vs->client_pf.bytes_per_pixel = bits_per_pixel / 8;
    vs->client_pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel;
    vs->client_be = big_endian_flag;

    set_pixel_conversion(vs);

    graphic_hw_invalidate(vs->vd->dcl.con);
    graphic_hw_update(vs->vd->dcl.con);
}

ui: vnc: avoid floating point exception

While sending 'SetPixelFormat' messages to a VNC server,
the client could set the 'red-max', 'green-max' and 'blue-max'
values to be zero. This leads to a floating point exception in
write_png_palette while doing frame buffer updates.

Reported-by: Lian Yihan <lianyihan@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>


repodata_schema2id(Repodata *data, Id *schema, int create)
{
  int h, len, i;
  Id *sp, cid;
  Id *schematahash;

  if (!*schema)
    return 0;	/* XXX: allow empty schema? */
  if ((schematahash = data->schematahash) == 0)
    {
      data->schematahash = schematahash = solv_calloc(256, sizeof(Id));
      for (i = 1; i < data->nschemata; i++)
	{
	  for (sp = data->schemadata + data->schemata[i], h = 0; *sp;)
	    h = h * 7 + *sp++;
	  h &= 255;
	  schematahash[h] = i;
	}
      data->schemadata = solv_extend_resize(data->schemadata, data->schemadatalen, sizeof(Id), SCHEMATADATA_BLOCK);
      data->schemata = solv_extend_resize(data->schemata, data->nschemata, sizeof(Id), SCHEMATA_BLOCK);
    }

  for (sp = schema, len = 0, h = 0; *sp; len++)
    h = h * 7 + *sp++;
  h &= 255;
  len++;

  cid = schematahash[h];
  if (cid)
    {
      if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
        return cid;
      /* cache conflict, do a slow search */
      for (cid = 1; cid < data->nschemata; cid++)
        if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
          return cid;
    }
  /* a new one */
  if (!create)
    return 0;
  data->schemadata = solv_extend(data->schemadata, data->schemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK);
  data->schemata = solv_extend(data->schemata, data->nschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
  /* add schema */
  memcpy(data->schemadata + data->schemadatalen, schema, len * sizeof(Id));
  data->schemata[data->nschemata] = data->schemadatalen;
  data->schemadatalen += len;
  schematahash[h] = data->nschemata;
#if 0
fprintf(stderr, "schema2id: new schema\n");
#endif
  return data->nschemata++;
}

repodata_schema2id: fix heap-buffer-overflow in memcmp

When the length of last schema in data->schemadata is
less than length of input schema, we got a read overflow
in asan test.

Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>

static unsigned char *data_skip_key(Repodata *data, unsigned char *dp, Repokey *key);

#define SCHEMATA_BLOCK 31

#define SCHEMATADATA_BLOCK 255

struct extdata {
  unsigned char *buf;
  int len;
}


int RGWGetObj_ObjStore_S3::send_response_data(bufferlist& bl, off_t bl_ofs,
					      off_t bl_len)
{
  const char *content_type = NULL;
  string content_type_str;
  map<string, string> response_attrs;
  map<string, string>::iterator riter;
  bufferlist metadata_bl;

  if (sent_header)
    goto send_data;

  if (custom_http_ret) {
    set_req_state_err(s, 0);
    dump_errno(s, custom_http_ret);
  } else {
    set_req_state_err(s, (partial_content && !op_ret) ? STATUS_PARTIAL_CONTENT
                  : op_ret);
    dump_errno(s);
  }

  if (op_ret)
    goto done;

  if (range_str)
    dump_range(s, start, end, s->obj_size);

  if (s->system_request &&
      s->info.args.exists(RGW_SYS_PARAM_PREFIX "prepend-metadata")) {

    dump_header(s, "Rgwx-Object-Size", (long long)total_len);

    if (rgwx_stat) {
      /*
       * in this case, we're not returning the object's content, only the prepended
       * extra metadata
       */
      total_len = 0;
    }

    /* JSON encode object metadata */
    JSONFormatter jf;
    jf.open_object_section("obj_metadata");
    encode_json("attrs", attrs, &jf);
    utime_t ut(lastmod);
    encode_json("mtime", ut, &jf);
    jf.close_section();
    stringstream ss;
    jf.flush(ss);
    metadata_bl.append(ss.str());
    dump_header(s, "Rgwx-Embedded-Metadata-Len", metadata_bl.length());
    total_len += metadata_bl.length();
  }

  if (s->system_request && !real_clock::is_zero(lastmod)) {
    /* we end up dumping mtime in two different methods, a bit redundant */
    dump_epoch_header(s, "Rgwx-Mtime", lastmod);
    uint64_t pg_ver = 0;
    int r = decode_attr_bl_single_value(attrs, RGW_ATTR_PG_VER, &pg_ver, (uint64_t)0);
    if (r < 0) {
      ldout(s->cct, 0) << "ERROR: failed to decode pg ver attr, ignoring" << dendl;
    }
    dump_header(s, "Rgwx-Obj-PG-Ver", pg_ver);

    uint32_t source_zone_short_id = 0;
    r = decode_attr_bl_single_value(attrs, RGW_ATTR_SOURCE_ZONE, &source_zone_short_id, (uint32_t)0);
    if (r < 0) {
      ldout(s->cct, 0) << "ERROR: failed to decode pg ver attr, ignoring" << dendl;
    }
    if (source_zone_short_id != 0) {
      dump_header(s, "Rgwx-Source-Zone-Short-Id", source_zone_short_id);
    }
  }

  for (auto &it : crypt_http_responses)
    dump_header(s, it.first, it.second);

  dump_content_length(s, total_len);
  dump_last_modified(s, lastmod);
  dump_header_if_nonempty(s, "x-amz-version-id", version_id);
  if (attrs.find(RGW_ATTR_APPEND_PART_NUM) != attrs.end()) {
    dump_header(s, "x-rgw-object-type", "Appendable");
    dump_header(s, "x-rgw-next-append-position", s->obj_size);
  } else {
    dump_header(s, "x-rgw-object-type", "Normal");
  }

  if (! op_ret) {
    if (! lo_etag.empty()) {
      /* Handle etag of Swift API's large objects (DLO/SLO). It's entirerly
       * legit to perform GET on them through S3 API. In such situation,
       * a client should receive the composited content with corresponding
       * etag value. */
      dump_etag(s, lo_etag);
    } else {
      auto iter = attrs.find(RGW_ATTR_ETAG);
      if (iter != attrs.end()) {
        dump_etag(s, iter->second.to_str());
      }
    }

    for (struct response_attr_param *p = resp_attr_params; p->param; p++) {
      bool exists;
      string val = s->info.args.get(p->param, &exists);
      if (exists) {
	if (strcmp(p->param, "response-content-type") != 0) {
	  response_attrs[p->http_attr] = val;
	} else {
	  content_type_str = val;
	  content_type = content_type_str.c_str();
	}
      }
    }

    for (auto iter = attrs.begin(); iter != attrs.end(); ++iter) {
      const char *name = iter->first.c_str();
      map<string, string>::iterator aiter = rgw_to_http_attrs.find(name);
      if (aiter != rgw_to_http_attrs.end()) {
        if (response_attrs.count(aiter->second) == 0) {
          /* Was not already overridden by a response param. */

          size_t len = iter->second.length();
          string s(iter->second.c_str(), len);
          while (len && !s[len - 1]) {
            --len;
            s.resize(len);
          }
          response_attrs[aiter->second] = s;
        }
      } else if (iter->first.compare(RGW_ATTR_CONTENT_TYPE) == 0) {
        /* Special handling for content_type. */
        if (!content_type) {
          content_type_str = rgw_bl_str(iter->second);
          content_type = content_type_str.c_str();
        }
      } else if (strcmp(name, RGW_ATTR_SLO_UINDICATOR) == 0) {
        // this attr has an extra length prefix from encode() in prior versions
        dump_header(s, "X-Object-Meta-Static-Large-Object", "True");
      } else if (strncmp(name, RGW_ATTR_META_PREFIX,
			 sizeof(RGW_ATTR_META_PREFIX)-1) == 0) {
        /* User custom metadata. */
        name += sizeof(RGW_ATTR_PREFIX) - 1;
        dump_header(s, name, iter->second);
      } else if (iter->first.compare(RGW_ATTR_TAGS) == 0) {
        RGWObjTags obj_tags;
        try{
          auto it = iter->second.cbegin();
          obj_tags.decode(it);
        } catch (buffer::error &err) {
          ldout(s->cct,0) << "Error caught buffer::error couldn't decode TagSet " << dendl;
        }
        dump_header(s, RGW_AMZ_TAG_COUNT, obj_tags.count());
      } else if (iter->first.compare(RGW_ATTR_OBJECT_RETENTION) == 0 && get_retention){
        RGWObjectRetention retention;
        try {
          decode(retention, iter->second);
          dump_header(s, "x-amz-object-lock-mode", retention.get_mode());
          dump_time_header(s, "x-amz-object-lock-retain-until-date", retention.get_retain_until_date());
        } catch (buffer::error& err) {
          ldpp_dout(this, 0) << "ERROR: failed to decode RGWObjectRetention" << dendl;
        }
      } else if (iter->first.compare(RGW_ATTR_OBJECT_LEGAL_HOLD) == 0 && get_legal_hold) {
        RGWObjectLegalHold legal_hold;
        try {
          decode(legal_hold, iter->second);
          dump_header(s, "x-amz-object-lock-legal-hold",legal_hold.get_status());
        } catch (buffer::error& err) {
          ldpp_dout(this, 0) << "ERROR: failed to decode RGWObjectLegalHold" << dendl;
        }
      }
    }
  }

done:
  for (riter = response_attrs.begin(); riter != response_attrs.end();
       ++riter) {
    dump_header(s, riter->first, riter->second);
  }

  if (op_ret == -ERR_NOT_MODIFIED) {
      end_header(s, this);
  } else {
      if (!content_type)
          content_type = "binary/octet-stream";

      end_header(s, this, content_type);
  }

  if (metadata_bl.length()) {
    dump_body(s, metadata_bl);
  }
  sent_header = true;

send_data:
  if (get_data && !op_ret) {
    int r = dump_body(s, bl.c_str() + bl_ofs, bl_len);
    if (r < 0)
      return r;
  }

  return 0;
}

rgw: reject unauthenticated response-header actions

Signed-off-by: Matt Benjamin <mbenjamin@redhat.com>
Reviewed-by: Casey Bodley <cbodley@redhat.com>
(cherry picked from commit d8dd5e513c0c62bbd7d3044d7e2eddcd897bd400)

struct response_attr_param {
  const char *param;
  const char *http_attr;
}

static struct response_attr_param resp_attr_params[] = {
  {"response-content-type", "Content-Type"},
  {"response-content-language", "Content-Language"},
  {"response-expires", "Expires"},
  {"response-cache-control", "Cache-Control"},
  {"response-content-disposition", "Content-Disposition"},
  {"response-content-encoding", "Content-Encoding"},
  {NULL, NULL},
};

struct ver_config_status {
  int status{VersioningSuspended};

  enum MFAStatus {
    MFA_UNKNOWN,
    MFA_DISABLED,
    MFA_ENABLED,
  } mfa_status{MFA_UNKNOWN};
  int retcode{0};

  void decode_xml(XMLObj *obj) {
    string status_str;
    string mfa_str;
    RGWXMLDecoder::decode_xml("Status", status_str, obj);
    if (status_str == "Enabled") {
      status = VersioningEnabled;
    } else if (status_str != "Suspended") {
      status = VersioningStatusInvalid;
    }

    if (RGWXMLDecoder::decode_xml("MfaDelete", mfa_str, obj)) {
      if (mfa_str == "Enabled") {
        mfa_status = MFA_ENABLED;
      } else if (mfa_str == "Disabled") {
        mfa_status = MFA_DISABLED;
      } else {
        retcode = -EINVAL;
      }
    }
  }
}

class RGWLocationConstraint : public XMLObj
{
public:
  RGWLocationConstraint() {}
  ~RGWLocationConstraint() override {}
  bool xml_end(const char *el) override {
    if (!el)
      return false;

    location_constraint = get_data();

    return true;
  }

  string location_constraint;
}

class RGWCreateBucketParser : public RGWXMLParser
{
  XMLObj *alloc_obj(const char *el) override {
    return new XMLObj;
  }

public:
  RGWCreateBucketParser() {}
  ~RGWCreateBucketParser() override {}

  bool get_location_constraint(string& zone_group) {
    XMLObj *config = find_first("CreateBucketConfiguration");
    if (!config)
      return false;

    XMLObj *constraint = config->find_first("LocationConstraint");
    if (!constraint)
      return false;

    zone_group = constraint->get_data();

    return true;
  }
}

class RGWSetRequestPaymentParser : public RGWXMLParser
{
  XMLObj *alloc_obj(const char *el) override {
    return new XMLObj;
  }

public:
  RGWSetRequestPaymentParser() {}
  ~RGWSetRequestPaymentParser() override {}

  int get_request_payment_payer(bool *requester_pays) {
    XMLObj *config = find_first("RequestPaymentConfiguration");
    if (!config)
      return -EINVAL;

    *requester_pays = false;

    XMLObj *field = config->find_first("Payer");
    if (!field)
      return 0;

    auto& s = field->get_data();

    if (stringcasecmp(s, "Requester") == 0) {
      *requester_pays = true;
    } else if (stringcasecmp(s, "BucketOwner") != 0) {
      return -EINVAL;
    }

    return 0;
  }
}

rgw::LDAPHelper* rgw::auth::s3::LDAPEngine::ldh = nullptr;

std::mutex rgw::auth::s3::LDAPEngine::mtx;


_decodeStripYCbCr(Imaging im, ImagingCodecState state, TIFF *tiff) {
    // To avoid dealing with YCbCr subsampling, let libtiff handle it
    // Use a TIFFRGBAImage wrapping the tiff image, and let libtiff handle
    // all of the conversion. Metadata read from the TIFFRGBAImage could
    // be different from the metadata that the base tiff returns.

    INT32 strip_row;
    UINT8 *new_data;
    UINT32 rows_per_strip, row_byte_size, rows_to_read;
    int ret;
    TIFFRGBAImage img;
    char emsg[1024] = "";

    ret = TIFFGetFieldDefaulted(tiff, TIFFTAG_ROWSPERSTRIP, &rows_per_strip);
    if (ret != 1) {
        rows_per_strip = state->ysize;
    }
    TRACE(("RowsPerStrip: %u \n", rows_per_strip));

    if (!(TIFFRGBAImageOK(tiff, emsg) && TIFFRGBAImageBegin(&img, tiff, 0, emsg))) {
        TRACE(("Decode error, msg: %s", emsg));
        state->errcode = IMAGING_CODEC_BROKEN;
        // nothing to clean up, just return
        return -1;
    }

    img.req_orientation = ORIENTATION_TOPLEFT;
    img.col_offset = 0;

    if (state->xsize != img.width || state->ysize != img.height) {
        TRACE(
            ("Inconsistent Image Error: %d =? %d, %d =? %d",
             state->xsize,
             img.width,
             state->ysize,
             img.height));
        state->errcode = IMAGING_CODEC_BROKEN;
        goto decodeycbcr_err;
    }

    /* overflow check for row byte size */
    if (INT_MAX / 4 < img.width) {
        state->errcode = IMAGING_CODEC_MEMORY;
        goto decodeycbcr_err;
    }

    // TiffRGBAImages are 32bits/pixel.
    row_byte_size = img.width * 4;

    /* overflow check for realloc */
    if (INT_MAX / row_byte_size < rows_per_strip) {
        state->errcode = IMAGING_CODEC_MEMORY;
        goto decodeycbcr_err;
    }

    state->bytes = rows_per_strip * row_byte_size;

    TRACE(("StripSize: %d \n", state->bytes));

    /* realloc to fit whole strip */
    /* malloc check above */
    new_data = realloc(state->buffer, state->bytes);
    if (!new_data) {
        state->errcode = IMAGING_CODEC_MEMORY;
        goto decodeycbcr_err;
    }

    state->buffer = new_data;

    for (; state->y < state->ysize; state->y += rows_per_strip) {
        img.row_offset = state->y;
        rows_to_read = min(rows_per_strip, img.height - state->y);

        if (TIFFRGBAImageGet(&img, (UINT32 *)state->buffer, img.width, rows_to_read) ==
            -1) {
            TRACE(("Decode Error, y: %d\n", state->y));
            state->errcode = IMAGING_CODEC_BROKEN;
            goto decodeycbcr_err;
        }

        TRACE(("Decoded strip for row %d \n", state->y));

        // iterate over each row in the strip and stuff data into image
        for (strip_row = 0;
             strip_row < min((INT32)rows_per_strip, state->ysize - state->y);
             strip_row++) {
            TRACE(("Writing data into line %d ; \n", state->y + strip_row));

            // UINT8 * bbb = state->buffer + strip_row * (state->bytes /
            // rows_per_strip); TRACE(("chars: %x %x %x %x\n", ((UINT8 *)bbb)[0],
            // ((UINT8 *)bbb)[1], ((UINT8 *)bbb)[2], ((UINT8 *)bbb)[3]));

            state->shuffle(
                (UINT8 *)im->image[state->y + state->yoff + strip_row] +
                    state->xoff * im->pixelsize,
                state->buffer + strip_row * row_byte_size,
                state->xsize);
        }
    }

decodeycbcr_err:
    TIFFRGBAImageEnd(&img);
    if (state->errcode != 0) {
        return -1;
    }
    return 0;
}

Incorrect error code checking in TiffDecode.c

* since Pillow 8.1.0
* CVE-2021-25289


mono_lookup_pinvoke_call (MonoMethod *method, const char **exc_class, const char **exc_arg)
{
	MonoImage *image = method->klass->image;
	MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
	MonoTableInfo *tables = image->tables;
	MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
	MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
	guint32 im_cols [MONO_IMPLMAP_SIZE];
	guint32 scope_token;
	const char *import = NULL;
	const char *orig_scope;
	const char *new_scope;
	char *error_msg;
	char *full_name, *file_name;
	int i;
	MonoDl *module = NULL;

	g_assert (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL);

	if (piinfo->addr)
		return piinfo->addr;

	if (method->klass->image->dynamic) {
		MonoReflectionMethodAux *method_aux =
			g_hash_table_lookup (
				((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
		if (!method_aux)
			return NULL;

		import = method_aux->dllentry;
		orig_scope = method_aux->dll;
	}
	else {
		if (!piinfo->implmap_idx)
			return NULL;

		mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);

		piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
		import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
		scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
		orig_scope = mono_metadata_string_heap (image, scope_token);
	}

	mono_dllmap_lookup (image, orig_scope, import, &new_scope, &import);

	mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT,
			"DllImport attempting to load: '%s'.", new_scope);

	if (exc_class) {
		*exc_class = NULL;
		*exc_arg = NULL;
	}

	/* we allow a special name to dlopen from the running process namespace */
	if (strcmp (new_scope, "__Internal") == 0)
		module = mono_dl_open (NULL, MONO_DL_LAZY, &error_msg);

	/*
	 * Try loading the module using a variety of names
	 */
	for (i = 0; i < 4; ++i) {
		switch (i) {
		case 0:
			/* Try the original name */
			file_name = g_strdup (new_scope);
			break;
		case 1:
			/* Try trimming the .dll extension */
			if (strstr (new_scope, ".dll") == (new_scope + strlen (new_scope) - 4)) {
				file_name = g_strdup (new_scope);
				file_name [strlen (new_scope) - 4] = '\0';
			}
			else
				continue;
			break;
		case 2:
			if (strstr (new_scope, "lib") != new_scope) {
				file_name = g_strdup_printf ("lib%s", new_scope);
			}
			else
				continue;
			break;
		default:
#ifndef TARGET_WIN32
			if (!g_ascii_strcasecmp ("user32.dll", new_scope) ||
			    !g_ascii_strcasecmp ("kernel32.dll", new_scope) ||
			    !g_ascii_strcasecmp ("user32", new_scope) ||
			    !g_ascii_strcasecmp ("kernel", new_scope)) {
				file_name = g_strdup ("libMonoSupportW.so");
			} else
#endif
				    continue;
#ifndef TARGET_WIN32
			break;
#endif
		}

		if (!module) {
			void *iter = NULL;
			while ((full_name = mono_dl_build_path (NULL, file_name, &iter))) {
				mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT,
						"DllImport loading location: '%s'.", full_name);
				module = cached_module_load (full_name, MONO_DL_LAZY, &error_msg);
				if (!module) {
					mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT,
							"DllImport error loading library: '%s'.",
							error_msg);
					g_free (error_msg);
				}
				g_free (full_name);
				if (module)
					break;
			}
		}

		if (!module) {
			void *iter = NULL;
			while ((full_name = mono_dl_build_path (".", file_name, &iter))) {
				mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT,
					"DllImport loading library: '%s'.", full_name);
				module = cached_module_load (full_name, MONO_DL_LAZY, &error_msg);
				if (!module) {
					mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT,
						"DllImport error loading library '%s'.",
						error_msg);
					g_free (error_msg);
				}
				g_free (full_name);
				if (module)
					break;
			}
		}

		if (!module) {
			mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT,
					"DllImport loading: '%s'.", file_name);
			module = cached_module_load (file_name, MONO_DL_LAZY, &error_msg);
			if (!module) {
				mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT,
						"DllImport error loading library '%s'.",
						error_msg);
			}
		}

		g_free (file_name);

		if (module)
			break;
	}

	if (!module) {
		mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_DLLIMPORT,
				"DllImport unable to load library '%s'.",
				error_msg);
		g_free (error_msg);

		if (exc_class) {
			*exc_class = "DllNotFoundException";
			*exc_arg = new_scope;
		}
		return NULL;
	}

#ifdef TARGET_WIN32
	if (import && import [0] == '#' && isdigit (import [1])) {
		char *end;
		long id;

		id = strtol (import + 1, &end, 10);
		if (id > 0 && *end == '\0')
			import++;
	}
#endif
	mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT,
				"Searching for '%s'.", import);

	if (piinfo->piflags & PINVOKE_ATTRIBUTE_NO_MANGLE) {
		error_msg = mono_dl_symbol (module, import, &piinfo->addr);
	} else {
		char *mangled_name = NULL, *mangled_name2 = NULL;
		int mangle_charset;
		int mangle_stdcall;
		int mangle_param_count;
#ifdef TARGET_WIN32
		int param_count;
#endif

		/*
		 * Search using a variety of mangled names
		 */
		for (mangle_charset = 0; mangle_charset <= 1; mangle_charset ++) {
			for (mangle_stdcall = 0; mangle_stdcall <= 1; mangle_stdcall ++) {
				gboolean need_param_count = FALSE;
#ifdef TARGET_WIN32
				if (mangle_stdcall > 0)
					need_param_count = TRUE;
#endif
				for (mangle_param_count = 0; mangle_param_count <= (need_param_count ? 256 : 0); mangle_param_count += 4) {

					if (piinfo->addr)
						continue;

					mangled_name = (char*)import;
					switch (piinfo->piflags & PINVOKE_ATTRIBUTE_CHAR_SET_MASK) {
					case PINVOKE_ATTRIBUTE_CHAR_SET_UNICODE:
						/* Try the mangled name first */
						if (mangle_charset == 0)
							mangled_name = g_strconcat (import, "W", NULL);
						break;
					case PINVOKE_ATTRIBUTE_CHAR_SET_AUTO:
#ifdef TARGET_WIN32
						if (mangle_charset == 0)
							mangled_name = g_strconcat (import, "W", NULL);
#else
						/* Try the mangled name last */
						if (mangle_charset == 1)
							mangled_name = g_strconcat (import, "A", NULL);
#endif
						break;
					case PINVOKE_ATTRIBUTE_CHAR_SET_ANSI:
					default:
						/* Try the mangled name last */
						if (mangle_charset == 1)
							mangled_name = g_strconcat (import, "A", NULL);
						break;
					}

#ifdef TARGET_WIN32
					if (mangle_param_count == 0)
						param_count = mono_method_signature (method)->param_count * sizeof (gpointer);
					else
						/* Try brute force, since it would be very hard to compute the stack usage correctly */
						param_count = mangle_param_count;

					/* Try the stdcall mangled name */
					/*
					 * gcc under windows creates mangled names without the underscore, but MS.NET
					 * doesn't support it, so we doesn't support it either.
					 */
					if (mangle_stdcall == 1)
						mangled_name2 = g_strdup_printf ("_%s@%d", mangled_name, param_count);
					else
						mangled_name2 = mangled_name;
#else
					mangled_name2 = mangled_name;
#endif

					mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT,
								"Probing '%s'.", mangled_name2);

					error_msg = mono_dl_symbol (module, mangled_name2, &piinfo->addr);

					if (piinfo->addr)
						mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT,
									"Found as '%s'.", mangled_name2);

					if (mangled_name != mangled_name2)
						g_free (mangled_name2);
					if (mangled_name != import)
						g_free (mangled_name);
				}
			}
		}
	}

	if (!piinfo->addr) {
		g_free (error_msg);
		if (exc_class) {
			*exc_class = "EntryPointNotFoundException";
			*exc_arg = import;
		}
		return NULL;
	}
	return piinfo->addr;
}

Search for dllimported shared libs in the base directory, not cwd.

* loader.c: we don't search the current directory anymore for shared
libraries referenced in DllImport attributes, as it has a slight
security risk. We search in the same directory where the referencing
image was loaded from, instead. Fixes bug# 641915.


bool timerqueue_add(struct timerqueue_head *head, struct timerqueue_node *node)
{
	struct rb_node **p = &head->head.rb_node;
	struct rb_node *parent = NULL;
	struct timerqueue_node  *ptr;

	/* Make sure we don't add nodes that are already added */
	WARN_ON_ONCE(!RB_EMPTY_NODE(&node->node));

	while (*p) {
		parent = *p;
		ptr = rb_entry(parent, struct timerqueue_node, node);
		if (node->expires < ptr->expires)
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
	}
	rb_link_node(&node->node, parent, p);
	rb_insert_color(&node->node, &head->head);

	if (!head->next || node->expires < head->next->expires) {
		head->next = node;
		return true;
	}
	return false;
}

lib/timerqueue: Rely on rbtree semantics for next timer

Simplify the timerqueue code by using cached rbtrees and rely on the tree
leftmost node semantics to get the timer with earliest expiration time.
This is a drop in conversion, and therefore semantics remain untouched.

The runtime overhead of cached rbtrees is be pretty much the same as the
current head->next method, noting that when removing the leftmost node,
a common operation for the timerqueue, the rb_next(leftmost) is O(1) as
well, so the next timer will either be the right node or its parent.
Therefore no extra pointer chasing. Finally, the size of the struct
timerqueue_head remains the same.

Passes several hours of rcutorture.

Signed-off-by: Davidlohr Bueso <dbueso@suse.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20190724152323.bojciei3muvfxalm@linux-r8p5


dissect_dnp3_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
  proto_item  *ti, *tdl, *tc, *hidden_item;
  proto_tree  *dnp3_tree, *dl_tree, *field_tree;
  int          offset = 0, temp_offset = 0;
  gboolean     dl_prm;
  guint8       dl_len, dl_ctl, dl_func;
  const gchar *func_code_str;
  guint16      dl_dst, dl_src, calc_dl_crc;

  /* Make entries in Protocol column and Info column on summary display */
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNP 3.0");
  col_clear(pinfo->cinfo, COL_INFO);

  /* Skip "0x0564" header bytes */
  temp_offset += 2;

  dl_len = tvb_get_guint8(tvb, temp_offset);
  temp_offset += 1;

  dl_ctl = tvb_get_guint8(tvb, temp_offset);
  temp_offset += 1;

  dl_dst = tvb_get_letohs(tvb, temp_offset);
  temp_offset += 2;

  dl_src = tvb_get_letohs(tvb, temp_offset);

  dl_func = dl_ctl & DNP3_CTL_FUNC;
  dl_prm = dl_ctl & DNP3_CTL_PRM;
  func_code_str = val_to_str(dl_func, dl_prm ? dnp3_ctl_func_pri_vals : dnp3_ctl_func_sec_vals,
           "Unknown function (0x%02x)");

  /* Make sure source and dest are always in the info column */
  col_append_fstr(pinfo->cinfo, COL_INFO, "from %u to %u", dl_src, dl_dst);
  col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "len=%u, %s", dl_len, func_code_str);

  /* create display subtree for the protocol */
  ti = proto_tree_add_item(tree, proto_dnp3, tvb, offset, -1, ENC_NA);
  dnp3_tree = proto_item_add_subtree(ti, ett_dnp3);

  /* Create Subtree for Data Link Layer */
  dl_tree = proto_tree_add_subtree_format(dnp3_tree, tvb, offset, DNP_HDR_LEN, ett_dnp3_dl, &tdl,
        "Data Link Layer, Len: %u, From: %u, To: %u, ", dl_len, dl_src, dl_dst);
  if (dl_prm) {
    if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tdl, "DIR, ");
    if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tdl, "PRM, ");
    if (dl_ctl & DNP3_CTL_FCB) proto_item_append_text(tdl, "FCB, ");
    if (dl_ctl & DNP3_CTL_FCV) proto_item_append_text(tdl, "FCV, ");
  }
  else {
    if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tdl, "DIR, ");
    if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tdl, "PRM, ");
    if (dl_ctl & DNP3_CTL_RES) proto_item_append_text(tdl, "RES, ");
    if (dl_ctl & DNP3_CTL_DFC) proto_item_append_text(tdl, "DFC, ");
  }
  proto_item_append_text(tdl, "%s", func_code_str);

  /* start bytes */
  proto_tree_add_item(dl_tree, hf_dnp3_start, tvb, offset, 2, ENC_BIG_ENDIAN);
  offset += 2;

  /* add length field */
  proto_tree_add_item(dl_tree, hf_dnp3_len, tvb, offset, 1, ENC_BIG_ENDIAN);
  offset += 1;

  /* Add Control Byte Subtree */
  tc = proto_tree_add_uint_format_value(dl_tree, hf_dnp3_ctl, tvb, offset, 1, dl_ctl,
          "0x%02x (", dl_ctl);
  /* Add Text to Control Byte Subtree Header */
  if (dl_prm) {
    if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tc, "DIR, ");
    if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tc, "PRM, ");
    if (dl_ctl & DNP3_CTL_FCB) proto_item_append_text(tc, "FCB, ");
    if (dl_ctl & DNP3_CTL_FCV) proto_item_append_text(tc, "FCV, ");
  }
  else {
    if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tc, "DIR, ");
    if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tc, "PRM, ");
    if (dl_ctl & DNP3_CTL_RES) proto_item_append_text(tc, "RES, ");
    if (dl_ctl & DNP3_CTL_DFC) proto_item_append_text(tc, "DFC, ");
  }
  proto_item_append_text(tc, "%s)", func_code_str );
  field_tree = proto_item_add_subtree(tc, ett_dnp3_dl_ctl);

  /* Add Control Byte Subtree Items */
  if (dl_prm) {
    proto_tree_add_item(field_tree, hf_dnp3_ctl_dir, tvb, offset, 1, ENC_LITTLE_ENDIAN);
    proto_tree_add_item(field_tree, hf_dnp3_ctl_prm, tvb, offset, 1, ENC_LITTLE_ENDIAN);
    proto_tree_add_item(field_tree, hf_dnp3_ctl_fcb, tvb, offset, 1, ENC_LITTLE_ENDIAN);
    proto_tree_add_item(field_tree, hf_dnp3_ctl_fcv, tvb, offset, 1, ENC_LITTLE_ENDIAN);
    proto_tree_add_item(field_tree, hf_dnp3_ctl_prifunc, tvb, offset, 1, ENC_BIG_ENDIAN);
  }
  else {
    proto_tree_add_item(field_tree, hf_dnp3_ctl_dir, tvb, offset, 1, ENC_LITTLE_ENDIAN);
    proto_tree_add_item(field_tree, hf_dnp3_ctl_prm, tvb, offset, 1, ENC_LITTLE_ENDIAN);
    proto_tree_add_item(field_tree, hf_dnp3_ctl_dfc, tvb, offset, 1, ENC_LITTLE_ENDIAN);
    proto_tree_add_item(field_tree, hf_dnp3_ctl_secfunc, tvb, offset, 1, ENC_BIG_ENDIAN);
  }
    offset += 1;

  /* add destination and source addresses */
  proto_tree_add_item(dl_tree, hf_dnp3_dst, tvb, offset, 2, ENC_LITTLE_ENDIAN);
  hidden_item = proto_tree_add_item(dl_tree, hf_dnp3_addr, tvb, offset, 2, ENC_LITTLE_ENDIAN);
  proto_item_set_hidden(hidden_item);
  offset += 2;
  proto_tree_add_item(dl_tree, hf_dnp3_src, tvb, offset, 2, ENC_LITTLE_ENDIAN);
  hidden_item = proto_tree_add_item(dl_tree, hf_dnp3_addr, tvb, offset, 2, ENC_LITTLE_ENDIAN);
  proto_item_set_hidden(hidden_item);
  offset += 2;

  /* and header CRC */
  calc_dl_crc = calculateCRCtvb(tvb, 0, DNP_HDR_LEN - 2);
  proto_tree_add_checksum(dl_tree, tvb, offset, hf_dnp3_data_hdr_crc,
                          hf_dnp3_data_hdr_crc_status, &ei_dnp3_data_hdr_crc_incorrect,
                          pinfo, calc_dl_crc, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
  offset += 2;

  /* If the DataLink function is 'Request Link Status' or 'Status of Link',
     or 'Reset Link' we don't expect any Transport or Application Layer Data
     NOTE: This code should probably check what DOES have TR or AL data */
  if ((dl_func != DL_FUNC_LINK_STAT) && (dl_func != DL_FUNC_STAT_LINK) &&
      (dl_func != DL_FUNC_RESET_LINK) && (dl_func != DL_FUNC_ACK))
  {
    proto_tree *data_tree;
    proto_item *data_ti;
    guint8      tr_ctl, tr_seq;
    gboolean    tr_fir, tr_fin;
    guint8     *al_buffer, *al_buffer_ptr;
    guint8      data_len;
    int         data_start = offset;
    int         tl_offset;
    gboolean    crc_OK = FALSE;
    tvbuff_t   *next_tvb;
    guint       i;
    static int * const transport_flags[] = {
      &hf_dnp3_tr_fin,
      &hf_dnp3_tr_fir,
      &hf_dnp3_tr_seq,
      NULL
    };

    /* get the transport layer byte */
    tr_ctl = tvb_get_guint8(tvb, offset);
    tr_seq = tr_ctl & DNP3_TR_SEQ;
    tr_fir = tr_ctl & DNP3_TR_FIR;
    tr_fin = tr_ctl & DNP3_TR_FIN;

    /* Add Transport Layer Tree */
    tc = proto_tree_add_bitmask(dnp3_tree, tvb, offset, hf_dnp3_tr_ctl, ett_dnp3_tr_ctl, transport_flags, ENC_BIG_ENDIAN);
    proto_item_append_text(tc, "(");
    if (tr_fir) proto_item_append_text(tc, "FIR, ");
    if (tr_fin) proto_item_append_text(tc, "FIN, ");
    proto_item_append_text(tc, "Sequence %u)", tr_seq);

    /* Add data chunk tree */
    data_tree = proto_tree_add_subtree(dnp3_tree, tvb, offset, -1, ett_dnp3_dl_data, &data_ti, "Data Chunks");

    /* extract the application layer data, validating the CRCs */

    /* XXX - check for dl_len <= 5 */
    data_len = dl_len - 5;
    al_buffer = (guint8 *)wmem_alloc(pinfo->pool, data_len);
    al_buffer_ptr = al_buffer;
    i = 0;
    tl_offset = 1;  /* skip the initial transport layer byte when assembling chunks for the application layer tvb */
    while (data_len > 0)
    {
      guint8        chk_size;
      const guint8 *chk_ptr;
      proto_tree   *chk_tree;
      proto_item   *chk_len_ti;
      guint16       calc_crc, act_crc;

      chk_size = MIN(data_len, AL_MAX_CHUNK_SIZE);
      chk_ptr  = tvb_get_ptr(tvb, offset, chk_size);
      memcpy(al_buffer_ptr, chk_ptr + tl_offset, chk_size - tl_offset);
      al_buffer_ptr += chk_size - tl_offset;

      chk_tree = proto_tree_add_subtree_format(data_tree, tvb, offset, chk_size + 2, ett_dnp3_dl_chunk, NULL, "Data Chunk: %u", i);
      proto_tree_add_item(chk_tree, hf_dnp3_data_chunk, tvb, offset, chk_size, ENC_NA);
      chk_len_ti = proto_tree_add_uint(chk_tree, hf_dnp3_data_chunk_len, tvb, offset, 0, chk_size);
      proto_item_set_generated(chk_len_ti);

      offset  += chk_size;

      calc_crc = calculateCRC(chk_ptr, chk_size);
      proto_tree_add_checksum(chk_tree, tvb, offset, hf_dnp3_data_chunk_crc,
                              hf_dnp3_data_chunk_crc_status, &ei_dnp3_data_chunk_crc_incorrect,
                              pinfo, calc_crc, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
      act_crc  = tvb_get_letohs(tvb, offset);
      offset  += 2;
      crc_OK   = calc_crc == act_crc;
      if (!crc_OK)
      {
        /* Don't trust the rest of the data, get out of here */
        break;
      }
      data_len -= chk_size;
      i++;
      tl_offset = 0;  /* copy all the data in the rest of the chunks */
    }
    proto_item_set_len(data_ti, offset - data_start);

    /* if crc OK, set up new tvb */
    if (crc_OK)
    {
      tvbuff_t *al_tvb;
      gboolean  save_fragmented;

      al_tvb = tvb_new_child_real_data(tvb, al_buffer, (guint) (al_buffer_ptr-al_buffer), (gint) (al_buffer_ptr-al_buffer));

      /* Check for fragmented packet */
      save_fragmented = pinfo->fragmented;

      /* Reassemble AL fragments */
      static guint al_max_fragments = 60;
      static guint al_fragment_aging = 64; /* sequence numbers only 6 bit */
      fragment_head *frag_al = NULL;
      pinfo->fragmented = TRUE;
      if (!pinfo->fd->visited)
      {
        frag_al = fragment_add_seq_single_aging(&al_reassembly_table,
            al_tvb, 0, pinfo, tr_seq, NULL,
            tvb_reported_length(al_tvb), /* As this is a constructed tvb, all of it is ok */
            tr_fir, tr_fin,
            al_max_fragments, al_fragment_aging);
      }
      else
      {
        frag_al = fragment_get_reassembled_id(&al_reassembly_table, pinfo, tr_seq);
      }
      next_tvb = process_reassembled_data(al_tvb, 0, pinfo,
          "Reassembled DNP 3.0 Application Layer message", frag_al, &dnp3_frag_items,
          NULL, dnp3_tree);

      if (frag_al)
      {
        if (pinfo->num == frag_al->reassembled_in && pinfo->curr_layer_num == frag_al->reas_in_layer_num)
        {
          /* As a complete AL message will have cleared the info column,
             make sure source and dest are always in the info column */
          //col_append_fstr(pinfo->cinfo, COL_INFO, "from %u to %u", dl_src, dl_dst);
          //col_set_fence(pinfo->cinfo, COL_INFO);
          dissect_dnp3_al(next_tvb, pinfo, dnp3_tree);
        }
        else
        {
          /* Lock any column info set by the DL and TL */
          col_set_fence(pinfo->cinfo, COL_INFO);
          col_append_fstr(pinfo->cinfo, COL_INFO,
              " (Application Layer fragment %u, reassembled in packet %u)",
              tr_seq, frag_al->reassembled_in);
          proto_tree_add_item(dnp3_tree, hf_al_frag_data, al_tvb, 0, -1, ENC_NA);
        }
      }
      else
      {
        col_append_fstr(pinfo->cinfo, COL_INFO,
            " (Application Layer Unreassembled fragment %u)",
            tr_seq);
        proto_tree_add_item(dnp3_tree, hf_al_frag_data, al_tvb, 0, -1, ENC_NA);
      }

      pinfo->fragmented = save_fragmented;
    }
    else
    {
      /* CRC error - throw away the data. */
      next_tvb = NULL;
    }
  }

  /* Set the length of the message */
  proto_item_set_len(ti, offset);
  return offset;
}

dnp: plug a memory leak.

If we're throwing away the data, *throw away the data* - free it, as
we're not using it as the backing data for a tvbuff.

#define DNP_HDR_LEN     10

#define DNP3_CTL_DIR    0x80

#define DNP3_CTL_PRM    0x40

#define DNP3_CTL_FCB    0x20

#define DNP3_CTL_FCV    0x10

#define DNP3_CTL_RES    0x20

#define DNP3_CTL_DFC    0x10

#define DNP3_CTL_FUNC   0x0f

#define DNP3_TR_FIR     0x40

#define DNP3_TR_FIN     0x80

#define DNP3_TR_SEQ     0x3f

#define AL_MAX_CHUNK_SIZE 16

#define DL_FUNC_RESET_LINK  0x00

#define DL_FUNC_LINK_STAT   0x09

#define DL_FUNC_ACK         0x00

#define DL_FUNC_STAT_LINK   0x0B

#define AL_FUNC_FRZCLR     0x09    /* 09  - Freeze and Clear */

#define AL_FUNC_FRZCLRNACK 0x0A    /* 10  - Freeze and Clear No ACK */

#define AL_FUNC_INITDATA   0x0F    /* 15  - Initialize Data */

#define AL_FUNC_INITAPP    0x10    /* 16  - Initialize Application */

#define AL_FUNC_STARTAPP   0x11    /* 17  - Start Application */

#define AL_FUNC_STOPAPP    0x12    /* 18  - Stop Application */

#define AL_FUNC_GETFILEINF 0x1C    /* 28  - Get File Info */

#define AL_FUNC_AUTHREQ    0x20    /* 32  - Authentication Request */

#define AL_IIN_BMSG        0x0100   /* Bit 0 - Broadcast message rx'd */

#define AL_IIN_CLS1D       0x0200   /* Bit 1 - Class 1 Data Available */

#define AL_IIN_CLS2D       0x0400   /* Bit 2 - Class 2 Data Available */

#define AL_IIN_CLS3D       0x0800   /* Bit 3 - Class 3 Data Available */

#define AL_IIN_TSR         0x1000   /* Bit 4 - Time Sync Req'd from Master */

#define AL_IIN_FCNI        0x0001   /* Bit 0 - Function code not implemented */

#define AL_IIN_OBJU        0x0002   /* Bit 1 - Requested Objects Unknown */

#define AL_OBJQ_PREFIX         0x70    /* x111xxxx Masks Prefix from Qualifier */

#define AL_OBJQ_RANGE          0x0F    /* xxxx1111 Masks Range from Qualifier */

#define AL_OBJQL_PREFIX_NI     0x00    /* Objects are Packed with no index */

#define AL_OBJQL_PREFIX_1O     0x01    /* Objects are prefixed w/ 1-octet index */

#define AL_OBJQL_PREFIX_2O     0x02    /* Objects are prefixed w/ 2-octet index */

#define AL_OBJQL_PREFIX_4O     0x03    /* Objects are prefixed w/ 4-octet index */

#define AL_OBJQL_PREFIX_1OS    0x04    /* Objects are prefixed w/ 1-octet object size */

#define AL_OBJQL_PREFIX_2OS    0x05    /* Objects are prefixed w/ 2-octet object size */

#define AL_OBJQL_PREFIX_4OS    0x06    /* Objects are prefixed w/ 4-octet object size */


static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoPtr, char **pszEncoding, char *szValuePtr, int ByteCount)
{
	int   a;
	char  *decode;
	size_t len;

	*pszEncoding = NULL;
	/* Copy the comment */
	if (ByteCount>=8) {
		const zend_encoding *from, *to;
		if (!memcmp(szValuePtr, "UNICODE\0", 8)) {
			*pszEncoding = estrdup((const char*)szValuePtr);
			szValuePtr = szValuePtr+8;
			ByteCount -= 8;
			/* First try to detect BOM: ZERO WIDTH NOBREAK SPACE (FEFF 16)
			 * since we have no encoding support for the BOM yet we skip that.
			 */
			if (!memcmp(szValuePtr, "\xFE\xFF", 2)) {
				decode = "UCS-2BE";
				szValuePtr = szValuePtr+2;
				ByteCount -= 2;
			} else if (!memcmp(szValuePtr, "\xFF\xFE", 2)) {
				decode = "UCS-2LE";
				szValuePtr = szValuePtr+2;
				ByteCount -= 2;
			} else if (ImageInfo->motorola_intel) {
				decode = ImageInfo->decode_unicode_be;
			} else {
				decode = ImageInfo->decode_unicode_le;
			}
			to = zend_multibyte_fetch_encoding(ImageInfo->encode_unicode);
			from = zend_multibyte_fetch_encoding(decode);
			/* XXX this will fail again if encoding_converter returns on error something different than SIZE_MAX   */
			if (!to || !from || zend_multibyte_encoding_converter(
					(unsigned char**)pszInfoPtr,
					&len,
					(unsigned char*)szValuePtr,
					ByteCount,
					to,
					from) == (size_t)-1) {
				len = exif_process_string_raw(pszInfoPtr, szValuePtr, ByteCount);
			}
			return len;
		} else if (!memcmp(szValuePtr, "ASCII\0\0\0", 8)) {
			*pszEncoding = estrdup((const char*)szValuePtr);
			szValuePtr = szValuePtr+8;
			ByteCount -= 8;
		} else if (!memcmp(szValuePtr, "JIS\0\0\0\0\0", 8)) {
			/* JIS should be tanslated to MB or we leave it to the user - leave it to the user */
			*pszEncoding = estrdup((const char*)szValuePtr);
			szValuePtr = szValuePtr+8;
			ByteCount -= 8;
			/* XXX this will fail again if encoding_converter returns on error something different than SIZE_MAX   */
			to = zend_multibyte_fetch_encoding(ImageInfo->encode_jis);
			from = zend_multibyte_fetch_encoding(ImageInfo->motorola_intel ? ImageInfo->decode_jis_be : ImageInfo->decode_jis_le);
			if (!to || !from || zend_multibyte_encoding_converter(
					(unsigned char**)pszInfoPtr,
					&len,
					(unsigned char*)szValuePtr,
					ByteCount,
					to,
					from) == (size_t)-1) {
				len = exif_process_string_raw(pszInfoPtr, szValuePtr, ByteCount);
			}
			return len;
		} else if (!memcmp(szValuePtr, "\0\0\0\0\0\0\0\0", 8)) {
			/* 8 NULL means undefined and should be ASCII... */
			*pszEncoding = estrdup("UNDEFINED");
			szValuePtr = szValuePtr+8;
			ByteCount -= 8;
		}
	}

	/* Olympus has this padded with trailing spaces.  Remove these first. */
	if (ByteCount>0) {
		for (a=ByteCount-1;a && szValuePtr[a]==' ';a--) {
			(szValuePtr)[a] = '\0';
		}
	}

	/* normal text without encoding */
	exif_process_string(pszInfoPtr, szValuePtr, ByteCount);
	return strlen(*pszInfoPtr);
}

Fix bug #78256 (heap-buffer-overflow on exif_process_user_comment)

(cherry picked from commit aeb6d13185a2ea4f1496ede2697469faed98ce05)

#define EXIFERR_DC , const char *_file, size_t _line

typedef unsigned char uchar;

static const zend_function_entry exif_functions[] = {
	PHP_FE(exif_read_data, arginfo_exif_read_data)
	PHP_FE(exif_tagname, arginfo_exif_tagname)
	PHP_FE(exif_thumbnail, arginfo_exif_thumbnail)
	PHP_FE(exif_imagetype, arginfo_exif_imagetype)
	PHP_FE_END
};

ZEND_BEGIN_MODULE_GLOBALS(exif)
	char * encode_unicode;

char * decode_unicode_be;

char * decode_unicode_le;

char * encode_jis;

char * decode_jis_be;

char * decode_jis_le;

static const zend_module_dep exif_module_deps[] = {
	ZEND_MOD_REQUIRED("standard")
	ZEND_MOD_OPTIONAL("mbstring")
	ZEND_MOD_END
};

zend_module_entry exif_module_entry = {
	STANDARD_MODULE_HEADER_EX, NULL,
	exif_module_deps,
	"exif",
	exif_functions,
	PHP_MINIT(exif),
	PHP_MSHUTDOWN(exif),
	NULL, NULL,
	PHP_MINFO(exif),
	PHP_EXIF_VERSION,
	PHP_MODULE_GLOBALS(exif),
	PHP_GINIT(exif),
	NULL,
	NULL,
	STANDARD_MODULE_PROPERTIES_EX
};

static const char * EXIF_ERROR_FILEEOF   = "Unexpected end of file reached";

static const char * EXIF_ERROR_CORRUPT   = "File structure corrupted";

static const char * EXIF_ERROR_THUMBEOF  = "Thumbnail goes IFD boundary or end of file reached";

static const char * EXIF_ERROR_FSREALLOC = "Illegal reallocating of undefined file section";

#define EXIF_ERRLOG_FILEEOF(ImageInfo)    exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "%s", EXIF_ERROR_FILEEOF);

#define EXIF_ERRLOG_CORRUPT(ImageInfo)    exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "%s", EXIF_ERROR_CORRUPT);

#define EXIF_ERRLOG_THUMBEOF(ImageInfo)   exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "%s", EXIF_ERROR_THUMBEOF);

#define EXIF_ERRLOG_FSREALLOC(ImageInfo)  exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "%s", EXIF_ERROR_FSREALLOC);

static int php_tiff_bytes_per_format[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 1};

#define TAG_NONE               			-1 /* note that -1 <> 0xFFFF */

typedef const struct {
	unsigned short Tag;
	char *Desc;
} tag_info_type;

#define TAG_TABLE_END \
  {TAG_NONE,           "No tag value"},\
  {TAG_COMPUTED_VALUE, "Computed value"},\
  {TAG_END_OF_LIST,    ""}  /* Important for exif_get_tagname() IF value != "" function result is != false */


static uint16_t nvme_map_addr(NvmeCtrl *n, NvmeSg *sg, hwaddr addr, size_t len)
{
    bool cmb = false, pmr = false;

    if (!len) {
        return NVME_SUCCESS;
    }

    trace_pci_nvme_map_addr(addr, len);

    if (nvme_addr_is_cmb(n, addr)) {
        cmb = true;
    } else if (nvme_addr_is_pmr(n, addr)) {
        pmr = true;
    }

    if (cmb || pmr) {
        if (sg->flags & NVME_SG_DMA) {
            return NVME_INVALID_USE_OF_CMB | NVME_DNR;
        }

        if (sg->iov.niov + 1 > IOV_MAX) {
            goto max_mappings_exceeded;
        }

        if (cmb) {
            return nvme_map_addr_cmb(n, &sg->iov, addr, len);
        } else {
            return nvme_map_addr_pmr(n, &sg->iov, addr, len);
        }
    }

    if (!(sg->flags & NVME_SG_DMA)) {
        return NVME_INVALID_USE_OF_CMB | NVME_DNR;
    }

    if (sg->qsg.nsg + 1 > IOV_MAX) {
        goto max_mappings_exceeded;
    }

    qemu_sglist_add(&sg->qsg, addr, len);

    return NVME_SUCCESS;

max_mappings_exceeded:
    NVME_GUEST_ERR(pci_nvme_ub_too_many_mappings,
                   "number of mappings exceed 1024");
    return NVME_INTERNAL_DEV_ERROR | NVME_DNR;
}

hw/nvme: fix CVE-2021-3929

This fixes CVE-2021-3929 "locally" by denying DMA to the iomem of the
device itself. This still allows DMA to MMIO regions of other devices
(e.g. doing P2P DMA to the controller memory buffer of another NVMe
device).

Fixes: CVE-2021-3929
Reported-by: Qiuhao Li <Qiuhao.Li@outlook.com>
Reviewed-by: Keith Busch <kbusch@kernel.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Klaus Jensen <k.jensen@samsung.com>


int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds,
		 bool nonblock)
{
	int error;
	int full_check = 0;
	struct fd f, tf;
	struct eventpoll *ep;
	struct epitem *epi;
	struct eventpoll *tep = NULL;

	error = -EBADF;
	f = fdget(epfd);
	if (!f.file)
		goto error_return;

	/* Get the "struct file *" for the target file */
	tf = fdget(fd);
	if (!tf.file)
		goto error_fput;

	/* The target file descriptor must support poll */
	error = -EPERM;
	if (!file_can_poll(tf.file))
		goto error_tgt_fput;

	/* Check if EPOLLWAKEUP is allowed */
	if (ep_op_has_event(op))
		ep_take_care_of_epollwakeup(epds);

	/*
	 * We have to check that the file structure underneath the file descriptor
	 * the user passed to us _is_ an eventpoll file. And also we do not permit
	 * adding an epoll file descriptor inside itself.
	 */
	error = -EINVAL;
	if (f.file == tf.file || !is_file_epoll(f.file))
		goto error_tgt_fput;

	/*
	 * epoll adds to the wakeup queue at EPOLL_CTL_ADD time only,
	 * so EPOLLEXCLUSIVE is not allowed for a EPOLL_CTL_MOD operation.
	 * Also, we do not currently supported nested exclusive wakeups.
	 */
	if (ep_op_has_event(op) && (epds->events & EPOLLEXCLUSIVE)) {
		if (op == EPOLL_CTL_MOD)
			goto error_tgt_fput;
		if (op == EPOLL_CTL_ADD && (is_file_epoll(tf.file) ||
				(epds->events & ~EPOLLEXCLUSIVE_OK_BITS)))
			goto error_tgt_fput;
	}

	/*
	 * At this point it is safe to assume that the "private_data" contains
	 * our own data structure.
	 */
	ep = f.file->private_data;

	/*
	 * When we insert an epoll file descriptor, inside another epoll file
	 * descriptor, there is the change of creating closed loops, which are
	 * better be handled here, than in more critical paths. While we are
	 * checking for loops we also determine the list of files reachable
	 * and hang them on the tfile_check_list, so we can check that we
	 * haven't created too many possible wakeup paths.
	 *
	 * We do not need to take the global 'epumutex' on EPOLL_CTL_ADD when
	 * the epoll file descriptor is attaching directly to a wakeup source,
	 * unless the epoll file descriptor is nested. The purpose of taking the
	 * 'epmutex' on add is to prevent complex toplogies such as loops and
	 * deep wakeup paths from forming in parallel through multiple
	 * EPOLL_CTL_ADD operations.
	 */
	error = epoll_mutex_lock(&ep->mtx, 0, nonblock);
	if (error)
		goto error_tgt_fput;
	if (op == EPOLL_CTL_ADD) {
		if (!list_empty(&f.file->f_ep_links) ||
						is_file_epoll(tf.file)) {
			mutex_unlock(&ep->mtx);
			error = epoll_mutex_lock(&epmutex, 0, nonblock);
			if (error)
				goto error_tgt_fput;
			full_check = 1;
			if (is_file_epoll(tf.file)) {
				error = -ELOOP;
				if (ep_loop_check(ep, tf.file) != 0) {
					clear_tfile_check_list();
					goto error_tgt_fput;
				}
			} else {
				get_file(tf.file);
				list_add(&tf.file->f_tfile_llink,
							&tfile_check_list);
			}
			error = epoll_mutex_lock(&ep->mtx, 0, nonblock);
			if (error) {
out_del:
				list_del(&tf.file->f_tfile_llink);
				if (!is_file_epoll(tf.file))
					fput(tf.file);
				goto error_tgt_fput;
			}
			if (is_file_epoll(tf.file)) {
				tep = tf.file->private_data;
				error = epoll_mutex_lock(&tep->mtx, 1, nonblock);
				if (error) {
					mutex_unlock(&ep->mtx);
					goto out_del;
				}
			}
		}
	}

	/*
	 * Try to lookup the file inside our RB tree, Since we grabbed "mtx"
	 * above, we can be sure to be able to use the item looked up by
	 * ep_find() till we release the mutex.
	 */
	epi = ep_find(ep, tf.file, fd);

	error = -EINVAL;
	switch (op) {
	case EPOLL_CTL_ADD:
		if (!epi) {
			epds->events |= EPOLLERR | EPOLLHUP;
			error = ep_insert(ep, epds, tf.file, fd, full_check);
		} else
			error = -EEXIST;
		if (full_check)
			clear_tfile_check_list();
		break;
	case EPOLL_CTL_DEL:
		if (epi)
			error = ep_remove(ep, epi);
		else
			error = -ENOENT;
		break;
	case EPOLL_CTL_MOD:
		if (epi) {
			if (!(epi->event.events & EPOLLEXCLUSIVE)) {
				epds->events |= EPOLLERR | EPOLLHUP;
				error = ep_modify(ep, epi, epds);
			}
		} else
			error = -ENOENT;
		break;
	}
	if (tep != NULL)
		mutex_unlock(&tep->mtx);
	mutex_unlock(&ep->mtx);

error_tgt_fput:
	if (full_check)
		mutex_unlock(&epmutex);

	fdput(tf);
error_fput:
	fdput(f);
error_return:

	return error;
}

do_epoll_ctl(): clean the failure exits up a bit

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

#define EP_PRIVATE_BITS (EPOLLWAKEUP | EPOLLONESHOT | EPOLLET | EPOLLEXCLUSIVE)

#define EPOLLEXCLUSIVE_OK_BITS (EPOLLINOUT_BITS | EPOLLERR | EPOLLHUP | \
				EPOLLWAKEUP | EPOLLET | EPOLLEXCLUSIVE)

#define EP_MAX_EVENTS (INT_MAX / sizeof(struct epoll_event))

#define EP_ITEM_COST (sizeof(struct epitem) + sizeof(struct eppoll_entry))

struct epoll_filefd {
	struct file *file;
	int fd;
} __packed;

struct nested_call_node {
	struct list_head llink;
	void *cookie;
	void *ctx;
}

struct nested_calls {
	struct list_head tasks_call_list;
	spinlock_t lock;
}

struct epitem {
	union {
		/* RB tree node links this structure to the eventpoll RB tree */
		struct rb_node rbn;
		/* Used to free the struct epitem */
		struct rcu_head rcu;
	};

	/* List header used to link this structure to the eventpoll ready list */
	struct list_head rdllink;

	/*
	 * Works together "struct eventpoll"->ovflist in keeping the
	 * single linked chain of items.
	 */
	struct epitem *next;

	/* The file descriptor information this item refers to */
	struct epoll_filefd ffd;

	/* Number of active wait queue attached to poll operations */
	int nwait;

	/* List containing poll wait queues */
	struct list_head pwqlist;

	/* The "container" of this item */
	struct eventpoll *ep;

	/* List header used to link this item to the "struct file" items list */
	struct list_head fllink;

	/* wakeup_source used when EPOLLWAKEUP is set */
	struct wakeup_source __rcu *ws;

	/* The structure that describe the interested events and the source fd */
	struct epoll_event event;
}

struct eventpoll {
	/*
	 * This mutex is used to ensure that files are not removed
	 * while epoll is using them. This is held during the event
	 * collection loop, the file cleanup path, the epoll file exit
	 * code and the ctl operations.
	 */
	struct mutex mtx;

	/* Wait queue used by sys_epoll_wait() */
	wait_queue_head_t wq;

	/* Wait queue used by file->poll() */
	wait_queue_head_t poll_wait;

	/* List of ready file descriptors */
	struct list_head rdllist;

	/* Lock which protects rdllist and ovflist */
	rwlock_t lock;

	/* RB tree root used to store monitored fd structs */
	struct rb_root_cached rbr;

	/*
	 * This is a single linked list that chains all the "struct epitem" that
	 * happened while transferring ready events to userspace w/out
	 * holding ->lock.
	 */
	struct epitem *ovflist;

	/* wakeup_source used when ep_scan_ready_list is running */
	struct wakeup_source *ws;

	/* The user that created the eventpoll descriptor */
	struct user_struct *user;

	struct file *file;

	/* used to optimize loop detection check */
	struct list_head visited_list_link;
	int visited;

#ifdef CONFIG_NET_RX_BUSY_POLL
	/* used to track busy poll napi_id */
	unsigned int napi_id;
#endif

#ifdef CONFIG_DEBUG_LOCK_ALLOC
	/* tracks wakeup nests for lockdep validation */
	u8 nests;
#endif
}


read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
                   struct unres_schema *unres)
{
    struct ly_ctx *ctx = module->ctx;
    struct lyxml_elem *sub, *next, root;
    struct lys_node *node = NULL;
    struct lys_node *retval;
    struct lys_node_container *cont;
    const char *value;
    void *reallocated;
    int r;
    int c_tpdf = 0, c_must = 0, c_ftrs = 0, c_ext = 0;

    /* init */
    memset(&root, 0, sizeof root);

    cont = calloc(1, sizeof *cont);
    LY_CHECK_ERR_RETURN(!cont, LOGMEM(ctx), NULL);

    cont->nodetype = LYS_CONTAINER;
    cont->prev = (struct lys_node *)cont;
    retval = (struct lys_node *)cont;

    if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
            OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
                (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
            unres)) {
        goto error;
    }

    LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);

    /* insert the node into the schema tree */
    if (lys_node_addchild(parent, lys_main_module(module), retval, options)) {
        goto error;
    }

    /* process container's specific children */
    LY_TREE_FOR_SAFE(yin->child, next, sub) {
        if (strcmp(sub->ns->value, LY_NSYIN)) {
            /* extension */
            YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ext, retval->ext_size, "extensions", "container", error);
            c_ext++;
        } else if (!strcmp(sub->name, "presence")) {
            if (cont->presence) {
                LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
                goto error;
            }
            GETVAL(ctx, value, sub, "value");
            cont->presence = lydict_insert(ctx, value, strlen(value));

            if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
                goto error;
            }
            lyxml_free(ctx, sub);
        } else if (!strcmp(sub->name, "when")) {
            if (cont->when) {
                LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
                goto error;
            }

            cont->when = read_yin_when(module, sub, unres);
            if (!cont->when) {
                lyxml_free(ctx, sub);
                goto error;
            }
            lyxml_free(ctx, sub);

            /* data statements */
        } else if (!strcmp(sub->name, "container") ||
                !strcmp(sub->name, "leaf-list") ||
                !strcmp(sub->name, "leaf") ||
                !strcmp(sub->name, "list") ||
                !strcmp(sub->name, "choice") ||
                !strcmp(sub->name, "uses") ||
                !strcmp(sub->name, "grouping") ||
                !strcmp(sub->name, "anyxml") ||
                !strcmp(sub->name, "anydata") ||
                !strcmp(sub->name, "action") ||
                !strcmp(sub->name, "notification")) {
            lyxml_unlink_elem(ctx, sub, 2);
            lyxml_add_child(ctx, &root, sub);

            /* array counters */
        } else if (!strcmp(sub->name, "typedef")) {
            YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_tpdf, cont->tpdf_size, "typedefs", "container", error);
            c_tpdf++;
        } else if (!strcmp(sub->name, "must")) {
            YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_must, cont->must_size, "musts", "container", error);
            c_must++;
        } else if (!strcmp(sub->name, "if-feature")) {
            YIN_CHECK_ARRAY_OVERFLOW_GOTO(ctx, c_ftrs, retval->iffeature_size, "if-features", "container", error);
            c_ftrs++;
        } else {
            LOGVAL(ctx, LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
            goto error;
        }
    }

    /* middle part - process nodes with cardinality of 0..n except the data nodes */
    if (c_tpdf) {
        cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
        LY_CHECK_ERR_GOTO(!cont->tpdf, LOGMEM(ctx), error);
    }
    if (c_must) {
        cont->must = calloc(c_must, sizeof *cont->must);
        LY_CHECK_ERR_GOTO(!cont->must, LOGMEM(ctx), error);
    }
    if (c_ftrs) {
        cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
        LY_CHECK_ERR_GOTO(!cont->iffeature, LOGMEM(ctx), error);
    }
    if (c_ext) {
        /* some extensions may be already present from the substatements */
        reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
        LY_CHECK_ERR_GOTO(!reallocated, LOGMEM(ctx), error);
        retval->ext = reallocated;

        /* init memory */
        memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
    }

    LY_TREE_FOR_SAFE(yin->child, next, sub) {
        if (strcmp(sub->ns->value, LY_NSYIN)) {
            /* extension */
            r = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, &retval->ext_size, unres);
            if (r) {
                goto error;
            }
        } else if (!strcmp(sub->name, "typedef")) {
            r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
            cont->tpdf_size++;
            if (r) {
                goto error;
            }
        } else if (!strcmp(sub->name, "must")) {
            r = fill_yin_must(module, sub, &cont->must[cont->must_size], unres);
            cont->must_size++;
            if (r) {
                goto error;
            }
        } else if (!strcmp(sub->name, "if-feature")) {
            r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
            cont->iffeature_size++;
            if (r) {
                goto error;
            }
        }
    }

    lyp_reduce_ext_list(&retval->ext, retval->ext_size, c_ext + retval->ext_size);

    /* last part - process data nodes */
    LY_TREE_FOR_SAFE(root.child, next, sub) {
        if (!strcmp(sub->name, "container")) {
            node = read_yin_container(module, retval, sub, options, unres);
        } else if (!strcmp(sub->name, "leaf-list")) {
            node = read_yin_leaflist(module, retval, sub, options, unres);
        } else if (!strcmp(sub->name, "leaf")) {
            node = read_yin_leaf(module, retval, sub, options, unres);
        } else if (!strcmp(sub->name, "list")) {
            node = read_yin_list(module, retval, sub, options, unres);
        } else if (!strcmp(sub->name, "choice")) {
            node = read_yin_choice(module, retval, sub, options, unres);
        } else if (!strcmp(sub->name, "uses")) {
            node = read_yin_uses(module, retval, sub, options, unres);
        } else if (!strcmp(sub->name, "grouping")) {
            node = read_yin_grouping(module, retval, sub, options, unres);
        } else if (!strcmp(sub->name, "anyxml")) {
            node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
        } else if (!strcmp(sub->name, "anydata")) {
            node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
        } else if (!strcmp(sub->name, "action")) {
            node = read_yin_rpc_action(module, retval, sub, options, unres);
        } else if (!strcmp(sub->name, "notification")) {
            node = read_yin_notif(module, retval, sub, options, unres);
        }
        if (!node) {
            goto error;
        }

        lyxml_free(ctx, sub);
    }

    /* check XPath dependencies */
    if (!(ctx->models.flags & LY_CTX_TRUSTED) && (cont->when || cont->must)) {
        if (options & LYS_PARSE_OPT_INGRP) {
            if (lyxp_node_check_syntax(retval)) {
                goto error;
            }
        } else {
            if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
                goto error;
            }
        }
    }

    for (r = 0; r < retval->ext_size; ++r) {
        /* set flag, which represent LYEXT_OPT_VALID */
        if (retval->ext[r]->flags & LYEXT_OPT_VALID) {
            retval->flags |= LYS_VALID_EXT;
            if (retval->ext[r]->flags & LYEXT_OPT_VALID_SUBTREE) {
                retval->flags |= LYS_VALID_EXT_SUBTREE;
                break;
            }
        }
    }

    return retval;

error:
    lys_node_free(ctx, retval, NULL, 0);
    while (root.child) {
        lyxml_free(ctx, root.child);
    }
    return NULL;
}

yin parser BUGFIX invalid memory access

... in case there were some unresolved
extensions.
Fixes #1454
Fixes #1455


rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
{
    rb_encoding *enc;
    VALUE w;
    long width, len, flen = 1, fclen = 1;
    VALUE res;
    char *p;
    const char *f = " ";
    long n, llen, rlen;
    volatile VALUE pad;
    int singlebyte = 1, cr;

    rb_scan_args(argc, argv, "11", &w, &pad);
    enc = STR_ENC_GET(str);
    width = NUM2LONG(w);
    if (argc == 2) {
	StringValue(pad);
	enc = rb_enc_check(str, pad);
	f = RSTRING_PTR(pad);
	flen = RSTRING_LEN(pad);
	fclen = str_strlen(pad, enc);
	singlebyte = single_byte_optimizable(pad);
	if (flen == 0 || fclen == 0) {
	    rb_raise(rb_eArgError, "zero width padding");
	}
    }
    len = str_strlen(str, enc);
    if (width < 0 || len >= width) return rb_str_dup(str);
    n = width - len;
    llen = (jflag == 'l') ? 0 : ((jflag == 'r') ? n : n/2);
    rlen = n - llen;
    cr = ENC_CODERANGE(str);
    res = rb_str_new5(str, 0, RSTRING_LEN(str)+n*flen/fclen+2);
    p = RSTRING_PTR(res);
    while (llen) {
	if (flen <= 1) {
	    *p++ = *f;
	    llen--;
	}
	else if (llen > fclen) {
	    memcpy(p,f,flen);
	    p += flen;
	    llen -= fclen;
	}
	else {
	    char *fp = str_nth(f, f+flen, llen, enc, singlebyte);
	    n = fp - f;
	    memcpy(p,f,n);
	    p+=n;
	    break;
	}
    }
    memcpy(p, RSTRING_PTR(str), RSTRING_LEN(str));
    p+=RSTRING_LEN(str);
    while (rlen) {
	if (flen <= 1) {
	    *p++ = *f;
	    rlen--;
	}
	else if (rlen > fclen) {
	    memcpy(p,f,flen);
	    p += flen;
	    rlen -= fclen;
	}
	else {
	    char *fp = str_nth(f, f+flen, rlen, enc, singlebyte);
	    n = fp - f;
	    memcpy(p,f,n);
	    p+=n;
	    break;
	}
    }
    *p = '\0';
    STR_SET_LEN(res, p-RSTRING_PTR(res));
    OBJ_INFECT(res, str);
    if (!NIL_P(pad)) OBJ_INFECT(res, pad);
    rb_enc_associate(res, enc);
    if (argc == 2)
	cr = ENC_CODERANGE_AND(cr, ENC_CODERANGE(pad));
    if (cr != ENC_CODERANGE_BROKEN)
	ENC_CODERANGE_SET(res, cr);
    return res;
}

* string.c (rb_str_justify): CVE-2009-4124.
  Fixes a bug reported by
  Emmanouel Kellinis <Emmanouel.Kellinis AT kpmg.co.uk>, KPMG London;
  Patch by nobu.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@26038 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

#define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))

VALUE rb_cString;

VALUE rb_cSymbol;

#define STR_UNSET_NOCAPA(s) do {\
    if (FL_TEST(s,STR_NOEMBED)) FL_UNSET(s,(ELTS_SHARED|STR_ASSOC));\
} while (0)

#define STR_SET_NOEMBED(str) do {\
    FL_SET(str, STR_NOEMBED);\
    STR_SET_EMBED_LEN(str, 0);\
} while (0)

#define STR_SET_EMBED(str) FL_UNSET(str, STR_NOEMBED)

#define STR_EMBED_P(str) (!FL_TEST(str, STR_NOEMBED))

#define STR_SET_EMBED_LEN(str, n) do { \
    long tmp_n = (n);\
    RBASIC(str)->flags &= ~RSTRING_EMBED_LEN_MASK;\
    RBASIC(str)->flags |= (tmp_n) << RSTRING_EMBED_LEN_SHIFT;\
} while (0)

#define STR_SET_LEN(str, n) do { \
    if (STR_EMBED_P(str)) {\
	STR_SET_EMBED_LEN(str, n);\
    }\
    else {\
	RSTRING(str)->as.heap.len = (n);\
    }\
} while (0)

#define STR_DEC_LEN(str) do {\
    if (STR_EMBED_P(str)) {\
	long n = RSTRING_LEN(str);\
	n--;\
	STR_SET_EMBED_LEN(str, n);\
    }\
    else {\
	RSTRING(str)->as.heap.len--;\
    }\
} while (0)

#define RESIZE_CAPA(str,capacity) do {\
    if (STR_EMBED_P(str)) {\
	if ((capacity) > RSTRING_EMBED_LEN_MAX) {\
	    char *tmp = ALLOC_N(char, capacity+1);\
	    memcpy(tmp, RSTRING_PTR(str), RSTRING_LEN(str));\
	    RSTRING(str)->as.heap.ptr = tmp;\
	    RSTRING(str)->as.heap.len = RSTRING_LEN(str);\
            STR_SET_NOEMBED(str);\
	    RSTRING(str)->as.heap.aux.capa = (capacity);\
	}\
    }\
    else {\
	REALLOC_N(RSTRING(str)->as.heap.ptr, char, (capacity)+1);\
	if (!STR_NOCAPA_P(str))\
	    RSTRING(str)->as.heap.aux.capa = (capacity);\
    }\
} while (0)

#define is_ascii_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT)

#define is_broken_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN)

#define STR_ENC_GET(str) rb_enc_from_index(ENCODING_GET(str))

VALUE rb_fs;

RUBY_ALIAS_FUNCTION(rb_str_new2(const char *ptr), rb_str_new_cstr, (ptr))
#define rb_str_new2 rb_str_new_cstr

VALUE
rb_usascii_str_new_cstr(const char *ptr)
{
    VALUE str = rb_str_new2(ptr);

RUBY_ALIAS_FUNCTION(rb_tainted_str_new2(const char *ptr), rb_tainted_str_new_cstr, (ptr))
#define rb_tainted_str_new2 rb_tainted_str_new_cstr

VALUE
rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts)
{
    rb_econv_t *ec;

long len;

VALUE newstr;

const unsigned char *sp;

unsigned char *dp;

RUBY_ALIAS_FUNCTION(rb_str_new3(VALUE str), rb_str_new_shared, (str))
#define rb_str_new3 rb_str_new_shared

static VALUE
str_new4(VALUE klass, VALUE str)
{
    VALUE str2;


static int cmd_handle_untagged (IMAP_DATA* idata)
{
  char* s;
  char* pn;
  unsigned int count;

  s = imap_next_word (idata->buf);
  pn = imap_next_word (s);

  if ((idata->state >= IMAP_SELECTED) && isdigit ((unsigned char) *s))
  {
    pn = s;
    s = imap_next_word (s);

    /* EXISTS and EXPUNGE are always related to the SELECTED mailbox for the
     * connection, so update that one.
     */
    if (ascii_strncasecmp ("EXISTS", s, 6) == 0)
    {
      dprint (2, (debugfile, "Handling EXISTS\n"));

      /* new mail arrived */
      mutt_atoui (pn, &count);

      if ( !(idata->reopen & IMAP_EXPUNGE_PENDING) &&
	   count < idata->max_msn)
      {
        /* Notes 6.0.3 has a tendency to report fewer messages exist than
         * it should. */
	dprint (1, (debugfile, "Message count is out of sync"));
	return 0;
      }
      /* at least the InterChange server sends EXISTS messages freely,
       * even when there is no new mail */
      else if (count == idata->max_msn)
	dprint (3, (debugfile,
          "cmd_handle_untagged: superfluous EXISTS message.\n"));
      else
      {
	if (!(idata->reopen & IMAP_EXPUNGE_PENDING))
        {
          dprint (2, (debugfile,
            "cmd_handle_untagged: New mail in %s - %d messages total.\n",
            idata->mailbox, count));
	  idata->reopen |= IMAP_NEWMAIL_PENDING;
        }
	idata->newMailCount = count;
      }
    }
    /* pn vs. s: need initial seqno */
    else if (ascii_strncasecmp ("EXPUNGE", s, 7) == 0)
      cmd_parse_expunge (idata, pn);
    else if (ascii_strncasecmp ("FETCH", s, 5) == 0)
      cmd_parse_fetch (idata, pn);
  }
  else if (ascii_strncasecmp ("CAPABILITY", s, 10) == 0)
    cmd_parse_capability (idata, s);
  else if (!ascii_strncasecmp ("OK [CAPABILITY", s, 14))
    cmd_parse_capability (idata, pn);
  else if (!ascii_strncasecmp ("OK [CAPABILITY", pn, 14))
    cmd_parse_capability (idata, imap_next_word (pn));
  else if (ascii_strncasecmp ("LIST", s, 4) == 0)
    cmd_parse_list (idata, s);
  else if (ascii_strncasecmp ("LSUB", s, 4) == 0)
    cmd_parse_lsub (idata, s);
  else if (ascii_strncasecmp ("MYRIGHTS", s, 8) == 0)
    cmd_parse_myrights (idata, s);
  else if (ascii_strncasecmp ("SEARCH", s, 6) == 0)
    cmd_parse_search (idata, s);
  else if (ascii_strncasecmp ("STATUS", s, 6) == 0)
    cmd_parse_status (idata, s);
  else if (ascii_strncasecmp ("ENABLED", s, 7) == 0)
    cmd_parse_enabled (idata, s);
  else if (ascii_strncasecmp ("BYE", s, 3) == 0)
  {
    dprint (2, (debugfile, "Handling BYE\n"));

    /* check if we're logging out */
    if (idata->status == IMAP_BYE)
      return 0;

    /* server shut down our connection */
    s += 3;
    SKIPWS (s);
    mutt_error ("%s", s);
    mutt_sleep (2);
    cmd_handle_fatal (idata);

    return -1;
  }
  else if (option (OPTIMAPSERVERNOISE) && (ascii_strncasecmp ("NO", s, 2) == 0))
  {
    dprint (2, (debugfile, "Handling untagged NO\n"));

    /* Display the warning message from the server */
    mutt_error ("%s", s+3);
    mutt_sleep (2);
  }

  return 0;
}

Handle NO response without message properly

static int cmd_start (IMAP_DATA* idata, const char* cmdstr, int flags);

static int cmd_queue_full (IMAP_DATA* idata);

static int cmd_queue (IMAP_DATA* idata, const char* cmdstr, int flags);

static IMAP_COMMAND* cmd_new (IMAP_DATA* idata);

static int cmd_status (const char *s);

static void cmd_handle_fatal (IMAP_DATA* idata);

static int cmd_handle_untagged (IMAP_DATA* idata);

static void cmd_parse_capability (IMAP_DATA* idata, char* s);

static void cmd_parse_expunge (IMAP_DATA* idata, const char* s);

static void cmd_parse_list (IMAP_DATA* idata, char* s);

static void cmd_parse_lsub (IMAP_DATA* idata, char* s);

static void cmd_parse_fetch (IMAP_DATA* idata, char* s);

static void cmd_parse_myrights (IMAP_DATA* idata, const char* s);

static void cmd_parse_search (IMAP_DATA* idata, const char* s);

static void cmd_parse_status (IMAP_DATA* idata, char* s);

static void cmd_parse_enabled (IMAP_DATA* idata, const char* s);

static const char * const Capabilities[] = {
  "IMAP4",
  "IMAP4rev1",
  "STATUS",
  "ACL",
  "NAMESPACE",
  "AUTH=CRAM-MD5",
  "AUTH=GSSAPI",
  "AUTH=ANONYMOUS",
  "STARTTLS",
  "LOGINDISABLED",
  "IDLE",
  "SASL-IR",
  "ENABLE",

  NULL
};