get_lisp_indent(void)
{
    pos_T	*pos, realpos, paren;
    int		amount;
    char_u	*that;
    colnr_T	col;
    colnr_T	firsttry;
    int		parencount, quotecount;
    int		vi_lisp;

    // Set vi_lisp to use the vi-compatible method
    vi_lisp = (vim_strchr(p_cpo, CPO_LISP) != NULL);

    realpos = curwin->w_cursor;
    curwin->w_cursor.col = 0;

    if ((pos = findmatch(NULL, '(')) == NULL)
	pos = findmatch(NULL, '[');
    else
    {
	paren = *pos;
	pos = findmatch(NULL, '[');
	if (pos == NULL || LT_POSP(pos, &paren))
	    pos = &paren;
    }
    if (pos != NULL)
    {
	// Extra trick: Take the indent of the first previous non-white
	// line that is at the same () level.
	amount = -1;
	parencount = 0;

	while (--curwin->w_cursor.lnum >= pos->lnum)
	{
	    if (linewhite(curwin->w_cursor.lnum))
		continue;
	    for (that = ml_get_curline(); *that != NUL; ++that)
	    {
		if (*that == ';')
		{
		    while (*(that + 1) != NUL)
			++that;
		    continue;
		}
		if (*that == '\\')
		{
		    if (*(that + 1) != NUL)
			++that;
		    continue;
		}
		if (*that == '"' && *(that + 1) != NUL)
		{
		    while (*++that && *that != '"')
		    {
			// skipping escaped characters in the string
			if (*that == '\\')
			{
			    if (*++that == NUL)
				break;
			    if (that[1] == NUL)
			    {
				++that;
				break;
			    }
			}
		    }
		}
		if (*that == '(' || *that == '[')
		    ++parencount;
		else if (*that == ')' || *that == ']')
		    --parencount;
	    }
	    if (parencount == 0)
	    {
		amount = get_indent();
		break;
	    }
	}

	if (amount == -1)
	{
	    curwin->w_cursor.lnum = pos->lnum;
	    curwin->w_cursor.col = pos->col;
	    col = pos->col;

	    that = ml_get_curline();

	    if (vi_lisp && get_indent() == 0)
		amount = 2;
	    else
	    {
		char_u *line = that;

		amount = 0;
		while (*that && col)
		{
		    amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount);
		    col--;
		}

		// Some keywords require "body" indenting rules (the
		// non-standard-lisp ones are Scheme special forms):
		//
		// (let ((a 1))    instead    (let ((a 1))
		//   (...))	      of	   (...))

		if (!vi_lisp && (*that == '(' || *that == '[')
						      && lisp_match(that + 1))
		    amount += 2;
		else
		{
		    that++;
		    amount++;
		    firsttry = amount;

		    while (VIM_ISWHITE(*that))
		    {
			amount += lbr_chartabsize(line, that, (colnr_T)amount);
			++that;
		    }

		    if (*that && *that != ';') // not a comment line
		    {
			// test *that != '(' to accommodate first let/do
			// argument if it is more than one line
			if (!vi_lisp && *that != '(' && *that != '[')
			    firsttry++;

			parencount = 0;
			quotecount = 0;

			if (vi_lisp
				|| (*that != '"'
				    && *that != '\''
				    && *that != '#'
				    && (*that < '0' || *that > '9')))
			{
			    while (*that
				    && (!VIM_ISWHITE(*that)
					|| quotecount
					|| parencount)
				    && (!((*that == '(' || *that == '[')
					    && !quotecount
					    && !parencount
					    && vi_lisp)))
			    {
				if (*that == '"')
				    quotecount = !quotecount;
				if ((*that == '(' || *that == '[')
							       && !quotecount)
				    ++parencount;
				if ((*that == ')' || *that == ']')
							       && !quotecount)
				    --parencount;
				if (*that == '\\' && *(that+1) != NUL)
				    amount += lbr_chartabsize_adv(
						line, &that, (colnr_T)amount);
				amount += lbr_chartabsize_adv(
						line, &that, (colnr_T)amount);
			    }
			}
			while (VIM_ISWHITE(*that))
			{
			    amount += lbr_chartabsize(
						 line, that, (colnr_T)amount);
			    that++;
			}
			if (!*that || *that == ';')
			    amount = firsttry;
		    }
		}
	    }
	}
    }
    else
	amount = 0;	// no matching '(' or '[' found, use zero indent

    curwin->w_cursor = realpos;

    return amount;
}

patch 8.2.5122: lisp indenting my run over the end of the line

Problem:    Lisp indenting my run over the end of the line.
Solution:   Check for NUL earlier.


ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
{
    linenr_T	count;
    char_u	*p;

    count = line2 - line1 + 1;
    if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0)
    {
	curbuf->b_op_start.lnum = n + 1;
	curbuf->b_op_end.lnum = n + count;
	curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
    }

    /*
     * there are three situations:
     * 1. destination is above line1
     * 2. destination is between line1 and line2
     * 3. destination is below line2
     *
     * n = destination (when starting)
     * curwin->w_cursor.lnum = destination (while copying)
     * line1 = start of source (while copying)
     * line2 = end of source (while copying)
     */
    if (u_save(n, n + 1) == FAIL)
	return;

    curwin->w_cursor.lnum = n;
    while (line1 <= line2)
    {
	// need to use vim_strsave() because the line will be unlocked within
	// ml_append()
	p = vim_strsave(ml_get(line1));
	if (p != NULL)
	{
	    ml_append(curwin->w_cursor.lnum, p, (colnr_T)0, FALSE);
	    vim_free(p);
	}
	// situation 2: skip already copied lines
	if (line1 == n)
	    line1 = curwin->w_cursor.lnum;
	++line1;
	if (curwin->w_cursor.lnum < line1)
	    ++line1;
	if (curwin->w_cursor.lnum < line2)
	    ++line2;
	++curwin->w_cursor.lnum;
    }

    appended_lines_mark(n, count);

    msgmore((long)count);
}

patch 8.2.4215: illegal memory access when copying lines in Visual mode

Problem:    Illegal memory access when copying lines in Visual mode.
Solution:   Adjust the Visual position after copying lines.


int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
		 struct xfrm_migrate *m, int num_migrate,
		 struct xfrm_kmaddress *k, struct net *net,
		 struct xfrm_encap_tmpl *encap)
{
	int i, err, nx_cur = 0, nx_new = 0;
	struct xfrm_policy *pol = NULL;
	struct xfrm_state *x, *xc;
	struct xfrm_state *x_cur[XFRM_MAX_DEPTH];
	struct xfrm_state *x_new[XFRM_MAX_DEPTH];
	struct xfrm_migrate *mp;

	if ((err = xfrm_migrate_check(m, num_migrate)) < 0)
		goto out;

	/* Stage 1 - find policy */
	if ((pol = xfrm_migrate_policy_find(sel, dir, type, net)) == NULL) {
		err = -ENOENT;
		goto out;
	}

	/* Stage 2 - find and update state(s) */
	for (i = 0, mp = m; i < num_migrate; i++, mp++) {
		if ((x = xfrm_migrate_state_find(mp, net))) {
			x_cur[nx_cur] = x;
			nx_cur++;
			xc = xfrm_state_migrate(x, mp, encap);
			if (xc) {
				x_new[nx_new] = xc;
				nx_new++;
			} else {
				err = -ENODATA;
				goto restore_state;
			}
		}
	}

	/* Stage 3 - update policy */
	if ((err = xfrm_policy_migrate(pol, m, num_migrate)) < 0)
		goto restore_state;

	/* Stage 4 - delete old state(s) */
	if (nx_cur) {
		xfrm_states_put(x_cur, nx_cur);
		xfrm_states_delete(x_cur, nx_cur);
	}

	/* Stage 5 - announce */
	km_migrate(sel, dir, type, m, num_migrate, k, encap);

	xfrm_pol_put(pol);

	return 0;
out:
	return err;

restore_state:
	if (pol)
		xfrm_pol_put(pol);
	if (nx_cur)
		xfrm_states_put(x_cur, nx_cur);
	if (nx_new)
		xfrm_states_delete(x_new, nx_new);

	return err;
}

xfrm: policy: check policy direction value

The 'dir' parameter in xfrm_migrate() is a user-controlled byte which is used
as an array index. This can lead to an out-of-bound access, kernel lockup and
DoS. Add a check for the 'dir' value.

This fixes CVE-2017-11600.

References: https://bugzilla.redhat.com/show_bug.cgi?id=1474928
Fixes: 80c9abaabf42 ("[XFRM]: Extension for dynamic update of endpoint address(es)")
Cc: <stable@vger.kernel.org> # v2.6.21-rc1
Reported-by: "bo Zhang" <zhangbo5891001@gmail.com>
Signed-off-by: Vladis Dronov <vdronov@redhat.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>


mp_sint32 LoaderS3M::load(XMFileBase& f, XModule* module)
{
	module->cleanUp();

	// this will make code much easier to read
	TXMHeader*		header = &module->header;
	TXMInstrument*	instr  = module->instr;
	TXMSample*		smp	   = module->smp;
	TXMPattern*		phead  = module->phead;

	// we're already out of memory here
	if (!phead || !instr || !smp)
		return MP_OUT_OF_MEMORY;

	f.read(&header->name,1,28);
	header->whythis1a = f.readByte();

	if (f.readByte() != 16)
		return MP_LOADER_FAILED;	// no ST3 module

	f.readByte(); // skip something
	f.readByte(); // skip something

	header->ordnum = f.readWord(); // number of positions in order list (songlength)

	mp_ubyte* orders = new mp_ubyte[header->ordnum];
	if (orders == NULL)
		return MP_OUT_OF_MEMORY;

	header->insnum = f.readWord(); // number of instruments
	header->patnum = f.readWord(); // number of patterns

	mp_sint32 flags = f.readWord(); // st3 flags

	mp_sint32 Cvt = f.readWord();

	header->flags = XModule::MODULE_ST3NEWINSTRUMENT | XModule::MODULE_ST3DUALCOMMANDS;

	if (Cvt == 0x1300 || (flags & 64))
		header->flags |= module->MODULE_OLDS3MVOLSLIDES;

	header->flags |= module->MODULE_ST3NOTECUT;

	/*mp_uword Ffi = */f.readWord();

	f.read(header->sig,1,4);

	header->mainvol = module->vol64to255(f.readByte()); // initial main volume

	header->tempo = f.readByte(); // tempo

	header->speed = f.readByte(); // speed

	f.readByte(); // global volume? skipped...

	f.readByte(); // ignore GUS click removal

	/*mp_ubyte dp = */f.readByte();

	f.readDword();	// skip something
	f.readDword();	// skip something
	f.readWord();	// skip some more...

	mp_ubyte channelSettings[32];
	f.read(channelSettings,1,32);

	mp_sint32 numChannels = 0;

	for (numChannels = 0; numChannels < 32; numChannels++)
		if (channelSettings[numChannels] == 255)
			break;

	header->channum = numChannels; // number of channels

	f.read(orders,1,header->ordnum);

	mp_sint32 j = 0, i = 0;
	for (i = 0; i < header->ordnum; i++)
	{
		if (orders[i] == 255)
			break;

		header->ord[j++] = orders[i];
	}

	header->ordnum = j; // final songlength

	delete[] orders;

	mp_uword* insParaPtrs = new mp_uword[header->insnum];

	if (insParaPtrs == NULL)
		return MP_OUT_OF_MEMORY;

	f.readWords(insParaPtrs,header->insnum);

	mp_uword* patParaPtrs = new mp_uword[header->patnum];

	if (patParaPtrs == NULL)
	{
		delete[] insParaPtrs;
		return MP_OUT_OF_MEMORY;
	}

	f.readWords(patParaPtrs,header->patnum);

	//for (i = 0; i < header->insnum; i++)
	//{
	//	printf("%x\n",insParaPtrs[i]*16);
	//}

	//////////////////////
	// read instruments //
	//////////////////////
	mp_uint32* samplePtrs = new mp_uint32[header->insnum];
	if (samplePtrs == NULL)
	{
		delete[] insParaPtrs;
		delete[] patParaPtrs;
		return MP_OUT_OF_MEMORY;
	}

	memset(samplePtrs,0,sizeof(mp_uint32)*header->insnum);

	mp_sint32 s = 0;
	for (i = 0; i < header->insnum; i++)
	{
		mp_uint32 insOffs = insParaPtrs[i]*16;

		if (insOffs)
		{
			f.seekWithBaseOffset(insOffs);

			// We can only read that if it's a sample
			mp_ubyte type = f.readByte();

			if (type == 1)
			{
				f.read(smp[s].name,1,12);	// read dos filename

				mp_ubyte bOffs = f.readByte();
				mp_uword wOffs = f.readWord();

				// stupid fileoffsets
				samplePtrs[i] = (((mp_uint32)bOffs<<16)+(mp_uint32)wOffs)*16;

				smp[s].flags = 1;
				smp[s].pan = 0x80;

				smp[s].samplen = f.readDword();
				smp[s].loopstart = f.readDword();
				mp_sint32 looplen = ((mp_sint32)f.readDword() - (mp_sint32)smp[s].loopstart);
				if (looplen < 0)
					looplen = 0;
				smp[s].looplen = looplen;

				smp[s].vol = module->vol64to255(f.readByte());

				f.readByte(); // skip something

				smp[s].res = f.readByte() == 0x04 ? 0xAD : 0; // packing

				mp_ubyte flags = f.readByte();

				// looping
				if (flags & 1)
				{
					smp[s].type = 1;
				}

				// 16 bit sample
				if (flags & 4)
				{
					smp[s].type |= 16;
					smp[s].samplen >>= 1;
					smp[s].loopstart >>= 1;
					smp[s].looplen >>= 1;
				}

				mp_uint32 c4spd = f.readDword();

				XModule::convertc4spd(c4spd,&smp[s].finetune,&smp[s].relnote);

#ifdef VERBOSE
				printf("%i, %i\n",c4spd,module->getc4spd(smp[s].relnote,smp[s].finetune));
#endif

				f.readDword(); // skip something

				f.readDword(); // skip two internal words

				f.readDword(); // skip internal dword

				f.read(instr[i].name,1,28); // instrument name

				f.readDword(); // skip signature

				if (samplePtrs[i] && smp[s].samplen)
				{
					instr[i].samp=1;
					for (j=0;j<120;j++)
						instr[i].snum[j] = s;
					s++;
				}
			}
			else if (type == 0)
			{
				samplePtrs[i] = 0;

				mp_ubyte buffer[12];
				f.read(buffer,1,12);	// read dos filename

				f.readByte();
				f.readWord();

				f.readDword();
				f.readDword();
				f.readDword();
				f.readByte();
				f.readByte(); // skip something
				f.readByte(); // skip packing

				f.readByte();

				f.readDword();

				f.readDword(); // skip something

				f.readDword(); // skip two internal words

				f.readDword(); // skip internal dword

				f.read(instr[i].name,1,28); // instrument name

				f.readDword(); // skip signature
			}
			else
			{
				samplePtrs[i] = 0;
			}

		}

	}

	//////////////////////
	// read patterns	//
	//////////////////////
	mp_ubyte* pattern = new mp_ubyte[64*32*5];
	if (pattern == NULL)
	{
		delete[] insParaPtrs;
		delete[] patParaPtrs;
		delete[] samplePtrs;
		return MP_OUT_OF_MEMORY;
	}

	mp_uint32 songMaxChannels = 1;

	for (i = 0; i < header->patnum; i++)
	{
		for (j = 0; j < 32*64; j++)
		{
			pattern[j*5] = 0xFF;
			pattern[j*5+1] = 0;
			pattern[j*5+2] = 0xFF;
			pattern[j*5+3] = 0xFF;
			pattern[j*5+4] = 0;
		}

		mp_uint32 patOffs = patParaPtrs[i]*16;

		mp_uint32 maxChannels = 1;

		if (patOffs)
		{
			f.seekWithBaseOffset(patOffs);

			mp_uint32 size = f.readWord();

			if (size > 2)
			{
				size-=2;

				mp_ubyte* packed = new mp_ubyte[size+5];
				if (packed == NULL)
				{
					delete[] insParaPtrs;
					delete[] patParaPtrs;
					delete[] samplePtrs;
					delete[] pattern;
					return MP_OUT_OF_MEMORY;
				}

				memset(packed, 0, size);
				f.read(packed, 1, size);

				mp_uint32 index = 0;
				mp_uint32 row = 0;

				while (index<size)
				{

					mp_ubyte pi = safeRead(packed, index, size);

					if (pi == 0)
					{
						row++;
						// one more safety net for incorrectly saved pattern sizes
						if (row >= 64)
						{
							int i = 0;
							i++;
							i--;
							break;
						}
						continue;
					}

					mp_uint32 chn = pi&31;

					if (chn>maxChannels && (pi & (32+64+128)))
					{
						maxChannels = chn;
					}

					mp_ubyte* slot = pattern+(row*32*5)+chn*5;

					if (pi & 32)
					{
						slot[0] = safeRead(packed, index, size, 0xFF);
						slot[1] = safeRead(packed, index, size);
					}
					if (pi & 64)
					{
						slot[2] = safeRead(packed, index, size, 0xFF);
					}
					if (pi & 128)
					{
						slot[3] = safeRead(packed, index, size, 0xFF);
						slot[4] = safeRead(packed, index, size);
					}

				}

				maxChannels++;

				if (maxChannels > header->channum)
					maxChannels = header->channum;

				delete[] packed;
			}

			if (maxChannels > songMaxChannels)
				songMaxChannels = maxChannels;

		}

		convertS3MPattern(&phead[i], pattern, maxChannels, i);

	}

	if (header->channum > songMaxChannels)
		header->channum = songMaxChannels;

	delete[] pattern;
	delete[] insParaPtrs;
	delete[] patParaPtrs;

	s = 0;
	for (i = 0; i < header->insnum; i++)
	{
		mp_uint32 smpOffs = samplePtrs[i];

		if (smpOffs)
		{
			f.seekWithBaseOffset(smpOffs);

			if (!smp[s].samplen)
				continue;

			bool adpcm = (smp[s].res == 0xAD);

			mp_sint32 result = module->loadModuleSample(f, s,
										  adpcm ? XModule::ST_PACKING_ADPCM : XModule::ST_UNSIGNED,
										  adpcm ? (XModule::ST_16BIT | XModule::ST_PACKING_ADPCM) : (XModule::ST_16BIT | XModule::ST_UNSIGNED));
			if (result != MP_OK)
			{
				delete[] samplePtrs;
				return result;
			}

			if (adpcm)
				// no longer needed
				smp[s].res = 0;

			s++;

		}

	}

	delete[] samplePtrs;

	header->smpnum = s;

	strcpy(header->tracker,"Screamtracker 3");

	module->setDefaultPanning();

	module->postProcessSamples();

	return MP_OK;
}

Fix #184: Heap overflow in S3M loader


int CLASS ljpeg_start (struct jhead *jh, int info_only)
{
  int c, tag, len;
  uchar data[0x10000];
  const uchar *dp;

  memset (jh, 0, sizeof *jh);
  jh->restart = INT_MAX;
  fread (data, 2, 1, ifp);
  if (data[1] != 0xd8) return 0;
  do {
    fread (data, 2, 2, ifp);
    tag =  data[0] << 8 | data[1];
    len = (data[2] << 8 | data[3]) - 2;
    if (tag <= 0xff00) return 0;
    fread (data, 1, len, ifp);
    switch (tag) {
      case 0xffc3:
	jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3;
      case 0xffc0:
	jh->bits = data[0];
	jh->high = data[1] << 8 | data[2];
	jh->wide = data[3] << 8 | data[4];
	jh->clrs = data[5] + jh->sraw;
	if (len == 9 && !dng_version) getc(ifp);
	break;
      case 0xffc4:
	if (info_only) break;
	for (dp = data; dp < data+len && (c = *dp++) < 4; )
	  jh->free[c] = jh->huff[c] = make_decoder_ref (&dp);
	break;
      case 0xffda:
	jh->psv = data[1+data[0]*2];
	jh->bits -= data[3+data[0]*2] & 15;
	break;
      case 0xffdd:
	jh->restart = data[0] << 8 | data[1];
    }
  } while (tag != 0xffda);
  if (info_only) return 1;
  if (jh->clrs > 6 || !jh->huff[0]) return 0;
  FORC(5) if (!jh->huff[c+1]) jh->huff[c+1] = jh->huff[c];
  if (jh->sraw) {
    FORC(4)        jh->huff[2+c] = jh->huff[1];
    FORC(jh->sraw) jh->huff[1+c] = jh->huff[0];
  }
  jh->row = (ushort *) calloc (jh->wide*jh->clrs, 4);
  merror (jh->row, "ljpeg_start()");
  return zero_after_ff = 1;
}

0.16.1: fix for dcraw ljpeg_start() vulnerability


static int rsi_send_beacon(struct rsi_common *common)
{
	struct sk_buff *skb = NULL;
	u8 dword_align_bytes = 0;

	skb = dev_alloc_skb(MAX_MGMT_PKT_SIZE);
	if (!skb)
		return -ENOMEM;

	memset(skb->data, 0, MAX_MGMT_PKT_SIZE);

	dword_align_bytes = ((unsigned long)skb->data & 0x3f);
	if (dword_align_bytes)
		skb_pull(skb, (64 - dword_align_bytes));
	if (rsi_prepare_beacon(common, skb)) {
		rsi_dbg(ERR_ZONE, "Failed to prepare beacon\n");
		return -EINVAL;
	}
	skb_queue_tail(&common->tx_queue[MGMT_BEACON_Q], skb);
	rsi_set_event(&common->tx_thread.event);
	rsi_dbg(DATA_TX_ZONE, "%s: Added to beacon queue\n", __func__);

	return 0;
}

rsi: release skb if rsi_prepare_beacon fails

In rsi_send_beacon, if rsi_prepare_beacon fails the allocated skb should
be released.

Signed-off-by: Navid Emamdoost <navid.emamdoost@gmail.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>


static ptrdiff_t finderrfunc(lua_State *L)
{
  cTValue *frame = L->base-1, *bot = tvref(L->stack);
  void *cf = L->cframe;
  while (frame > bot && cf) {
    while (cframe_nres(cframe_raw(cf)) < 0) {  /* cframe without frame? */
      if (frame >= restorestack(L, -cframe_nres(cf)))
	break;
      if (cframe_errfunc(cf) >= 0)  /* Error handler not inherited (-1)? */
	return cframe_errfunc(cf);
      cf = cframe_prev(cf);  /* Else unwind cframe and continue searching. */
      if (cf == NULL)
	return 0;
    }
    switch (frame_typep(frame)) {
    case FRAME_LUA:
    case FRAME_LUAP:
      frame = frame_prevl(frame);
      break;
    case FRAME_C:
      cf = cframe_prev(cf);
      /* fallthrough */
    case FRAME_VARG:
      frame = frame_prevd(frame);
      break;
    case FRAME_CONT:
#if LJ_HASFFI
      if ((frame-1)->u32.lo == LJ_CONT_FFI_CALLBACK)
	cf = cframe_prev(cf);
#endif
      frame = frame_prevd(frame);
      break;
    case FRAME_CP:
      if (cframe_canyield(cf)) return 0;
      if (cframe_errfunc(cf) >= 0)
	return cframe_errfunc(cf);
      frame = frame_prevd(frame);
      break;
    case FRAME_PCALL:
    case FRAME_PCALLH:
      if (frame_ftsz(frame) >= (ptrdiff_t)(2*sizeof(TValue)))  /* xpcall? */
	return savestack(L, frame-1);  /* Point to xpcall's errorfunc. */
      return 0;
    default:
      lua_assert(0);
      return 0;
    }
  }
  return 0;
}

Fix frame traversal for __gc handler frames.

Reported by Changochen.


static uint64_t zynq_slcr_compute_pll(uint64_t input, uint32_t ctrl_reg)
{
    uint32_t mult = ((ctrl_reg & R_xxx_PLL_CTRL_PLL_FPDIV_MASK) >>
            R_xxx_PLL_CTRL_PLL_FPDIV_SHIFT);

    /* first, check if pll is bypassed */
    if (ctrl_reg & R_xxx_PLL_CTRL_PLL_BYPASS_FORCE_MASK) {
        return input;
    }

    /* is pll disabled ? */
    if (ctrl_reg & (R_xxx_PLL_CTRL_PLL_RESET_MASK |
                    R_xxx_PLL_CTRL_PLL_PWRDWN_MASK)) {
        return 0;
    }

    /* frequency multiplier -> period division */
    return input / mult;
}

hw/misc/zynq_slcr: Avoid #DIV/0! error

Malicious user can set the feedback divisor for the PLLs
to zero, triggering a floating-point exception (SIGFPE).

As the datasheet [*] is not clear how hardware behaves
when these bits are zeroes, use the maximum divisor
possible (128) to avoid the software FPE.

[*] Zynq-7000 TRM, UG585 (v1.12.2)
    B.28 System Level Control Registers (slcr)
    -> "Register (slcr) ARM_PLL_CTRL"
    25.10.4 PLLs
    -> "Software-Controlled PLL Update"

Fixes: 38867cb7ec9 ("hw/misc/zynq_slcr: add clock generation for uarts")
Reported-by: Gaoning Pan <pgn@zju.edu.cn>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Damien Hedde <damien.hedde@greensocs.com>
Message-id: 20201210141610.884600-1-f4bug@amsat.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>


RList *r_bin_ne_get_entrypoints(r_bin_ne_obj_t *bin) {
	if (!bin->entry_table) {
		return NULL;
	}
	RList *entries = r_list_newf (free);
	if (!entries) {
		return NULL;
	}
	RList *segments = r_bin_ne_get_segments (bin);
	if (!segments) {
		r_list_free (entries);
		return NULL;
	}
	if (bin->ne_header->csEntryPoint) {
		RBinAddr *entry = R_NEW0 (RBinAddr);
		if (!entry) {
			r_list_free (entries);
			return NULL;
		}
		entry->bits = 16;
		ut32 entry_cs = bin->ne_header->csEntryPoint;
		RBinSection *s = r_list_get_n (segments, entry_cs - 1);
		entry->paddr = bin->ne_header->ipEntryPoint + (s? s->paddr: 0);

		r_list_append (entries, entry);
	}
	int off = 0;
	size_t tableat = bin->header_offset + bin->ne_header->EntryTableOffset;
	while (off < bin->ne_header->EntryTableLength) {
		if (tableat + off >= r_buf_size (bin->buf)) {
			break;
		}
		ut8 bundle_length = *(ut8 *)(bin->entry_table + off);
		if (!bundle_length) {
			break;
		}
		off++;
		ut8 bundle_type = *(ut8 *)(bin->entry_table + off);
		off++;
		int i;
		for (i = 0; i < bundle_length; i++) {
			if (tableat + off + 4 >= r_buf_size (bin->buf)) {
				break;
			}
			RBinAddr *entry = R_NEW0 (RBinAddr);
			if (!entry) {
				r_list_free (entries);
				return NULL;
			}
			off++;
			if (!bundle_type) { // Skip
				off--;
				free (entry);
				break;
			} else if (bundle_type == 0xff) { // moveable
				off += 2;
				ut8 segnum = *(bin->entry_table + off);
				off++;
				ut16 segoff = *(ut16 *)(bin->entry_table + off);
				if (segnum > 0) {
					entry->paddr = (ut64)bin->segment_entries[segnum - 1].offset * bin->alignment + segoff;
				}
			} else { // Fixed
				if (bundle_type < bin->ne_header->SegCount) {
					entry->paddr = (ut64)bin->segment_entries[bundle_type - 1].offset
						* bin->alignment + *(ut16 *)(bin->entry_table + off);
				}
			}
			off += 2;
			r_list_append (entries, entry);
		}
	}
	r_list_free (segments);
	bin->entries = entries;
	return entries;
}

Fix oobread and unaligned casts in the NE entrypoint logic ##crash

* Reported by @hmsec via huntr.dev
* Reproducer: nepocaligns
* BountyID: ec538fa4-06c6-4050-a141-f60153ddeaac


SWTPM_NVRAM_CheckHeader(unsigned char *data, uint32_t length,
                        uint32_t *dataoffset, uint16_t *hdrflags,
                        uint8_t *hdrversion, bool quiet)
{
    blobheader *bh = (blobheader *)data;

    if (length < sizeof(bh)) {
        if (!quiet)
            logprintf(STDERR_FILENO,
                      "not enough bytes for header: %u\n", length);
        return TPM_BAD_PARAMETER;
    }

    if (ntohl(bh->totlen) != length) {
        if (!quiet)
            logprintf(STDERR_FILENO,
                      "broken header: bh->totlen %u != %u\n",
                      htonl(bh->totlen), length);
        return TPM_BAD_PARAMETER;
    }

    if (bh->min_version > BLOB_HEADER_VERSION) {
        if (!quiet)
            logprintf(STDERR_FILENO,
                      "Minimum required version for the blob is %d, we "
                      "only support version %d\n", bh->min_version,
                      BLOB_HEADER_VERSION);
        return TPM_BAD_VERSION;
    }

    *hdrversion = bh->version;
    *dataoffset = ntohs(bh->hdrsize);
    *hdrflags = ntohs(bh->flags);

    return TPM_SUCCESS;
}

swtpm: Check header size indicator against expected size (CID 375869)

This fix addresses Coverity issue CID 375869.

Check the header size indicated in the header of the state against the
expected size and return an error code in case the header size indicator
is different. There was only one header size so far since blobheader was
introduced, so we don't need to deal with different sizes.

Without this fix a specially craft header could have cause out-of-bounds
accesses on the byte array containing the swtpm's state.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>


static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
{
	int err = 0;
	unsigned int saved_f_flags;
	struct snd_pcm_substream *substream;
	struct snd_pcm_runtime *runtime;
	snd_pcm_format_t format;
	unsigned long width;
	size_t size;

	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
	if (substream != NULL) {
		runtime = substream->runtime;
		if (atomic_read(&substream->mmap_count))
			goto __direct;
		err = snd_pcm_oss_make_ready(substream);
		if (err < 0)
			return err;
		atomic_inc(&runtime->oss.rw_ref);
		if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
			atomic_dec(&runtime->oss.rw_ref);
			return -ERESTARTSYS;
		}
		format = snd_pcm_oss_format_from(runtime->oss.format);
		width = snd_pcm_format_physical_width(format);
		if (runtime->oss.buffer_used > 0) {
#ifdef OSS_DEBUG
			pcm_dbg(substream->pcm, "sync: buffer_used\n");
#endif
			size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width;
			snd_pcm_format_set_silence(format,
						   runtime->oss.buffer + runtime->oss.buffer_used,
						   size);
			err = snd_pcm_oss_sync1(substream, runtime->oss.period_bytes);
			if (err < 0)
				goto unlock;
		} else if (runtime->oss.period_ptr > 0) {
#ifdef OSS_DEBUG
			pcm_dbg(substream->pcm, "sync: period_ptr\n");
#endif
			size = runtime->oss.period_bytes - runtime->oss.period_ptr;
			snd_pcm_format_set_silence(format,
						   runtime->oss.buffer,
						   size * 8 / width);
			err = snd_pcm_oss_sync1(substream, size);
			if (err < 0)
				goto unlock;
		}
		/*
		 * The ALSA's period might be a bit large than OSS one.
		 * Fill the remain portion of ALSA period with zeros.
		 */
		size = runtime->control->appl_ptr % runtime->period_size;
		if (size > 0) {
			size = runtime->period_size - size;
			if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED)
				snd_pcm_lib_write(substream, NULL, size);
			else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
				snd_pcm_lib_writev(substream, NULL, size);
		}
unlock:
		mutex_unlock(&runtime->oss.params_lock);
		atomic_dec(&runtime->oss.rw_ref);
		if (err < 0)
			return err;
		/*
		 * finish sync: drain the buffer
		 */
	      __direct:
		saved_f_flags = substream->f_flags;
		substream->f_flags &= ~O_NONBLOCK;
		err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
		substream->f_flags = saved_f_flags;
		if (err < 0)
			return err;
		mutex_lock(&runtime->oss.params_lock);
		runtime->oss.prepare = 1;
		mutex_unlock(&runtime->oss.params_lock);
	}

	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
	if (substream != NULL) {
		err = snd_pcm_oss_make_ready(substream);
		if (err < 0)
			return err;
		runtime = substream->runtime;
		err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
		if (err < 0)
			return err;
		mutex_lock(&runtime->oss.params_lock);
		runtime->oss.buffer_used = 0;
		runtime->oss.prepare = 1;
		mutex_unlock(&runtime->oss.params_lock);
	}
	return 0;
}

ALSA: pcm: oss: Fix race at SNDCTL_DSP_SYNC

There is a small race window at snd_pcm_oss_sync() that is called from
OSS PCM SNDCTL_DSP_SYNC ioctl; namely the function calls
snd_pcm_oss_make_ready() at first, then takes the params_lock mutex
for the rest.  When the stream is set up again by another thread
between them, it leads to inconsistency, and may result in unexpected
results such as NULL dereference of OSS buffer as a fuzzer spotted
recently.

The fix is simply to cover snd_pcm_oss_make_ready() call into the same
params_lock mutex with snd_pcm_oss_make_ready_locked() variant.

Reported-and-tested-by: butt3rflyh4ck <butterflyhuangxx@gmail.com>
Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/CAFcO6XN7JDM4xSXGhtusQfS2mSBcx50VJKwQpCq=WeLt57aaZA@mail.gmail.com
Link: https://lore.kernel.org/r/20220905060714.22549-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>


static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
		    unsigned long param)
{
	int drive = (long)bdev->bd_disk->private_data;
	int type = ITYPE(drive_state[drive].fd_device);
	int i;
	int ret;
	int size;
	union inparam {
		struct floppy_struct g;	/* geometry */
		struct format_descr f;
		struct floppy_max_errors max_errors;
		struct floppy_drive_params dp;
	} inparam;		/* parameters coming from user space */
	const void *outparam;	/* parameters passed back to user space */

	/* convert compatibility eject ioctls into floppy eject ioctl.
	 * We do this in order to provide a means to eject floppy disks before
	 * installing the new fdutils package */
	if (cmd == CDROMEJECT ||	/* CD-ROM eject */
	    cmd == 0x6470) {		/* SunOS floppy eject */
		DPRINT("obsolete eject ioctl\n");
		DPRINT("please use floppycontrol --eject\n");
		cmd = FDEJECT;
	}

	if (!((cmd & 0xff00) == 0x0200))
		return -EINVAL;

	/* convert the old style command into a new style command */
	ret = normalize_ioctl(&cmd, &size);
	if (ret)
		return ret;

	/* permission checks */
	if (((cmd & 0x40) && !(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL))) ||
	    ((cmd & 0x80) && !capable(CAP_SYS_ADMIN)))
		return -EPERM;

	if (WARN_ON(size < 0 || size > sizeof(inparam)))
		return -EINVAL;

	/* copyin */
	memset(&inparam, 0, sizeof(inparam));
	if (_IOC_DIR(cmd) & _IOC_WRITE) {
		ret = fd_copyin((void __user *)param, &inparam, size);
		if (ret)
			return ret;
	}

	switch (cmd) {
	case FDEJECT:
		if (drive_state[drive].fd_ref != 1)
			/* somebody else has this drive open */
			return -EBUSY;
		if (lock_fdc(drive))
			return -EINTR;

		/* do the actual eject. Fails on
		 * non-Sparc architectures */
		ret = fd_eject(UNIT(drive));

		set_bit(FD_DISK_CHANGED_BIT, &drive_state[drive].flags);
		set_bit(FD_VERIFY_BIT, &drive_state[drive].flags);
		process_fd_request();
		return ret;
	case FDCLRPRM:
		if (lock_fdc(drive))
			return -EINTR;
		current_type[drive] = NULL;
		floppy_sizes[drive] = MAX_DISK_SIZE << 1;
		drive_state[drive].keep_data = 0;
		return invalidate_drive(bdev);
	case FDSETPRM:
	case FDDEFPRM:
		return set_geometry(cmd, &inparam.g, drive, type, bdev);
	case FDGETPRM:
		ret = get_floppy_geometry(drive, type,
					  (struct floppy_struct **)&outparam);
		if (ret)
			return ret;
		memcpy(&inparam.g, outparam,
				offsetof(struct floppy_struct, name));
		outparam = &inparam.g;
		break;
	case FDMSGON:
		drive_params[drive].flags |= FTD_MSG;
		return 0;
	case FDMSGOFF:
		drive_params[drive].flags &= ~FTD_MSG;
		return 0;
	case FDFMTBEG:
		if (lock_fdc(drive))
			return -EINTR;
		if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR)
			return -EINTR;
		ret = drive_state[drive].flags;
		process_fd_request();
		if (ret & FD_VERIFY)
			return -ENODEV;
		if (!(ret & FD_DISK_WRITABLE))
			return -EROFS;
		return 0;
	case FDFMTTRK:
		if (drive_state[drive].fd_ref != 1)
			return -EBUSY;
		return do_format(drive, &inparam.f);
	case FDFMTEND:
	case FDFLUSH:
		if (lock_fdc(drive))
			return -EINTR;
		return invalidate_drive(bdev);
	case FDSETEMSGTRESH:
		drive_params[drive].max_errors.reporting = (unsigned short)(param & 0x0f);
		return 0;
	case FDGETMAXERRS:
		outparam = &drive_params[drive].max_errors;
		break;
	case FDSETMAXERRS:
		drive_params[drive].max_errors = inparam.max_errors;
		break;
	case FDGETDRVTYP:
		outparam = drive_name(type, drive);
		SUPBOUND(size, strlen((const char *)outparam) + 1);
		break;
	case FDSETDRVPRM:
		if (!valid_floppy_drive_params(inparam.dp.autodetect,
				inparam.dp.native_format))
			return -EINVAL;
		drive_params[drive] = inparam.dp;
		break;
	case FDGETDRVPRM:
		outparam = &drive_params[drive];
		break;
	case FDPOLLDRVSTAT:
		if (lock_fdc(drive))
			return -EINTR;
		if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR)
			return -EINTR;
		process_fd_request();
		fallthrough;
	case FDGETDRVSTAT:
		outparam = &drive_state[drive];
		break;
	case FDRESET:
		return user_reset_fdc(drive, (int)param, true);
	case FDGETFDCSTAT:
		outparam = &fdc_state[FDC(drive)];
		break;
	case FDWERRORCLR:
		memset(&write_errors[drive], 0, sizeof(write_errors[drive]));
		return 0;
	case FDWERRORGET:
		outparam = &write_errors[drive];
		break;
	case FDRAWCMD:
		if (type)
			return -EINVAL;
		if (lock_fdc(drive))
			return -EINTR;
		set_floppy(drive);
		i = raw_cmd_ioctl(cmd, (void __user *)param);
		if (i == -EINTR)
			return -EINTR;
		process_fd_request();
		return i;
	case FDTWADDLE:
		if (lock_fdc(drive))
			return -EINTR;
		twaddle(current_fdc, current_drive);
		process_fd_request();
		return 0;
	default:
		return -EINVAL;
	}

	if (_IOC_DIR(cmd) & _IOC_READ)
		return fd_copyout((void __user *)param, outparam, size);

	return 0;
}

floppy: disable FDRAWCMD by default

Minh Yuan reported a concurrency use-after-free issue in the floppy code
between raw_cmd_ioctl and seek_interrupt.

[ It turns out this has been around, and that others have reported the
  KASAN splats over the years, but Minh Yuan had a reproducer for it and
  so gets primary credit for reporting it for this fix   - Linus ]

The problem is, this driver tends to break very easily and nowadays,
nobody is expected to use FDRAWCMD anyway since it was used to
manipulate non-standard formats.  The risk of breaking the driver is
higher than the risk presented by this race, and accessing the device
requires privileges anyway.

Let's just add a config option to completely disable this ioctl and
leave it disabled by default.  Distros shouldn't use it, and only those
running on antique hardware might need to enable it.

Link: https://lore.kernel.org/all/000000000000b71cdd05d703f6bf@google.com/
Link: https://lore.kernel.org/lkml/CAKcFiNC=MfYVW-Jt9A3=FPJpTwCD2PL_ULNCpsCVE5s8ZeBQgQ@mail.gmail.com
Link: https://lore.kernel.org/all/CAEAjamu1FRhz6StCe_55XY5s389ZP_xmCF69k987En+1z53=eg@mail.gmail.com
Reported-by: Minh Yuan <yuanmingbuaa@gmail.com>
Reported-by: syzbot+8e8958586909d62b6840@syzkaller.appspotmail.com
Reported-by: cruise k <cruise4k@gmail.com>
Reported-by: Kyungtae Kim <kt0755@gmail.com>
Suggested-by: Linus Torvalds <torvalds@linuxfoundation.org>
Tested-by: Denis Efremov <efremov@linux.com>
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>


static void rtrs_clt_dev_release(struct device *dev)
{
	struct rtrs_clt_sess *clt = container_of(dev, struct rtrs_clt_sess,
						 dev);

	kfree(clt);
}

RDMA/rtrs-clt: Fix possible double free in error case

Callback function rtrs_clt_dev_release() for put_device() calls kfree(clt)
to free memory. We shouldn't call kfree(clt) again, and we can't use the
clt after kfree too.

Replace device_register() with device_initialize() and device_add() so that
dev_set_name can() be used appropriately.

Move mutex_destroy() to the release function so it can be called in
the alloc_clt err path.

Fixes: eab098246625 ("RDMA/rtrs-clt: Refactor the failure cases in alloc_clt")
Link: https://lore.kernel.org/r/20220217030929.323849-1-haris.iqbal@ionos.com
Reported-by: Miaoqian Lin <linmq006@gmail.com>
Signed-off-by: Md Haris Iqbal <haris.iqbal@ionos.com>
Reviewed-by: Jack Wang <jinpu.wang@ionos.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>


void LinkResolver::resolve_handle_call(CallInfo& result,
                                       const LinkInfo& link_info,
                                       TRAPS) {
  // JSR 292:  this must be an implicitly generated method MethodHandle.invokeExact(*...) or similar
  Klass* resolved_klass = link_info.resolved_klass();
  assert(resolved_klass == SystemDictionary::MethodHandle_klass() ||
         resolved_klass == SystemDictionary::VarHandle_klass(), "");
  assert(MethodHandles::is_signature_polymorphic_name(link_info.name()), "");
  Handle       resolved_appendix;
  Handle       resolved_method_type;
  methodHandle resolved_method = lookup_polymorphic_method(link_info,
                                       &resolved_appendix, &resolved_method_type, CHECK);
  result.set_handle(resolved_klass, resolved_method, resolved_appendix, resolved_method_type, CHECK);
}

8281866: Enhance MethodHandle invocations

Reviewed-by: mbaesken
Backport-of: d974d9da365f787f67971d88c79371c8b0769f75


inbound_cap_ls (server *serv, char *nick, char *extensions_str,
					 const message_tags_data *tags_data)
{
	char buffer[256];	/* buffer for requesting capabilities and emitting the signal */
	guint32 want_cap; /* format the CAP REQ string based on previous capabilities being requested or not */
	guint32 want_sasl; /* CAP END shouldn't be sent when SASL is requested, it needs further responses */
	char **extensions;
	int i;

	EMIT_SIGNAL_TIMESTAMP (XP_TE_CAPLIST, serv->server_session, nick,
								  extensions_str, NULL, NULL, 0, tags_data->timestamp);
	want_cap = 0;
	want_sasl = 0;

	extensions = g_strsplit (extensions_str, " ", 0);

	strcpy (buffer, "CAP REQ :");

	for (i=0; extensions[i]; i++)
	{
		const char *extension = extensions[i];

		if (!strcmp (extension, "identify-msg"))
		{
			strcat (buffer, "identify-msg ");
			want_cap = 1;
		}
		if (!strcmp (extension, "multi-prefix"))
		{
			strcat (buffer, "multi-prefix ");
			want_cap = 1;
		}
		if (!strcmp (extension, "away-notify"))
		{
			strcat (buffer, "away-notify ");
			want_cap = 1;
		}
		if (!strcmp (extension, "account-notify"))
		{
			strcat (buffer, "account-notify ");
			want_cap = 1;
		}
		if (!strcmp (extension, "extended-join"))
		{
			strcat (buffer, "extended-join ");
			want_cap = 1;
		}
		if (!strcmp (extension, "userhost-in-names"))
		{
			strcat (buffer, "userhost-in-names ");
			want_cap = 1;
		}

		/* bouncers can prefix a name space to the extension so we should use.
		 * znc <= 1.0 uses "znc.in/server-time" and newer use "znc.in/server-time-iso".
		 */
		if (!strcmp (extension, "znc.in/server-time-iso"))
		{
			strcat (buffer, "znc.in/server-time-iso ");
			want_cap = 1;
		}
		if (!strcmp (extension, "znc.in/server-time"))
		{
			strcat (buffer, "znc.in/server-time ");
			want_cap = 1;
		}
		if (prefs.hex_irc_cap_server_time
			 && !strcmp (extension, "server-time"))
		{
			strcat (buffer, "server-time ");
			want_cap = 1;
		}

		/* if the SASL password is set AND auth mode is set to SASL, request SASL auth */
		if (!strcmp (extension, "sasl")
			&& ((serv->loginmethod == LOGIN_SASL && strlen (serv->password) != 0)
			|| (serv->loginmethod == LOGIN_SASLEXTERNAL && serv->have_cert)))
		{
			strcat (buffer, "sasl ");
			want_cap = 1;
			want_sasl = 1;
		}
	}

	g_strfreev (extensions);

	if (want_cap)
	{
		/* buffer + 9 = emit buffer without "CAP REQ :" */
		EMIT_SIGNAL_TIMESTAMP (XP_TE_CAPREQ, serv->server_session,
									  buffer + 9, NULL, NULL, NULL, 0,
									  tags_data->timestamp);
		tcp_sendf (serv, "%s\r\n", g_strchomp (buffer));
	}
	if (!want_sasl)
	{
		/* if we use SASL, CAP END is dealt via raw numerics */
		serv->sent_capend = TRUE;
		tcp_send_len (serv, "CAP END\r\n", 9);
	}
}

Clean up handling CAP LS


size_t puma_parser_execute(puma_parser *parser, const char *buffer, size_t len, size_t off)  {
  const char *p, *pe;
  int cs = parser->cs;

  assert(off <= len && "offset past end of buffer");

  p = buffer+off;
  pe = buffer+len;

  /* assert(*pe == '\0' && "pointer does not end on NUL"); */
  assert((size_t) (pe - p) == len - off && "pointers aren't same distance");

#line 87 "ext/puma_http11/http11_parser.c"
	{
	if ( p == pe )
		goto _test_eof;
	switch ( cs )
	{
case 1:
	switch( (*p) ) {
		case 36: goto tr0;
		case 95: goto tr0;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto tr0;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto tr0;
	} else
		goto tr0;
	goto st0;
st0:
cs = 0;
	goto _out;
tr0:
#line 37 "ext/puma_http11/http11_parser.rl"
	{ MARK(mark, p); }
	goto st2;
st2:
	if ( ++p == pe )
		goto _test_eof2;
case 2:
#line 118 "ext/puma_http11/http11_parser.c"
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st27;
		case 95: goto st27;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st27;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st27;
	} else
		goto st27;
	goto st0;
tr2:
#line 50 "ext/puma_http11/http11_parser.rl"
	{
    parser->request_method(parser, PTR_TO(mark), LEN(mark, p));
  }
	goto st3;
st3:
	if ( ++p == pe )
		goto _test_eof3;
case 3:
#line 143 "ext/puma_http11/http11_parser.c"
	switch( (*p) ) {
		case 42: goto tr4;
		case 43: goto tr5;
		case 47: goto tr6;
		case 58: goto tr7;
	}
	if ( (*p) < 65 ) {
		if ( 45 <= (*p) && (*p) <= 57 )
			goto tr5;
	} else if ( (*p) > 90 ) {
		if ( 97 <= (*p) && (*p) <= 122 )
			goto tr5;
	} else
		goto tr5;
	goto st0;
tr4:
#line 37 "ext/puma_http11/http11_parser.rl"
	{ MARK(mark, p); }
	goto st4;
st4:
	if ( ++p == pe )
		goto _test_eof4;
case 4:
#line 167 "ext/puma_http11/http11_parser.c"
	switch( (*p) ) {
		case 32: goto tr8;
		case 35: goto tr9;
	}
	goto st0;
tr8:
#line 53 "ext/puma_http11/http11_parser.rl"
	{
    parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
  }
	goto st5;
tr31:
#line 37 "ext/puma_http11/http11_parser.rl"
	{ MARK(mark, p); }
#line 56 "ext/puma_http11/http11_parser.rl"
	{
    parser->fragment(parser, PTR_TO(mark), LEN(mark, p));
  }
	goto st5;
tr33:
#line 56 "ext/puma_http11/http11_parser.rl"
	{
    parser->fragment(parser, PTR_TO(mark), LEN(mark, p));
  }
	goto st5;
tr37:
#line 69 "ext/puma_http11/http11_parser.rl"
	{
    parser->request_path(parser, PTR_TO(mark), LEN(mark,p));
  }
#line 53 "ext/puma_http11/http11_parser.rl"
	{
    parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
  }
	goto st5;
tr41:
#line 60 "ext/puma_http11/http11_parser.rl"
	{ MARK(query_start, p); }
#line 61 "ext/puma_http11/http11_parser.rl"
	{
    parser->query_string(parser, PTR_TO(query_start), LEN(query_start, p));
  }
#line 53 "ext/puma_http11/http11_parser.rl"
	{
    parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
  }
	goto st5;
tr44:
#line 61 "ext/puma_http11/http11_parser.rl"
	{
    parser->query_string(parser, PTR_TO(query_start), LEN(query_start, p));
  }
#line 53 "ext/puma_http11/http11_parser.rl"
	{
    parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
  }
	goto st5;
st5:
	if ( ++p == pe )
		goto _test_eof5;
case 5:
#line 229 "ext/puma_http11/http11_parser.c"
	if ( (*p) == 72 )
		goto tr10;
	goto st0;
tr10:
#line 37 "ext/puma_http11/http11_parser.rl"
	{ MARK(mark, p); }
	goto st6;
st6:
	if ( ++p == pe )
		goto _test_eof6;
case 6:
#line 241 "ext/puma_http11/http11_parser.c"
	if ( (*p) == 84 )
		goto st7;
	goto st0;
st7:
	if ( ++p == pe )
		goto _test_eof7;
case 7:
	if ( (*p) == 84 )
		goto st8;
	goto st0;
st8:
	if ( ++p == pe )
		goto _test_eof8;
case 8:
	if ( (*p) == 80 )
		goto st9;
	goto st0;
st9:
	if ( ++p == pe )
		goto _test_eof9;
case 9:
	if ( (*p) == 47 )
		goto st10;
	goto st0;
st10:
	if ( ++p == pe )
		goto _test_eof10;
case 10:
	if ( 48 <= (*p) && (*p) <= 57 )
		goto st11;
	goto st0;
st11:
	if ( ++p == pe )
		goto _test_eof11;
case 11:
	if ( (*p) == 46 )
		goto st12;
	if ( 48 <= (*p) && (*p) <= 57 )
		goto st11;
	goto st0;
st12:
	if ( ++p == pe )
		goto _test_eof12;
case 12:
	if ( 48 <= (*p) && (*p) <= 57 )
		goto st13;
	goto st0;
st13:
	if ( ++p == pe )
		goto _test_eof13;
case 13:
	if ( (*p) == 13 )
		goto tr18;
	if ( 48 <= (*p) && (*p) <= 57 )
		goto st13;
	goto st0;
tr18:
#line 65 "ext/puma_http11/http11_parser.rl"
	{
    parser->http_version(parser, PTR_TO(mark), LEN(mark, p));
  }
	goto st14;
tr26:
#line 46 "ext/puma_http11/http11_parser.rl"
	{ MARK(mark, p); }
#line 47 "ext/puma_http11/http11_parser.rl"
	{
    parser->http_field(parser, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p));
  }
	goto st14;
tr29:
#line 47 "ext/puma_http11/http11_parser.rl"
	{
    parser->http_field(parser, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p));
  }
	goto st14;
st14:
	if ( ++p == pe )
		goto _test_eof14;
case 14:
#line 322 "ext/puma_http11/http11_parser.c"
	if ( (*p) == 10 )
		goto st15;
	goto st0;
st15:
	if ( ++p == pe )
		goto _test_eof15;
case 15:
	switch( (*p) ) {
		case 13: goto st16;
		case 33: goto tr21;
		case 124: goto tr21;
		case 126: goto tr21;
	}
	if ( (*p) < 45 ) {
		if ( (*p) > 39 ) {
			if ( 42 <= (*p) && (*p) <= 43 )
				goto tr21;
		} else if ( (*p) >= 35 )
			goto tr21;
	} else if ( (*p) > 46 ) {
		if ( (*p) < 65 ) {
			if ( 48 <= (*p) && (*p) <= 57 )
				goto tr21;
		} else if ( (*p) > 90 ) {
			if ( 94 <= (*p) && (*p) <= 122 )
				goto tr21;
		} else
			goto tr21;
	} else
		goto tr21;
	goto st0;
st16:
	if ( ++p == pe )
		goto _test_eof16;
case 16:
	if ( (*p) == 10 )
		goto tr22;
	goto st0;
tr22:
#line 73 "ext/puma_http11/http11_parser.rl"
	{
    parser->body_start = p - buffer + 1;
    parser->header_done(parser, p + 1, pe - p - 1);
    {p++; cs = 46; goto _out;}
  }
	goto st46;
st46:
	if ( ++p == pe )
		goto _test_eof46;
case 46:
#line 373 "ext/puma_http11/http11_parser.c"
	goto st0;
tr21:
#line 40 "ext/puma_http11/http11_parser.rl"
	{ MARK(field_start, p); }
#line 41 "ext/puma_http11/http11_parser.rl"
	{ snake_upcase_char((char *)p); }
	goto st17;
tr23:
#line 41 "ext/puma_http11/http11_parser.rl"
	{ snake_upcase_char((char *)p); }
	goto st17;
st17:
	if ( ++p == pe )
		goto _test_eof17;
case 17:
#line 389 "ext/puma_http11/http11_parser.c"
	switch( (*p) ) {
		case 33: goto tr23;
		case 58: goto tr24;
		case 124: goto tr23;
		case 126: goto tr23;
	}
	if ( (*p) < 45 ) {
		if ( (*p) > 39 ) {
			if ( 42 <= (*p) && (*p) <= 43 )
				goto tr23;
		} else if ( (*p) >= 35 )
			goto tr23;
	} else if ( (*p) > 46 ) {
		if ( (*p) < 65 ) {
			if ( 48 <= (*p) && (*p) <= 57 )
				goto tr23;
		} else if ( (*p) > 90 ) {
			if ( 94 <= (*p) && (*p) <= 122 )
				goto tr23;
		} else
			goto tr23;
	} else
		goto tr23;
	goto st0;
tr24:
#line 42 "ext/puma_http11/http11_parser.rl"
	{
    parser->field_len = LEN(field_start, p);
  }
	goto st18;
tr27:
#line 46 "ext/puma_http11/http11_parser.rl"
	{ MARK(mark, p); }
	goto st18;
st18:
	if ( ++p == pe )
		goto _test_eof18;
case 18:
#line 428 "ext/puma_http11/http11_parser.c"
	switch( (*p) ) {
		case 13: goto tr26;
		case 32: goto tr27;
	}
	goto tr25;
tr25:
#line 46 "ext/puma_http11/http11_parser.rl"
	{ MARK(mark, p); }
	goto st19;
st19:
	if ( ++p == pe )
		goto _test_eof19;
case 19:
#line 442 "ext/puma_http11/http11_parser.c"
	if ( (*p) == 13 )
		goto tr29;
	goto st19;
tr9:
#line 53 "ext/puma_http11/http11_parser.rl"
	{
    parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
  }
	goto st20;
tr38:
#line 69 "ext/puma_http11/http11_parser.rl"
	{
    parser->request_path(parser, PTR_TO(mark), LEN(mark,p));
  }
#line 53 "ext/puma_http11/http11_parser.rl"
	{
    parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
  }
	goto st20;
tr42:
#line 60 "ext/puma_http11/http11_parser.rl"
	{ MARK(query_start, p); }
#line 61 "ext/puma_http11/http11_parser.rl"
	{
    parser->query_string(parser, PTR_TO(query_start), LEN(query_start, p));
  }
#line 53 "ext/puma_http11/http11_parser.rl"
	{
    parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
  }
	goto st20;
tr45:
#line 61 "ext/puma_http11/http11_parser.rl"
	{
    parser->query_string(parser, PTR_TO(query_start), LEN(query_start, p));
  }
#line 53 "ext/puma_http11/http11_parser.rl"
	{
    parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
  }
	goto st20;
st20:
	if ( ++p == pe )
		goto _test_eof20;
case 20:
#line 488 "ext/puma_http11/http11_parser.c"
	switch( (*p) ) {
		case 32: goto tr31;
		case 60: goto st0;
		case 62: goto st0;
		case 127: goto st0;
	}
	if ( (*p) > 31 ) {
		if ( 34 <= (*p) && (*p) <= 35 )
			goto st0;
	} else if ( (*p) >= 0 )
		goto st0;
	goto tr30;
tr30:
#line 37 "ext/puma_http11/http11_parser.rl"
	{ MARK(mark, p); }
	goto st21;
st21:
	if ( ++p == pe )
		goto _test_eof21;
case 21:
#line 509 "ext/puma_http11/http11_parser.c"
	switch( (*p) ) {
		case 32: goto tr33;
		case 60: goto st0;
		case 62: goto st0;
		case 127: goto st0;
	}
	if ( (*p) > 31 ) {
		if ( 34 <= (*p) && (*p) <= 35 )
			goto st0;
	} else if ( (*p) >= 0 )
		goto st0;
	goto st21;
tr5:
#line 37 "ext/puma_http11/http11_parser.rl"
	{ MARK(mark, p); }
	goto st22;
st22:
	if ( ++p == pe )
		goto _test_eof22;
case 22:
#line 530 "ext/puma_http11/http11_parser.c"
	switch( (*p) ) {
		case 43: goto st22;
		case 58: goto st23;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st22;
	} else if ( (*p) > 57 ) {
		if ( (*p) > 90 ) {
			if ( 97 <= (*p) && (*p) <= 122 )
				goto st22;
		} else if ( (*p) >= 65 )
			goto st22;
	} else
		goto st22;
	goto st0;
tr7:
#line 37 "ext/puma_http11/http11_parser.rl"
	{ MARK(mark, p); }
	goto st23;
st23:
	if ( ++p == pe )
		goto _test_eof23;
case 23:
#line 555 "ext/puma_http11/http11_parser.c"
	switch( (*p) ) {
		case 32: goto tr8;
		case 34: goto st0;
		case 35: goto tr9;
		case 60: goto st0;
		case 62: goto st0;
		case 127: goto st0;
	}
	if ( 0 <= (*p) && (*p) <= 31 )
		goto st0;
	goto st23;
tr6:
#line 37 "ext/puma_http11/http11_parser.rl"
	{ MARK(mark, p); }
	goto st24;
st24:
	if ( ++p == pe )
		goto _test_eof24;
case 24:
#line 575 "ext/puma_http11/http11_parser.c"
	switch( (*p) ) {
		case 32: goto tr37;
		case 34: goto st0;
		case 35: goto tr38;
		case 60: goto st0;
		case 62: goto st0;
		case 63: goto tr39;
		case 127: goto st0;
	}
	if ( 0 <= (*p) && (*p) <= 31 )
		goto st0;
	goto st24;
tr39:
#line 69 "ext/puma_http11/http11_parser.rl"
	{
    parser->request_path(parser, PTR_TO(mark), LEN(mark,p));
  }
	goto st25;
st25:
	if ( ++p == pe )
		goto _test_eof25;
case 25:
#line 598 "ext/puma_http11/http11_parser.c"
	switch( (*p) ) {
		case 32: goto tr41;
		case 34: goto st0;
		case 35: goto tr42;
		case 60: goto st0;
		case 62: goto st0;
		case 127: goto st0;
	}
	if ( 0 <= (*p) && (*p) <= 31 )
		goto st0;
	goto tr40;
tr40:
#line 60 "ext/puma_http11/http11_parser.rl"
	{ MARK(query_start, p); }
	goto st26;
st26:
	if ( ++p == pe )
		goto _test_eof26;
case 26:
#line 618 "ext/puma_http11/http11_parser.c"
	switch( (*p) ) {
		case 32: goto tr44;
		case 34: goto st0;
		case 35: goto tr45;
		case 60: goto st0;
		case 62: goto st0;
		case 127: goto st0;
	}
	if ( 0 <= (*p) && (*p) <= 31 )
		goto st0;
	goto st26;
st27:
	if ( ++p == pe )
		goto _test_eof27;
case 27:
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st28;
		case 95: goto st28;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st28;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st28;
	} else
		goto st28;
	goto st0;
st28:
	if ( ++p == pe )
		goto _test_eof28;
case 28:
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st29;
		case 95: goto st29;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st29;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st29;
	} else
		goto st29;
	goto st0;
st29:
	if ( ++p == pe )
		goto _test_eof29;
case 29:
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st30;
		case 95: goto st30;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st30;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st30;
	} else
		goto st30;
	goto st0;
st30:
	if ( ++p == pe )
		goto _test_eof30;
case 30:
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st31;
		case 95: goto st31;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st31;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st31;
	} else
		goto st31;
	goto st0;
st31:
	if ( ++p == pe )
		goto _test_eof31;
case 31:
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st32;
		case 95: goto st32;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st32;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st32;
	} else
		goto st32;
	goto st0;
st32:
	if ( ++p == pe )
		goto _test_eof32;
case 32:
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st33;
		case 95: goto st33;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st33;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st33;
	} else
		goto st33;
	goto st0;
st33:
	if ( ++p == pe )
		goto _test_eof33;
case 33:
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st34;
		case 95: goto st34;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st34;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st34;
	} else
		goto st34;
	goto st0;
st34:
	if ( ++p == pe )
		goto _test_eof34;
case 34:
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st35;
		case 95: goto st35;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st35;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st35;
	} else
		goto st35;
	goto st0;
st35:
	if ( ++p == pe )
		goto _test_eof35;
case 35:
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st36;
		case 95: goto st36;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st36;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st36;
	} else
		goto st36;
	goto st0;
st36:
	if ( ++p == pe )
		goto _test_eof36;
case 36:
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st37;
		case 95: goto st37;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st37;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st37;
	} else
		goto st37;
	goto st0;
st37:
	if ( ++p == pe )
		goto _test_eof37;
case 37:
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st38;
		case 95: goto st38;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st38;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st38;
	} else
		goto st38;
	goto st0;
st38:
	if ( ++p == pe )
		goto _test_eof38;
case 38:
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st39;
		case 95: goto st39;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st39;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st39;
	} else
		goto st39;
	goto st0;
st39:
	if ( ++p == pe )
		goto _test_eof39;
case 39:
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st40;
		case 95: goto st40;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st40;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st40;
	} else
		goto st40;
	goto st0;
st40:
	if ( ++p == pe )
		goto _test_eof40;
case 40:
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st41;
		case 95: goto st41;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st41;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st41;
	} else
		goto st41;
	goto st0;
st41:
	if ( ++p == pe )
		goto _test_eof41;
case 41:
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st42;
		case 95: goto st42;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st42;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st42;
	} else
		goto st42;
	goto st0;
st42:
	if ( ++p == pe )
		goto _test_eof42;
case 42:
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st43;
		case 95: goto st43;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st43;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st43;
	} else
		goto st43;
	goto st0;
st43:
	if ( ++p == pe )
		goto _test_eof43;
case 43:
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st44;
		case 95: goto st44;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st44;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st44;
	} else
		goto st44;
	goto st0;
st44:
	if ( ++p == pe )
		goto _test_eof44;
case 44:
	switch( (*p) ) {
		case 32: goto tr2;
		case 36: goto st45;
		case 95: goto st45;
	}
	if ( (*p) < 48 ) {
		if ( 45 <= (*p) && (*p) <= 46 )
			goto st45;
	} else if ( (*p) > 57 ) {
		if ( 65 <= (*p) && (*p) <= 90 )
			goto st45;
	} else
		goto st45;
	goto st0;
st45:
	if ( ++p == pe )
		goto _test_eof45;
case 45:
	if ( (*p) == 32 )
		goto tr2;
	goto st0;
	}
	_test_eof2: cs = 2; goto _test_eof;
	_test_eof3: cs = 3; goto _test_eof;
	_test_eof4: cs = 4; goto _test_eof;
	_test_eof5: cs = 5; goto _test_eof;
	_test_eof6: cs = 6; goto _test_eof;
	_test_eof7: cs = 7; goto _test_eof;
	_test_eof8: cs = 8; goto _test_eof;
	_test_eof9: cs = 9; goto _test_eof;
	_test_eof10: cs = 10; goto _test_eof;
	_test_eof11: cs = 11; goto _test_eof;
	_test_eof12: cs = 12; goto _test_eof;
	_test_eof13: cs = 13; goto _test_eof;
	_test_eof14: cs = 14; goto _test_eof;
	_test_eof15: cs = 15; goto _test_eof;
	_test_eof16: cs = 16; goto _test_eof;
	_test_eof46: cs = 46; goto _test_eof;
	_test_eof17: cs = 17; goto _test_eof;
	_test_eof18: cs = 18; goto _test_eof;
	_test_eof19: cs = 19; goto _test_eof;
	_test_eof20: cs = 20; goto _test_eof;
	_test_eof21: cs = 21; goto _test_eof;
	_test_eof22: cs = 22; goto _test_eof;
	_test_eof23: cs = 23; goto _test_eof;
	_test_eof24: cs = 24; goto _test_eof;
	_test_eof25: cs = 25; goto _test_eof;
	_test_eof26: cs = 26; goto _test_eof;
	_test_eof27: cs = 27; goto _test_eof;
	_test_eof28: cs = 28; goto _test_eof;
	_test_eof29: cs = 29; goto _test_eof;
	_test_eof30: cs = 30; goto _test_eof;
	_test_eof31: cs = 31; goto _test_eof;
	_test_eof32: cs = 32; goto _test_eof;
	_test_eof33: cs = 33; goto _test_eof;
	_test_eof34: cs = 34; goto _test_eof;
	_test_eof35: cs = 35; goto _test_eof;
	_test_eof36: cs = 36; goto _test_eof;
	_test_eof37: cs = 37; goto _test_eof;
	_test_eof38: cs = 38; goto _test_eof;
	_test_eof39: cs = 39; goto _test_eof;
	_test_eof40: cs = 40; goto _test_eof;
	_test_eof41: cs = 41; goto _test_eof;
	_test_eof42: cs = 42; goto _test_eof;
	_test_eof43: cs = 43; goto _test_eof;
	_test_eof44: cs = 44; goto _test_eof;
	_test_eof45: cs = 45; goto _test_eof;

	_test_eof: {}
	_out: {}
	}

#line 117 "ext/puma_http11/http11_parser.rl"

  if (!puma_parser_has_error(parser))
    parser->cs = cs;
  parser->nread += p - (buffer + off);

  assert(p <= pe && "buffer overflow after parsing execute");
  assert(parser->nread <= len && "nread longer than length");
  assert(parser->body_start <= len && "body starts after buffer end");
  assert(parser->mark < len && "mark is after buffer end");
  assert(parser->field_len <= len && "field has length longer than whole buffer");
  assert(parser->field_start < len && "field starts after buffer end");

  return(parser->nread);
}

Merge pull request from GHSA-48w2-rm65-62xx

* Fix HTTP request smuggling vulnerability

See GHSA-48w2-rm65-62xx or CVE-2021-41136 for more info.

* 4.3.9 release note

* 5.5.1 release note

* 5.5.1


gif_internal_decode_frame(gif_animation *gif,
                          unsigned int frame,
                          bool clear_image)
{
        unsigned int index = 0;
        const unsigned char *gif_data, *gif_end;
        ssize_t gif_bytes;
        unsigned int width, height, offset_x, offset_y;
        unsigned int flags, colour_table_size, interlace;
        unsigned int *colour_table;
        unsigned int *frame_data = 0;	// Set to 0 for no warnings
        unsigned int *frame_scanline;
        ssize_t save_buffer_position;
        unsigned int return_value = 0;
        unsigned int x, y, decode_y, burst_bytes;
        register unsigned char colour;

        /* Ensure this frame is supposed to be decoded */
        if (gif->frames[frame].display == false) {
                return GIF_OK;
        }

        /* Ensure the frame is in range to decode */
        if (frame > gif->frame_count_partial) {
                return GIF_INSUFFICIENT_DATA;
        }

        /* done if frame is already decoded */
        if ((!clear_image) &&
            ((int)frame == gif->decoded_frame)) {
                return GIF_OK;
        }

        /* Get the start of our frame data and the end of the GIF data */
        gif_data = gif->gif_data + gif->frames[frame].frame_pointer;
        gif_end = gif->gif_data + gif->buffer_size;
        gif_bytes = (gif_end - gif_data);

        /*
         * Ensure there is a minimal amount of data to proceed.  The shortest
         * block of data is a 10-byte image descriptor + 1-byte gif trailer
         */
        if (gif_bytes < 12) {
                return GIF_INSUFFICIENT_FRAME_DATA;
        }

        /* Save the buffer position */
        save_buffer_position = gif->buffer_position;
        gif->buffer_position = gif_data - gif->gif_data;

        /* Skip any extensions because they have allready been processed */
        if ((return_value = gif_skip_frame_extensions(gif)) != GIF_OK) {
                goto gif_decode_frame_exit;
        }
        gif_data = (gif->gif_data + gif->buffer_position);
        gif_bytes = (gif_end - gif_data);

        /* Ensure we have enough data for the 10-byte image descriptor + 1-byte
         * gif trailer
         */
        if (gif_bytes < 12) {
                return_value = GIF_INSUFFICIENT_FRAME_DATA;
                goto gif_decode_frame_exit;
        }

        /* 10-byte Image Descriptor is:
         *
         *	+0	CHAR	Image Separator (0x2c)
         *	+1	SHORT	Image Left Position
         *	+3	SHORT	Image Top Position
         *	+5	SHORT	Width
         *	+7	SHORT	Height
         *	+9	CHAR	__Packed Fields__
         *			1BIT	Local Colour Table Flag
         *			1BIT	Interlace Flag
         *			1BIT	Sort Flag
         *			2BITS	Reserved
         *			3BITS	Size of Local Colour Table
         */
        if (gif_data[0] != GIF_IMAGE_SEPARATOR) {
                return_value = GIF_DATA_ERROR;
                goto gif_decode_frame_exit;
        }
        offset_x = gif_data[1] | (gif_data[2] << 8);
        offset_y = gif_data[3] | (gif_data[4] << 8);
        width = gif_data[5] | (gif_data[6] << 8);
        height = gif_data[7] | (gif_data[8] << 8);

        /* Boundary checking - shouldn't ever happen except unless the data has
         * been modified since initialisation.
         */
        if ((offset_x + width > gif->width) ||
            (offset_y + height > gif->height)) {
                return_value = GIF_DATA_ERROR;
                goto gif_decode_frame_exit;
        }

        /* Decode the flags */
        flags = gif_data[9];
        colour_table_size = 2 << (flags & GIF_COLOUR_TABLE_SIZE_MASK);
        interlace = flags & GIF_INTERLACE_MASK;

        /* Advance data pointer to next block either colour table or image
         * data.
         */
        gif_data += 10;
        gif_bytes = (gif_end - gif_data);

        /* Set up the colour table */
        if (flags & GIF_COLOUR_TABLE_MASK) {
                if (gif_bytes < (int)(3 * colour_table_size)) {
                        return_value = GIF_INSUFFICIENT_FRAME_DATA;
                        goto gif_decode_frame_exit;
                }
                colour_table = gif->local_colour_table;
                if (!clear_image) {
                        for (index = 0; index < colour_table_size; index++) {
                                /* Gif colour map contents are r,g,b.
                                 *
                                 * We want to pack them bytewise into the
                                 * colour table, such that the red component
                                 * is in byte 0 and the alpha component is in
                                 * byte 3.
                                 */
                                unsigned char *entry =
                                        (unsigned char *) &colour_table[index];

                                entry[0] = gif_data[0];	/* r */
                                entry[1] = gif_data[1];	/* g */
                                entry[2] = gif_data[2];	/* b */
                                entry[3] = 0xff;	/* a */

                                gif_data += 3;
                        }
                } else {
                        gif_data += 3 * colour_table_size;
                }
                gif_bytes = (gif_end - gif_data);
        } else {
                colour_table = gif->global_colour_table;
        }

        /* Ensure sufficient data remains */
        if (gif_bytes < 1) {
                return_value = GIF_INSUFFICIENT_FRAME_DATA;
                goto gif_decode_frame_exit;
        }

        /* check for an end marker */
        if (gif_data[0] == GIF_TRAILER) {
                return_value = GIF_OK;
                goto gif_decode_frame_exit;
        }

        /* Get the frame data */
        assert(gif->bitmap_callbacks.bitmap_get_buffer);
        frame_data = (void *)gif->bitmap_callbacks.bitmap_get_buffer(gif->frame_image);
        if (!frame_data) {
                return GIF_INSUFFICIENT_MEMORY;
        }

        /* If we are clearing the image we just clear, if not decode */
        if (!clear_image) {
                lzw_result res;
                const uint8_t *stack_base;
                const uint8_t *stack_pos;

                /* Ensure we have enough data for a 1-byte LZW code size +
                 * 1-byte gif trailer
                 */
                if (gif_bytes < 2) {
                        return_value = GIF_INSUFFICIENT_FRAME_DATA;
                        goto gif_decode_frame_exit;
                }

                /* If we only have a 1-byte LZW code size + 1-byte gif trailer,
                 * we're finished
                 */
                if ((gif_bytes == 2) && (gif_data[1] == GIF_TRAILER)) {
                        return_value = GIF_OK;
                        goto gif_decode_frame_exit;
                }

                /* If the previous frame's disposal method requires we restore
                 * the background colour or this is the first frame, clear
                 * the frame data
                 */
                if ((frame == 0) || (gif->decoded_frame == GIF_INVALID_FRAME)) {
                        memset((char*)frame_data,
                               GIF_TRANSPARENT_COLOUR,
                               gif->width * gif->height * sizeof(int));
                        gif->decoded_frame = frame;
                        /* The line below would fill the image with its
                         * background color, but because GIFs support
                         * transparency we likely wouldn't want to do that. */
                        /* memset((char*)frame_data, colour_table[gif->background_index], gif->width * gif->height * sizeof(int)); */
                } else if ((frame != 0) &&
                           (gif->frames[frame - 1].disposal_method == GIF_FRAME_CLEAR)) {
                        return_value = gif_internal_decode_frame(gif,
                                                                 (frame - 1),
                                                                 true);
                        if (return_value != GIF_OK) {
                                goto gif_decode_frame_exit;
                        }

                } else if ((frame != 0) &&
                           (gif->frames[frame - 1].disposal_method == GIF_FRAME_RESTORE)) {
                        /*
                         * If the previous frame's disposal method requires we
                         * restore the previous image, find the last image set
                         * to "do not dispose" and get that frame data
                         */
                        int last_undisposed_frame = frame - 2;
                        while ((last_undisposed_frame >= 0) &&
                               (gif->frames[last_undisposed_frame].disposal_method == GIF_FRAME_RESTORE)) {
                                last_undisposed_frame--;
                        }

                        /* If we don't find one, clear the frame data */
                        if (last_undisposed_frame == -1) {
                                /* see notes above on transparency
                                 * vs. background color
                                 */
                                memset((char*)frame_data,
                                       GIF_TRANSPARENT_COLOUR,
                                       gif->width * gif->height * sizeof(int));
                        } else {
                                return_value = gif_internal_decode_frame(gif, last_undisposed_frame, false);
                                if (return_value != GIF_OK) {
                                        goto gif_decode_frame_exit;
                                }
                                /* Get this frame's data */
                                assert(gif->bitmap_callbacks.bitmap_get_buffer);
                                frame_data = (void *)gif->bitmap_callbacks.bitmap_get_buffer(gif->frame_image);
                                if (!frame_data) {
                                        return GIF_INSUFFICIENT_MEMORY;
                                }
                        }
                }
                gif->decoded_frame = frame;
                gif->buffer_position = (gif_data - gif->gif_data) + 1;

                /* Initialise the LZW decoding */
                res = lzw_decode_init(gif->lzw_ctx, gif->gif_data,
                                gif->buffer_size, gif->buffer_position,
                                gif_data[0], &stack_base, &stack_pos);
                if (res != LZW_OK) {
                        return gif_error_from_lzw(res);
                }

                /* Decompress the data */
                for (y = 0; y < height; y++) {
                        if (interlace) {
                                decode_y = gif_interlaced_line(height, y) + offset_y;
                        } else {
                                decode_y = y + offset_y;
                        }
                        frame_scanline = frame_data + offset_x + (decode_y * gif->width);

                        /* Rather than decoding pixel by pixel, we try to burst
                         * out streams of data to remove the need for end-of
                         * data checks every pixel.
                         */
                        x = width;
                        while (x > 0) {
                                burst_bytes = (stack_pos - stack_base);
                                if (burst_bytes > 0) {
                                        if (burst_bytes > x) {
                                                burst_bytes = x;
                                        }
                                        x -= burst_bytes;
                                        while (burst_bytes-- > 0) {
                                                colour = *--stack_pos;
                                                if (((gif->frames[frame].transparency) &&
                                                     (colour != gif->frames[frame].transparency_index)) ||
                                                    (!gif->frames[frame].transparency)) {
                                                        *frame_scanline = colour_table[colour];
                                                }
                                                frame_scanline++;
                                        }
                                } else {
                                        res = lzw_decode(gif->lzw_ctx, &stack_pos);
                                        if (res != LZW_OK) {
                                                /* Unexpected end of frame, try to recover */
                                                if (res == LZW_OK_EOD) {
                                                        return_value = GIF_OK;
                                                } else {
                                                        return_value = gif_error_from_lzw(res);
                                                }
                                                goto gif_decode_frame_exit;
                                        }
                                }
                        }
                }
        } else {
                /* Clear our frame */
                if (gif->frames[frame].disposal_method == GIF_FRAME_CLEAR) {
                        for (y = 0; y < height; y++) {
                                frame_scanline = frame_data + offset_x + ((offset_y + y) * gif->width);
                                if (gif->frames[frame].transparency) {
                                        memset(frame_scanline,
                                               GIF_TRANSPARENT_COLOUR,
                                               width * 4);
                                } else {
                                        memset(frame_scanline,
                                               colour_table[gif->background_index],
                                               width * 4);
                                }
                        }
                }
        }
gif_decode_frame_exit:

        /* Check if we should test for optimisation */
        if (gif->frames[frame].virgin) {
                if (gif->bitmap_callbacks.bitmap_test_opaque) {
                        gif->frames[frame].opaque = gif->bitmap_callbacks.bitmap_test_opaque(gif->frame_image);
                } else {
                        gif->frames[frame].opaque = false;
                }
                gif->frames[frame].virgin = false;
        }

        if (gif->bitmap_callbacks.bitmap_set_opaque) {
                gif->bitmap_callbacks.bitmap_set_opaque(gif->frame_image, gif->frames[frame].opaque);
        }

        if (gif->bitmap_callbacks.bitmap_modified) {
                gif->bitmap_callbacks.bitmap_modified(gif->frame_image);
        }

        /* Restore the buffer position */
        gif->buffer_position = save_buffer_position;

        return return_value;
}

libnsgif: Fix null pointer deref on frameless GIF input

A crafted GIF file with no frame data could cause a null pointer
dereference leading to denial of service (crash). Reported by
@JieyongMa via huntr.dev.


ins_compl_stop(int c, int prev_mode, int retval)
{
    char_u	*ptr;
    int		want_cindent;

    // Get here when we have finished typing a sequence of ^N and
    // ^P or other completion characters in CTRL-X mode.  Free up
    // memory that was used, and make sure we can redo the insert.
    if (compl_curr_match != NULL || compl_leader != NULL || c == Ctrl_E)
    {
	// If any of the original typed text has been changed, eg when
	// ignorecase is set, we must add back-spaces to the redo
	// buffer.  We add as few as necessary to delete just the part
	// of the original text that has changed.
	// When using the longest match, edited the match or used
	// CTRL-E then don't use the current match.
	if (compl_curr_match != NULL && compl_used_match && c != Ctrl_E)
	    ptr = compl_curr_match->cp_str;
	else
	    ptr = NULL;
	ins_compl_fixRedoBufForLeader(ptr);
    }

    want_cindent = (get_can_cindent() && cindent_on());

    // When completing whole lines: fix indent for 'cindent'.
    // Otherwise, break line if it's too long.
    if (compl_cont_mode == CTRL_X_WHOLE_LINE)
    {
	// re-indent the current line
	if (want_cindent)
	{
	    do_c_expr_indent();
	    want_cindent = FALSE;	// don't do it again
	}
    }
    else
    {
	int prev_col = curwin->w_cursor.col;

	// put the cursor on the last char, for 'tw' formatting
	if (prev_col > 0)
	    dec_cursor();
	// only format when something was inserted
	if (!arrow_used && !ins_need_undo_get() && c != Ctrl_E)
	    insertchar(NUL, 0, -1);
	if (prev_col > 0
		&& ml_get_curline()[curwin->w_cursor.col] != NUL)
	    inc_cursor();
    }

    // If the popup menu is displayed pressing CTRL-Y means accepting
    // the selection without inserting anything.  When
    // compl_enter_selects is set the Enter key does the same.
    if ((c == Ctrl_Y || (compl_enter_selects
		    && (c == CAR || c == K_KENTER || c == NL)))
	    && pum_visible())
	retval = TRUE;

    // CTRL-E means completion is Ended, go back to the typed text.
    // but only do this, if the Popup is still visible
    if (c == Ctrl_E)
    {
	ins_compl_delete();
	if (compl_leader != NULL)
	    ins_bytes(compl_leader + get_compl_len());
	else if (compl_first_match != NULL)
	    ins_bytes(compl_orig_text + get_compl_len());
	retval = TRUE;
    }

    auto_format(FALSE, TRUE);

    // Trigger the CompleteDonePre event to give scripts a chance to
    // act upon the completion before clearing the info, and restore
    // ctrl_x_mode, so that complete_info() can be used.
    ctrl_x_mode = prev_mode;
    ins_apply_autocmds(EVENT_COMPLETEDONEPRE);

    ins_compl_free();
    compl_started = FALSE;
    compl_matches = 0;
    if (!shortmess(SHM_COMPLETIONMENU))
	msg_clr_cmdline();	// necessary for "noshowmode"
    ctrl_x_mode = CTRL_X_NORMAL;
    compl_enter_selects = FALSE;
    if (edit_submode != NULL)
    {
	edit_submode = NULL;
	showmode();
    }

#ifdef FEAT_CMDWIN
    if (c == Ctrl_C && cmdwin_type != 0)
	// Avoid the popup menu remains displayed when leaving the
	// command line window.
	update_screen(0);
#endif
    // Indent now if a key was typed that is in 'cinkeys'.
    if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0)))
	do_c_expr_indent();
    // Trigger the CompleteDone event to give scripts a chance to act
    // upon the end of completion.
    ins_apply_autocmds(EVENT_COMPLETEDONE);

    return retval;
}

patch 9.0.0020: with some completion reading past end of string

Problem:    With some completion reading past end of string.
Solution:   Check the length of the string.


PJ_DEF(int) pj_scan_get_char( pj_scanner *scanner )
{
    int chr = *scanner->curptr;

    if (!chr) {
	pj_scan_syntax_err(scanner);
	return 0;
    }

    ++scanner->curptr;

    if (PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && scanner->skip_ws) {
	pj_scan_skip_whitespace(scanner);
    }
    return chr;
}

Merge pull request from GHSA-7fw8-54cv-r7pm


static bool load_buffer(RBinFile *bf, void **bin_obj, RBuffer *buf, ut64 loadaddr, Sdb *sdb) {
	RBuffer *fbuf = r_buf_ref (buf);
	struct MACH0_(opts_t) opts;
	MACH0_(opts_set_default) (&opts, bf);
	struct MACH0_(obj_t) *main_mach0 = MACH0_(new_buf) (fbuf, &opts);
	if (!main_mach0) {
		return false;
	}

	RRebaseInfo *rebase_info = r_rebase_info_new_from_mach0 (fbuf, main_mach0);
	RKernelCacheObj *obj = NULL;

	RPrelinkRange *prelink_range = get_prelink_info_range_from_mach0 (main_mach0);
	if (!prelink_range) {
		goto beach;
	}

	obj = R_NEW0 (RKernelCacheObj);
	if (!obj) {
		R_FREE (prelink_range);
		goto beach;
	}

	RCFValueDict *prelink_info = NULL;
	if (main_mach0->hdr.filetype != MH_FILESET && prelink_range->range.size) {
		prelink_info = r_cf_value_dict_parse (fbuf, prelink_range->range.offset,
				prelink_range->range.size, R_CF_OPTION_SKIP_NSDATA);
		if (!prelink_info) {
			R_FREE (prelink_range);
			R_FREE (obj);
			goto beach;
		}
	}

	if (!pending_bin_files) {
		pending_bin_files = r_list_new ();
		if (!pending_bin_files) {
			R_FREE (prelink_range);
			R_FREE (obj);
			R_FREE (prelink_info);
			goto beach;
		}
	}

	obj->mach0 = main_mach0;
	obj->rebase_info = rebase_info;
	obj->prelink_info = prelink_info;
	obj->cache_buf = fbuf;
	obj->pa2va_exec = prelink_range->pa2va_exec;
	obj->pa2va_data = prelink_range->pa2va_data;

	R_FREE (prelink_range);

	*bin_obj = obj;

	r_list_push (pending_bin_files, bf);

	if (rebase_info || main_mach0->chained_starts) {
		RIO *io = bf->rbin->iob.io;
		swizzle_io_read (obj, io);
	}

	return true;

beach:
	r_buf_free (fbuf);
	obj->cache_buf = NULL;
	MACH0_(mach0_free) (main_mach0);
	return false;
}

Fix null deref in xnu.kernelcache ##crash

* Reported by @xshad3 via huntr.dev


ex_retab(exarg_T *eap)
{
    linenr_T	lnum;
    int		got_tab = FALSE;
    long	num_spaces = 0;
    long	num_tabs;
    long	len;
    long	col;
    long	vcol;
    long	start_col = 0;		// For start of white-space string
    long	start_vcol = 0;		// For start of white-space string
    long	old_len;
    char_u	*ptr;
    char_u	*new_line = (char_u *)1; // init to non-NULL
    int		did_undo;		// called u_save for current line
#ifdef FEAT_VARTABS
    int		*new_vts_array = NULL;
    char_u	*new_ts_str;		// string value of tab argument
#else
    int		temp;
    int		new_ts;
#endif
    int		save_list;
    linenr_T	first_line = 0;		// first changed line
    linenr_T	last_line = 0;		// last changed line

    save_list = curwin->w_p_list;
    curwin->w_p_list = 0;	    // don't want list mode here

#ifdef FEAT_VARTABS
    new_ts_str = eap->arg;
    if (tabstop_set(eap->arg, &new_vts_array) == FAIL)
	return;
    while (vim_isdigit(*(eap->arg)) || *(eap->arg) == ',')
	++(eap->arg);

    // This ensures that either new_vts_array and new_ts_str are freshly
    // allocated, or new_vts_array points to an existing array and new_ts_str
    // is null.
    if (new_vts_array == NULL)
    {
	new_vts_array = curbuf->b_p_vts_array;
	new_ts_str = NULL;
    }
    else
	new_ts_str = vim_strnsave(new_ts_str, eap->arg - new_ts_str);
#else
    ptr = eap->arg;
    new_ts = getdigits(&ptr);
    if (new_ts < 0 && *eap->arg == '-')
    {
	emsg(_(e_argument_must_be_positive));
	return;
    }
    if (new_ts < 0 || new_ts > TABSTOP_MAX)
    {
	semsg(_(e_invalid_argument_str), eap->arg);
	return;
    }
    if (new_ts == 0)
	new_ts = curbuf->b_p_ts;
#endif
    for (lnum = eap->line1; !got_int && lnum <= eap->line2; ++lnum)
    {
	ptr = ml_get(lnum);
	col = 0;
	vcol = 0;
	did_undo = FALSE;
	for (;;)
	{
	    if (VIM_ISWHITE(ptr[col]))
	    {
		if (!got_tab && num_spaces == 0)
		{
		    // First consecutive white-space
		    start_vcol = vcol;
		    start_col = col;
		}
		if (ptr[col] == ' ')
		    num_spaces++;
		else
		    got_tab = TRUE;
	    }
	    else
	    {
		if (got_tab || (eap->forceit && num_spaces > 1))
		{
		    // Retabulate this string of white-space

		    // len is virtual length of white string
		    len = num_spaces = vcol - start_vcol;
		    num_tabs = 0;
		    if (!curbuf->b_p_et)
		    {
#ifdef FEAT_VARTABS
			int t, s;

			tabstop_fromto(start_vcol, vcol,
					curbuf->b_p_ts, new_vts_array, &t, &s);
			num_tabs = t;
			num_spaces = s;
#else
			temp = new_ts - (start_vcol % new_ts);
			if (num_spaces >= temp)
			{
			    num_spaces -= temp;
			    num_tabs++;
			}
			num_tabs += num_spaces / new_ts;
			num_spaces -= (num_spaces / new_ts) * new_ts;
#endif
		    }
		    if (curbuf->b_p_et || got_tab ||
					(num_spaces + num_tabs < len))
		    {
			if (did_undo == FALSE)
			{
			    did_undo = TRUE;
			    if (u_save((linenr_T)(lnum - 1),
						(linenr_T)(lnum + 1)) == FAIL)
			    {
				new_line = NULL;	// flag out-of-memory
				break;
			    }
			}

			// len is actual number of white characters used
			len = num_spaces + num_tabs;
			old_len = (long)STRLEN(ptr);
			new_line = alloc(old_len - col + start_col + len + 1);
			if (new_line == NULL)
			    break;
			if (start_col > 0)
			    mch_memmove(new_line, ptr, (size_t)start_col);
			mch_memmove(new_line + start_col + len,
				      ptr + col, (size_t)(old_len - col + 1));
			ptr = new_line + start_col;
			for (col = 0; col < len; col++)
			    ptr[col] = (col < num_tabs) ? '\t' : ' ';
			if (ml_replace(lnum, new_line, FALSE) == OK)
			    // "new_line" may have been copied
			    new_line = curbuf->b_ml.ml_line_ptr;
			if (first_line == 0)
			    first_line = lnum;
			last_line = lnum;
			ptr = new_line;
			col = start_col + len;
		    }
		}
		got_tab = FALSE;
		num_spaces = 0;
	    }
	    if (ptr[col] == NUL)
		break;
	    vcol += chartabsize(ptr + col, (colnr_T)vcol);
	    if (has_mbyte)
		col += (*mb_ptr2len)(ptr + col);
	    else
		++col;
	}
	if (new_line == NULL)		    // out of memory
	    break;
	line_breakcheck();
    }
    if (got_int)
	emsg(_(e_interrupted));

#ifdef FEAT_VARTABS
    // If a single value was given then it can be considered equal to
    // either the value of 'tabstop' or the value of 'vartabstop'.
    if (tabstop_count(curbuf->b_p_vts_array) == 0
	&& tabstop_count(new_vts_array) == 1
	&& curbuf->b_p_ts == tabstop_first(new_vts_array))
	; // not changed
    else if (tabstop_count(curbuf->b_p_vts_array) > 0
        && tabstop_eq(curbuf->b_p_vts_array, new_vts_array))
	; // not changed
    else
	redraw_curbuf_later(NOT_VALID);
#else
    if (curbuf->b_p_ts != new_ts)
	redraw_curbuf_later(NOT_VALID);
#endif
    if (first_line != 0)
	changed_lines(first_line, 0, last_line + 1, 0L);

    curwin->w_p_list = save_list;	// restore 'list'

#ifdef FEAT_VARTABS
    if (new_ts_str != NULL)		// set the new tabstop
    {
	// If 'vartabstop' is in use or if the value given to retab has more
	// than one tabstop then update 'vartabstop'.
	int *old_vts_ary = curbuf->b_p_vts_array;

	if (tabstop_count(old_vts_ary) > 0 || tabstop_count(new_vts_array) > 1)
	{
	    set_string_option_direct((char_u *)"vts", -1, new_ts_str,
							OPT_FREE|OPT_LOCAL, 0);
	    curbuf->b_p_vts_array = new_vts_array;
	    vim_free(old_vts_ary);
	}
	else
	{
	    // 'vartabstop' wasn't in use and a single value was given to
	    // retab then update 'tabstop'.
	    curbuf->b_p_ts = tabstop_first(new_vts_array);
	    vim_free(new_vts_array);
	}
	vim_free(new_ts_str);
    }
#else
    curbuf->b_p_ts = new_ts;
#endif
    coladvance(curwin->w_curswant);

    u_clearline();
}

patch 8.2.4359: crash when repeatedly using :retab

Problem:    crash when repeatedly using :retab.
Solution:   Bail out when the line is getting too long.


check_limit(VALUE str, VALUE opt)
{
    StringValue(str);
    size_t slen = RSTRING_LEN(str);
    size_t limit = get_limit(opt);
    if (slen > limit) {
	rb_raise(rb_eArgError,
		 "string length (%"PRI_SIZE_PREFIX"u) exceeds the limit %"PRI_SIZE_PREFIX"u", slen, limit);
    }
}

`Date._<format>(nil)` should return an empty Hash

Fix: https://github.com/ruby/date/issues/39

This is how versions previous to 3.2.1 behaved and Active Support
currently rely on this behavior.

https://github.com/rails/rails/blob/90357af08048ef5076730505f6e7b14a81f33d0c/activesupport/lib/active_support/values/time_zone.rb#L383-L384

Any Rails application upgrading to date `3.2.1` might run into unexpected errors.


spell_move_to(
    win_T	*wp,
    int		dir,		// FORWARD or BACKWARD
    int		allwords,	// TRUE for "[s"/"]s", FALSE for "[S"/"]S"
    int		curline,
    hlf_T	*attrp)		// return: attributes of bad word or NULL
				// (only when "dir" is FORWARD)
{
    linenr_T	lnum;
    pos_T	found_pos;
    int		found_len = 0;
    char_u	*line;
    char_u	*p;
    char_u	*endp;
    hlf_T	attr;
    int		len;
#ifdef FEAT_SYN_HL
    int		has_syntax = syntax_present(wp);
#endif
    int		col;
    int		can_spell;
    char_u	*buf = NULL;
    int		buflen = 0;
    int		skip = 0;
    int		capcol = -1;
    int		found_one = FALSE;
    int		wrapped = FALSE;

    if (no_spell_checking(wp))
	return 0;

    /*
     * Start looking for bad word at the start of the line, because we can't
     * start halfway a word, we don't know where it starts or ends.
     *
     * When searching backwards, we continue in the line to find the last
     * bad word (in the cursor line: before the cursor).
     *
     * We concatenate the start of the next line, so that wrapped words work
     * (e.g. "et<line-break>cetera").  Doesn't work when searching backwards
     * though...
     */
    lnum = wp->w_cursor.lnum;
    CLEAR_POS(&found_pos);

    while (!got_int)
    {
	line = ml_get_buf(wp->w_buffer, lnum, FALSE);

	len = (int)STRLEN(line);
	if (buflen < len + MAXWLEN + 2)
	{
	    vim_free(buf);
	    buflen = len + MAXWLEN + 2;
	    buf = alloc(buflen);
	    if (buf == NULL)
		break;
	}

	// In first line check first word for Capital.
	if (lnum == 1)
	    capcol = 0;

	// For checking first word with a capital skip white space.
	if (capcol == 0)
	    capcol = getwhitecols(line);
	else if (curline && wp == curwin)
	{
	    // For spellbadword(): check if first word needs a capital.
	    col = getwhitecols(line);
	    if (check_need_cap(lnum, col))
		capcol = col;

	    // Need to get the line again, may have looked at the previous
	    // one.
	    line = ml_get_buf(wp->w_buffer, lnum, FALSE);
	}

	// Copy the line into "buf" and append the start of the next line if
	// possible.
	STRCPY(buf, line);
	if (lnum < wp->w_buffer->b_ml.ml_line_count)
	    spell_cat_line(buf + STRLEN(buf),
			  ml_get_buf(wp->w_buffer, lnum + 1, FALSE), MAXWLEN);

	p = buf + skip;
	endp = buf + len;
	while (p < endp)
	{
	    // When searching backward don't search after the cursor.  Unless
	    // we wrapped around the end of the buffer.
	    if (dir == BACKWARD
		    && lnum == wp->w_cursor.lnum
		    && !wrapped
		    && (colnr_T)(p - buf) >= wp->w_cursor.col)
		break;

	    // start of word
	    attr = HLF_COUNT;
	    len = spell_check(wp, p, &attr, &capcol, FALSE);

	    if (attr != HLF_COUNT)
	    {
		// We found a bad word.  Check the attribute.
		if (allwords || attr == HLF_SPB)
		{
		    // When searching forward only accept a bad word after
		    // the cursor.
		    if (dir == BACKWARD
			    || lnum != wp->w_cursor.lnum
			    || (wrapped
				|| (colnr_T)(curline ? p - buf + len
						     : p - buf)
						  > wp->w_cursor.col))
		    {
#ifdef FEAT_SYN_HL
			if (has_syntax)
			{
			    col = (int)(p - buf);
			    (void)syn_get_id(wp, lnum, (colnr_T)col,
						    FALSE, &can_spell, FALSE);
			    if (!can_spell)
				attr = HLF_COUNT;
			}
			else
#endif
			    can_spell = TRUE;

			if (can_spell)
			{
			    found_one = TRUE;
			    found_pos.lnum = lnum;
			    found_pos.col = (int)(p - buf);
			    found_pos.coladd = 0;
			    if (dir == FORWARD)
			    {
				// No need to search further.
				wp->w_cursor = found_pos;
				vim_free(buf);
				if (attrp != NULL)
				    *attrp = attr;
				return len;
			    }
			    else if (curline)
				// Insert mode completion: put cursor after
				// the bad word.
				found_pos.col += len;
			    found_len = len;
			}
		    }
		    else
			found_one = TRUE;
		}
	    }

	    // advance to character after the word
	    p += len;
	    capcol -= len;
	}

	if (dir == BACKWARD && found_pos.lnum != 0)
	{
	    // Use the last match in the line (before the cursor).
	    wp->w_cursor = found_pos;
	    vim_free(buf);
	    return found_len;
	}

	if (curline)
	    break;	// only check cursor line

	// If we are back at the starting line and searched it again there
	// is no match, give up.
	if (lnum == wp->w_cursor.lnum && wrapped)
	    break;

	// Advance to next line.
	if (dir == BACKWARD)
	{
	    if (lnum > 1)
		--lnum;
	    else if (!p_ws)
		break;	    // at first line and 'nowrapscan'
	    else
	    {
		// Wrap around to the end of the buffer.  May search the
		// starting line again and accept the last match.
		lnum = wp->w_buffer->b_ml.ml_line_count;
		wrapped = TRUE;
		if (!shortmess(SHM_SEARCH))
		    give_warning((char_u *)_(top_bot_msg), TRUE);
	    }
	    capcol = -1;
	}
	else
	{
	    if (lnum < wp->w_buffer->b_ml.ml_line_count)
		++lnum;
	    else if (!p_ws)
		break;	    // at first line and 'nowrapscan'
	    else
	    {
		// Wrap around to the start of the buffer.  May search the
		// starting line again and accept the first match.
		lnum = 1;
		wrapped = TRUE;
		if (!shortmess(SHM_SEARCH))
		    give_warning((char_u *)_(bot_top_msg), TRUE);
	    }

	    // If we are back at the starting line and there is no match then
	    // give up.
	    if (lnum == wp->w_cursor.lnum && !found_one)
		break;

	    // Skip the characters at the start of the next line that were
	    // included in a match crossing line boundaries.
	    if (attr == HLF_COUNT)
		skip = (int)(p - endp);
	    else
		skip = 0;

	    // Capcol skips over the inserted space.
	    --capcol;

	    // But after empty line check first word in next line
	    if (*skipwhite(line) == NUL)
		capcol = 0;
	}

	line_breakcheck();
    }

    vim_free(buf);
    return 0;
}

patch 8.2.5072: using uninitialized value and freed memory in spell command

Problem:    Using uninitialized value and freed memory in spell command.
Solution:   Initialize "attr".  Check for empty line early.