HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env)
{
    char *p, *q, *r;
    int i, w, x, y, z, count, width;
    struct readbuffer *obuf = h_env->obuf;
    struct environment *envs = h_env->envs;
    Str tmp;
    int hseq;
    int cmd;
#ifdef ID_EXT
    char *id = NULL;
#endif				/* ID_EXT */

    cmd = tag->tagid;

    if (obuf->flag & RB_PRE) {
	switch (cmd) {
	case HTML_NOBR:
	case HTML_N_NOBR:
	case HTML_PRE_INT:
	case HTML_N_PRE_INT:
	    return 1;
	}
    }

    switch (cmd) {
    case HTML_B:
	obuf->in_bold++;
	if (obuf->in_bold > 1)
	    return 1;
	return 0;
    case HTML_N_B:
	if (obuf->in_bold == 1 && close_effect0(obuf, HTML_B))
	    obuf->in_bold = 0;
	if (obuf->in_bold > 0) {
	    obuf->in_bold--;
	    if (obuf->in_bold == 0)
		return 0;
	}
	return 1;
    case HTML_I:
	obuf->in_italic++;
	if (obuf->in_italic > 1)
	    return 1;
	return 0;
    case HTML_N_I:
	if (obuf->in_italic == 1 && close_effect0(obuf, HTML_I))
	    obuf->in_italic = 0;
	if (obuf->in_italic > 0) {
	    obuf->in_italic--;
	    if (obuf->in_italic == 0)
		return 0;
	}
	return 1;
    case HTML_U:
	obuf->in_under++;
	if (obuf->in_under > 1)
	    return 1;
	return 0;
    case HTML_N_U:
	if (obuf->in_under == 1 && close_effect0(obuf, HTML_U))
	    obuf->in_under = 0;
	if (obuf->in_under > 0) {
	    obuf->in_under--;
	    if (obuf->in_under == 0)
		return 0;
	}
	return 1;
    case HTML_EM:
	HTMLlineproc1("", h_env);
	return 1;
    case HTML_N_EM:
	HTMLlineproc1("", h_env);
	return 1;
    case HTML_STRONG:
	HTMLlineproc1("", h_env);
	return 1;
    case HTML_N_STRONG:
	HTMLlineproc1("", h_env);
	return 1;
    case HTML_Q:
	HTMLlineproc1("`", h_env);
	return 1;
    case HTML_N_Q:
	HTMLlineproc1("'", h_env);
	return 1;
    case HTML_P:
    case HTML_N_P:
	CLOSE_A;
	if (!(obuf->flag & RB_IGNORE_P)) {
	    flushline(h_env, obuf, envs[h_env->envc].indent, 1, h_env->limit);
	    do_blankline(h_env, obuf, envs[h_env->envc].indent, 0,
			 h_env->limit);
	}
	obuf->flag |= RB_IGNORE_P;
	if (cmd == HTML_P) {
	    set_alignment(obuf, tag);
	    obuf->flag |= RB_P;
	}
	return 1;
    case HTML_BR:
	flushline(h_env, obuf, envs[h_env->envc].indent, 1, h_env->limit);
	h_env->blank_lines = 0;
	return 1;
    case HTML_H:
	if (!(obuf->flag & (RB_PREMODE | RB_IGNORE_P))) {
	    flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	    do_blankline(h_env, obuf, envs[h_env->envc].indent, 0,
			 h_env->limit);
	}
	HTMLlineproc1("", h_env);
	set_alignment(obuf, tag);
	return 1;
    case HTML_N_H:
	HTMLlineproc1("", h_env);
	if (!(obuf->flag & RB_PREMODE)) {
	    flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	}
	do_blankline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	RB_RESTORE_FLAG(obuf);
	close_anchor(h_env, obuf);
	obuf->flag |= RB_IGNORE_P;
	return 1;
    case HTML_UL:
    case HTML_OL:
    case HTML_BLQ:
	CLOSE_A;
	if (!(obuf->flag & RB_IGNORE_P)) {
	    flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	    if (!(obuf->flag & RB_PREMODE) &&
		(h_env->envc == 0 || cmd == HTML_BLQ))
		do_blankline(h_env, obuf, envs[h_env->envc].indent, 0,
			     h_env->limit);
	}
	PUSH_ENV(cmd);
	if (cmd == HTML_UL || cmd == HTML_OL) {
	    if (parsedtag_get_value(tag, ATTR_START, &count)) {
		envs[h_env->envc].count = count - 1;
	    }
	}
	if (cmd == HTML_OL) {
	    envs[h_env->envc].type = '1';
	    if (parsedtag_get_value(tag, ATTR_TYPE, &p)) {
		envs[h_env->envc].type = (int)*p;
	    }
	}
	if (cmd == HTML_UL)
	    envs[h_env->envc].type = ul_type(tag, 0);
	flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	return 1;
    case HTML_N_UL:
    case HTML_N_OL:
    case HTML_N_DL:
    case HTML_N_BLQ:
	CLOSE_DT;
	CLOSE_A;
	if (h_env->envc > 0) {
	    flushline(h_env, obuf, envs[h_env->envc - 1].indent, 0,
		      h_env->limit);
	    POP_ENV;
	    if (!(obuf->flag & RB_PREMODE) &&
		(h_env->envc == 0 || cmd == HTML_N_DL || cmd == HTML_N_BLQ)) {
		do_blankline(h_env, obuf,
			     envs[h_env->envc].indent,
			     INDENT_INCR, h_env->limit);
		obuf->flag |= RB_IGNORE_P;
	    }
	}
	close_anchor(h_env, obuf);
	return 1;
    case HTML_DL:
	CLOSE_A;
	if (!(obuf->flag & RB_IGNORE_P)) {
	    flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	    if (!(obuf->flag & RB_PREMODE))
		do_blankline(h_env, obuf, envs[h_env->envc].indent, 0,
			     h_env->limit);
	}
	PUSH_ENV(cmd);
	if (parsedtag_exists(tag, ATTR_COMPACT))
	    envs[h_env->envc].env = HTML_DL_COMPACT;
	obuf->flag |= RB_IGNORE_P;
	return 1;
    case HTML_LI:
	CLOSE_A;
	CLOSE_DT;
	if (h_env->envc > 0) {
	    Str num;
	    flushline(h_env, obuf,
		      envs[h_env->envc - 1].indent, 0, h_env->limit);
	    envs[h_env->envc].count++;
	    if (parsedtag_get_value(tag, ATTR_VALUE, &p)) {
		count = atoi(p);
		if (count > 0)
		    envs[h_env->envc].count = count;
		else
		    envs[h_env->envc].count = 0;
	    }
	    switch (envs[h_env->envc].env) {
	    case HTML_UL:
		envs[h_env->envc].type = ul_type(tag, envs[h_env->envc].type);
		for (i = 0; i < INDENT_INCR - 3; i++)
		    push_charp(obuf, 1, NBSP, PC_ASCII);
		tmp = Strnew();
		switch (envs[h_env->envc].type) {
		case 'd':
		    push_symbol(tmp, UL_SYMBOL_DISC, symbol_width, 1);
		    break;
		case 'c':
		    push_symbol(tmp, UL_SYMBOL_CIRCLE, symbol_width, 1);
		    break;
		case 's':
		    push_symbol(tmp, UL_SYMBOL_SQUARE, symbol_width, 1);
		    break;
		default:
		    push_symbol(tmp,
				UL_SYMBOL((h_env->envc_real -
					   1) % MAX_UL_LEVEL), symbol_width,
				1);
		    break;
		}
		if (symbol_width == 1)
		    push_charp(obuf, 1, NBSP, PC_ASCII);
		push_str(obuf, symbol_width, tmp, PC_ASCII);
		push_charp(obuf, 1, NBSP, PC_ASCII);
		set_space_to_prevchar(obuf->prevchar);
		break;
	    case HTML_OL:
		if (parsedtag_get_value(tag, ATTR_TYPE, &p))
		    envs[h_env->envc].type = (int)*p;
		switch ((envs[h_env->envc].count > 0)? envs[h_env->envc].type: '1') {
		case 'i':
		    num = romanNumeral(envs[h_env->envc].count);
		    break;
		case 'I':
		    num = romanNumeral(envs[h_env->envc].count);
		    Strupper(num);
		    break;
		case 'a':
		    num = romanAlphabet(envs[h_env->envc].count);
		    break;
		case 'A':
		    num = romanAlphabet(envs[h_env->envc].count);
		    Strupper(num);
		    break;
		default:
		    num = Sprintf("%d", envs[h_env->envc].count);
		    break;
		}
		if (INDENT_INCR >= 4)
		    Strcat_charp(num, ". ");
		else
		    Strcat_char(num, '.');
		push_spaces(obuf, 1, INDENT_INCR - num->length);
		push_str(obuf, num->length, num, PC_ASCII);
		if (INDENT_INCR >= 4)
		    set_space_to_prevchar(obuf->prevchar);
		break;
	    default:
		push_spaces(obuf, 1, INDENT_INCR);
		break;
	    }
	}
	else {
	    flushline(h_env, obuf, 0, 0, h_env->limit);
	}
	obuf->flag |= RB_IGNORE_P;
	return 1;
    case HTML_DT:
	CLOSE_A;
	if (h_env->envc == 0 ||
	    (h_env->envc_real < h_env->nenv &&
	     envs[h_env->envc].env != HTML_DL &&
	     envs[h_env->envc].env != HTML_DL_COMPACT)) {
	    PUSH_ENV(HTML_DL);
	}
	if (h_env->envc > 0) {
	    flushline(h_env, obuf,
		      envs[h_env->envc - 1].indent, 0, h_env->limit);
	}
	if (!(obuf->flag & RB_IN_DT)) {
	    HTMLlineproc1("", h_env);
	    obuf->flag |= RB_IN_DT;
	}
	obuf->flag |= RB_IGNORE_P;
	return 1;
    case HTML_DD:
	CLOSE_A;
	CLOSE_DT;
	if (h_env->envc == 0 ||
	    (h_env->envc_real < h_env->nenv &&
	     envs[h_env->envc].env != HTML_DL &&
	     envs[h_env->envc].env != HTML_DL_COMPACT)) {
	    PUSH_ENV(HTML_DL);
	}
	if (envs[h_env->envc].env == HTML_DL_COMPACT) {
	    if (obuf->pos > envs[h_env->envc].indent)
		flushline(h_env, obuf, envs[h_env->envc].indent, 0,
			  h_env->limit);
	    else
		push_spaces(obuf, 1, envs[h_env->envc].indent - obuf->pos);
	}
	else
	    flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	/* obuf->flag |= RB_IGNORE_P; */
	return 1;
    case HTML_TITLE:
	close_anchor(h_env, obuf);
	process_title(tag);
	obuf->flag |= RB_TITLE;
	obuf->end_tag = HTML_N_TITLE;
	return 1;
    case HTML_N_TITLE:
	if (!(obuf->flag & RB_TITLE))
	    return 1;
	obuf->flag &= ~RB_TITLE;
	obuf->end_tag = 0;
	tmp = process_n_title(tag);
	if (tmp)
	    HTMLlineproc1(tmp->ptr, h_env);
	return 1;
    case HTML_TITLE_ALT:
	if (parsedtag_get_value(tag, ATTR_TITLE, &p))
	    h_env->title = html_unquote(p);
	return 0;
    case HTML_FRAMESET:
	PUSH_ENV(cmd);
	push_charp(obuf, 9, "--FRAME--", PC_ASCII);
	flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	return 0;
    case HTML_N_FRAMESET:
	if (h_env->envc > 0) {
	    POP_ENV;
	    flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	}
	return 0;
    case HTML_NOFRAMES:
	CLOSE_A;
	flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	obuf->flag |= (RB_NOFRAMES | RB_IGNORE_P);
	/* istr = str; */
	return 1;
    case HTML_N_NOFRAMES:
	CLOSE_A;
	flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	obuf->flag &= ~RB_NOFRAMES;
	return 1;
    case HTML_FRAME:
	q = r = NULL;
	parsedtag_get_value(tag, ATTR_SRC, &q);
	parsedtag_get_value(tag, ATTR_NAME, &r);
	if (q) {
	    q = html_quote(q);
	    push_tag(obuf, Sprintf("",
				   cur_hseq++, q)->ptr, HTML_A);
	    if (r)
		q = html_quote(r);
	    push_charp(obuf, get_strwidth(q), q, PC_ASCII);
	    push_tag(obuf, "", HTML_N_A);
	}
	flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	return 0;
    case HTML_HR:
	close_anchor(h_env, obuf);
	tmp = process_hr(tag, h_env->limit, envs[h_env->envc].indent);
	HTMLlineproc1(tmp->ptr, h_env);
	set_space_to_prevchar(obuf->prevchar);
	return 1;
    case HTML_PRE:
	x = parsedtag_exists(tag, ATTR_FOR_TABLE);
	CLOSE_A;
	if (!(obuf->flag & RB_IGNORE_P)) {
	    flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	    if (!x)
		do_blankline(h_env, obuf, envs[h_env->envc].indent, 0,
			     h_env->limit);
	}
	else
	    fillline(obuf, envs[h_env->envc].indent);
	obuf->flag |= (RB_PRE | RB_IGNORE_P);
	/* istr = str; */
	return 1;
    case HTML_N_PRE:
	flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	if (!(obuf->flag & RB_IGNORE_P)) {
	    do_blankline(h_env, obuf, envs[h_env->envc].indent, 0,
			 h_env->limit);
	    obuf->flag |= RB_IGNORE_P;
	    h_env->blank_lines++;
	}
	obuf->flag &= ~RB_PRE;
	close_anchor(h_env, obuf);
	return 1;
    case HTML_PRE_INT:
	i = obuf->line->length;
	append_tags(obuf);
	if (!(obuf->flag & RB_SPECIAL)) {
	    set_breakpoint(obuf, obuf->line->length - i);
	}
	obuf->flag |= RB_PRE_INT;
	return 0;
    case HTML_N_PRE_INT:
	push_tag(obuf, "</pre_int>", HTML_N_PRE_INT);
	obuf->flag &= ~RB_PRE_INT;
	if (!(obuf->flag & RB_SPECIAL) && obuf->pos > obuf->bp.pos) {
	    set_prevchar(obuf->prevchar, "", 0);
	    obuf->prev_ctype = PC_CTRL;
	}
	return 1;
    case HTML_NOBR:
	obuf->flag |= RB_NOBR;
	obuf->nobr_level++;
	return 0;
    case HTML_N_NOBR:
	if (obuf->nobr_level > 0)
	    obuf->nobr_level--;
	if (obuf->nobr_level == 0)
	    obuf->flag &= ~RB_NOBR;
	return 0;
    case HTML_PRE_PLAIN:
	CLOSE_A;
	if (!(obuf->flag & RB_IGNORE_P)) {
	    flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	    do_blankline(h_env, obuf, envs[h_env->envc].indent, 0,
			 h_env->limit);
	}
	obuf->flag |= (RB_PRE | RB_IGNORE_P);
	return 1;
    case HTML_N_PRE_PLAIN:
	CLOSE_A;
	if (!(obuf->flag & RB_IGNORE_P)) {
	    flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	    do_blankline(h_env, obuf, envs[h_env->envc].indent, 0,
			 h_env->limit);
	    obuf->flag |= RB_IGNORE_P;
	}
	obuf->flag &= ~RB_PRE;
	return 1;
    case HTML_LISTING:
    case HTML_XMP:
    case HTML_PLAINTEXT:
	CLOSE_A;
	if (!(obuf->flag & RB_IGNORE_P)) {
	    flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	    do_blankline(h_env, obuf, envs[h_env->envc].indent, 0,
			 h_env->limit);
	}
	obuf->flag |= (RB_PLAIN | RB_IGNORE_P);
	switch (cmd) {
	case HTML_LISTING:
	    obuf->end_tag = HTML_N_LISTING;
	    break;
	case HTML_XMP:
	    obuf->end_tag = HTML_N_XMP;
	    break;
	case HTML_PLAINTEXT:
	    obuf->end_tag = MAX_HTMLTAG;
	    break;
	}
	return 1;
    case HTML_N_LISTING:
    case HTML_N_XMP:
	CLOSE_A;
	if (!(obuf->flag & RB_IGNORE_P)) {
	    flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	    do_blankline(h_env, obuf, envs[h_env->envc].indent, 0,
			 h_env->limit);
	    obuf->flag |= RB_IGNORE_P;
	}
	obuf->flag &= ~RB_PLAIN;
	obuf->end_tag = 0;
	return 1;
    case HTML_SCRIPT:
	obuf->flag |= RB_SCRIPT;
	obuf->end_tag = HTML_N_SCRIPT;
	return 1;
    case HTML_STYLE:
	obuf->flag |= RB_STYLE;
	obuf->end_tag = HTML_N_STYLE;
	return 1;
    case HTML_N_SCRIPT:
	obuf->flag &= ~RB_SCRIPT;
	obuf->end_tag = 0;
	return 1;
    case HTML_N_STYLE:
	obuf->flag &= ~RB_STYLE;
	obuf->end_tag = 0;
	return 1;
    case HTML_A:
	if (obuf->anchor.url)
	    close_anchor(h_env, obuf);

	hseq = 0;

	if (parsedtag_get_value(tag, ATTR_HREF, &p))
	    obuf->anchor.url = Strnew_charp(p)->ptr;
	if (parsedtag_get_value(tag, ATTR_TARGET, &p))
	    obuf->anchor.target = Strnew_charp(p)->ptr;
	if (parsedtag_get_value(tag, ATTR_REFERER, &p))
	    obuf->anchor.referer = Strnew_charp(p)->ptr;
	if (parsedtag_get_value(tag, ATTR_TITLE, &p))
	    obuf->anchor.title = Strnew_charp(p)->ptr;
	if (parsedtag_get_value(tag, ATTR_ACCESSKEY, &p))
	    obuf->anchor.accesskey = (unsigned char)*p;
	if (parsedtag_get_value(tag, ATTR_HSEQ, &hseq))
	    obuf->anchor.hseq = hseq;

	if (hseq == 0 && obuf->anchor.url) {
	    obuf->anchor.hseq = cur_hseq;
	    tmp = process_anchor(tag, h_env->tagbuf->ptr);
	    push_tag(obuf, tmp->ptr, HTML_A);
	    if (displayLinkNumber)
		HTMLlineproc1(getLinkNumberStr(-1)->ptr, h_env);
	    return 1;
	}
	return 0;
    case HTML_N_A:
	close_anchor(h_env, obuf);
	return 1;
    case HTML_IMG:
	tmp = process_img(tag, h_env->limit);
	HTMLlineproc1(tmp->ptr, h_env);
	return 1;
    case HTML_IMG_ALT:
	if (parsedtag_get_value(tag, ATTR_SRC, &p))
	    obuf->img_alt = Strnew_charp(p);
#ifdef USE_IMAGE
	i = 0;
	if (parsedtag_get_value(tag, ATTR_TOP_MARGIN, &i)) {
	    if ((short)i > obuf->top_margin)
		obuf->top_margin = (short)i;
	}
	i = 0;
	if (parsedtag_get_value(tag, ATTR_BOTTOM_MARGIN, &i)) {
	    if ((short)i > obuf->bottom_margin)
		obuf->bottom_margin = (short)i;
	}
#endif
	return 0;
    case HTML_N_IMG_ALT:
	if (obuf->img_alt) {
	    if (!close_effect0(obuf, HTML_IMG_ALT))
		push_tag(obuf, "</img_alt>", HTML_N_IMG_ALT);
	    obuf->img_alt = NULL;
	}
	return 1;
    case HTML_INPUT_ALT:
	i = 0;
	if (parsedtag_get_value(tag, ATTR_TOP_MARGIN, &i)) {
	    if ((short)i > obuf->top_margin)
		obuf->top_margin = (short)i;
	}
	i = 0;
	if (parsedtag_get_value(tag, ATTR_BOTTOM_MARGIN, &i)) {
	    if ((short)i > obuf->bottom_margin)
		obuf->bottom_margin = (short)i;
	}
	if (parsedtag_get_value(tag, ATTR_HSEQ, &hseq)) {
	    obuf->input_alt.hseq = hseq;
	}
	if (parsedtag_get_value(tag, ATTR_FID, &i)) {
	    obuf->input_alt.fid = i;
	}
	if (parsedtag_get_value(tag, ATTR_TYPE, &p)) {
	    obuf->input_alt.type = Strnew_charp(p);
	}
	if (parsedtag_get_value(tag, ATTR_VALUE, &p)) {
	    obuf->input_alt.value = Strnew_charp(p);
	}
	if (parsedtag_get_value(tag, ATTR_NAME, &p)) {
	    obuf->input_alt.name = Strnew_charp(p);
	}
	obuf->input_alt.in = 1;
	return 0;
    case HTML_N_INPUT_ALT:
	if (obuf->input_alt.in) {
	    if (!close_effect0(obuf, HTML_INPUT_ALT))
		push_tag(obuf, "</input_alt>", HTML_N_INPUT_ALT);
	    obuf->input_alt.hseq = 0;
	    obuf->input_alt.fid = -1;
	    obuf->input_alt.in = 0;
	    obuf->input_alt.type = NULL;
	    obuf->input_alt.name = NULL;
	    obuf->input_alt.value = NULL;
	}
	return 1;
    case HTML_TABLE:
	close_anchor(h_env, obuf);
	obuf->table_level++;
	if (obuf->table_level >= MAX_TABLE)
	    break;
	w = BORDER_NONE;
	/* x: cellspacing, y: cellpadding */
	x = 2;
	y = 1;
	z = 0;
	width = 0;
	if (parsedtag_exists(tag, ATTR_BORDER)) {
	    if (parsedtag_get_value(tag, ATTR_BORDER, &w)) {
		if (w > 2)
		    w = BORDER_THICK;
		else if (w < 0) {	/* weird */
		    w = BORDER_THIN;
		}
	    }
	    else
		w = BORDER_THIN;
	}
	if (DisplayBorders && w == BORDER_NONE)
	    w = BORDER_THIN;
	if (parsedtag_get_value(tag, ATTR_WIDTH, &i)) {
	    if (obuf->table_level == 0)
		width = REAL_WIDTH(i, h_env->limit - envs[h_env->envc].indent);
	    else
		width = RELATIVE_WIDTH(i);
	}
	if (parsedtag_exists(tag, ATTR_HBORDER))
	    w = BORDER_NOWIN;
#define MAX_CELLSPACING 1000
#define MAX_CELLPADDING 1000
#define MAX_VSPACE 1000
	parsedtag_get_value(tag, ATTR_CELLSPACING, &x);
	parsedtag_get_value(tag, ATTR_CELLPADDING, &y);
	parsedtag_get_value(tag, ATTR_VSPACE, &z);
	if (x < 0)
	    x = 0;
	if (y < 0)
	    y = 0;
	if (z < 0)
	    z = 0;
	if (x > MAX_CELLSPACING)
	    x = MAX_CELLSPACING;
	if (y > MAX_CELLPADDING)
	    y = MAX_CELLPADDING;
	if (z > MAX_VSPACE)
	    z = MAX_VSPACE;
#ifdef ID_EXT
	parsedtag_get_value(tag, ATTR_ID, &id);
#endif				/* ID_EXT */
	tables[obuf->table_level] = begin_table(w, x, y, z);
#ifdef ID_EXT
	if (id != NULL)
	    tables[obuf->table_level]->id = Strnew_charp(id);
#endif				/* ID_EXT */
	table_mode[obuf->table_level].pre_mode = 0;
	table_mode[obuf->table_level].indent_level = 0;
	table_mode[obuf->table_level].nobr_level = 0;
	table_mode[obuf->table_level].caption = 0;
	table_mode[obuf->table_level].end_tag = 0;	/* HTML_UNKNOWN */
#ifndef TABLE_EXPAND
	tables[obuf->table_level]->total_width = width;
#else
	tables[obuf->table_level]->real_width = width;
	tables[obuf->table_level]->total_width = 0;
#endif
	return 1;
    case HTML_N_TABLE:
	/* should be processed in HTMLlineproc() */
	return 1;
    case HTML_CENTER:
	CLOSE_A;
	if (!(obuf->flag & (RB_PREMODE | RB_IGNORE_P)))
	    flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	RB_SAVE_FLAG(obuf);
	RB_SET_ALIGN(obuf, RB_CENTER);
	return 1;
    case HTML_N_CENTER:
	CLOSE_A;
	if (!(obuf->flag & RB_PREMODE))
	    flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	RB_RESTORE_FLAG(obuf);
	return 1;
    case HTML_DIV:
	CLOSE_A;
	if (!(obuf->flag & RB_IGNORE_P))
	    flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	set_alignment(obuf, tag);
	return 1;
    case HTML_N_DIV:
	CLOSE_A;
	flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	RB_RESTORE_FLAG(obuf);
	return 1;
    case HTML_DIV_INT:
	CLOSE_P;
	if (!(obuf->flag & RB_IGNORE_P))
	    flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	set_alignment(obuf, tag);
	return 1;
    case HTML_N_DIV_INT:
	CLOSE_P;
	flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	RB_RESTORE_FLAG(obuf);
	return 1;
    case HTML_FORM:
	CLOSE_A;
	if (!(obuf->flag & RB_IGNORE_P))
	    flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	tmp = process_form(tag);
	if (tmp)
	    HTMLlineproc1(tmp->ptr, h_env);
	return 1;
    case HTML_N_FORM:
	CLOSE_A;
	flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit);
	obuf->flag |= RB_IGNORE_P;
	process_n_form();
	return 1;
    case HTML_INPUT:
	close_anchor(h_env, obuf);
	tmp = process_input(tag);
       if (tmp)
           HTMLlineproc1(tmp->ptr, h_env);
       return 1;
    case HTML_BUTTON:
       tmp = process_button(tag);
       if (tmp)
           HTMLlineproc1(tmp->ptr, h_env);
       return 1;
    case HTML_N_BUTTON:
       tmp = process_n_button();
	if (tmp)
	    HTMLlineproc1(tmp->ptr, h_env);
	return 1;
    case HTML_SELECT:
	close_anchor(h_env, obuf);
	tmp = process_select(tag);
	if (tmp)
	    HTMLlineproc1(tmp->ptr, h_env);
	obuf->flag |= RB_INSELECT;
	obuf->end_tag = HTML_N_SELECT;
	return 1;
    case HTML_N_SELECT:
	obuf->flag &= ~RB_INSELECT;
	obuf->end_tag = 0;
	tmp = process_n_select();
	if (tmp)
	    HTMLlineproc1(tmp->ptr, h_env);
	return 1;
    case HTML_OPTION:
	/* nothing */
	return 1;
    case HTML_TEXTAREA:
	close_anchor(h_env, obuf);
	tmp = process_textarea(tag, h_env->limit);
	if (tmp)
	    HTMLlineproc1(tmp->ptr, h_env);
	obuf->flag |= RB_INTXTA;
	obuf->end_tag = HTML_N_TEXTAREA;
	return 1;
    case HTML_N_TEXTAREA:
	obuf->flag &= ~RB_INTXTA;
	obuf->end_tag = 0;
	tmp = process_n_textarea();
	if (tmp)
	    HTMLlineproc1(tmp->ptr, h_env);
	return 1;
    case HTML_ISINDEX:
	p = "";
	q = "!CURRENT_URL!";
	parsedtag_get_value(tag, ATTR_PROMPT, &p);
	parsedtag_get_value(tag, ATTR_ACTION, &q);
	tmp = Strnew_m_charp("<form method=get action=\"",
			     html_quote(q),
			     "\">",
			     html_quote(p),
			     "<input type=text name=\"\" accept></form>",
			     NULL);
	HTMLlineproc1(tmp->ptr, h_env);
	return 1;
    case HTML_META:
	p = q = r = NULL;
	parsedtag_get_value(tag, ATTR_HTTP_EQUIV, &p);
	parsedtag_get_value(tag, ATTR_CONTENT, &q);
#ifdef USE_M17N
	parsedtag_get_value(tag, ATTR_CHARSET, &r);
	if (r) {
	    /* <meta charset=""> */
	    SKIP_BLANKS(r);
	    meta_charset = wc_guess_charset(r, 0);
	}
	else
	if (p && q && !strcasecmp(p, "Content-Type") &&
	    (q = strcasestr(q, "charset")) != NULL) {
	    q += 7;
	    SKIP_BLANKS(q);
	    if (*q == '=') {
		q++;
		SKIP_BLANKS(q);
		meta_charset = wc_guess_charset(q, 0);
	    }
	}
	else
#endif
	if (p && q && !strcasecmp(p, "refresh")) {
	    int refresh_interval;
	    tmp = NULL;
	    refresh_interval = getMetaRefreshParam(q, &tmp);
	    if (tmp) {
		q = html_quote(tmp->ptr);
		tmp = Sprintf("Refresh (%d sec) %s",
			      refresh_interval, q, q);
	    }
	    else if (refresh_interval > 0)
		tmp = Sprintf("Refresh (%d sec)", refresh_interval);
	    if (tmp) {
		HTMLlineproc1(tmp->ptr, h_env);
		do_blankline(h_env, obuf, envs[h_env->envc].indent, 0,
			     h_env->limit);
		if (!is_redisplay &&
		    !((obuf->flag & RB_NOFRAMES) && RenderFrame)) {
		    tag->need_reconstruct = TRUE;
		    return 0;
		}
	    }
	}
	return 1;
    case HTML_BASE:
#if defined(USE_M17N) || defined(USE_IMAGE)
	p = NULL;
	if (parsedtag_get_value(tag, ATTR_HREF, &p)) {
	    cur_baseURL = New(ParsedURL);
	    parseURL(p, cur_baseURL, NULL);
	}
#endif
    case HTML_MAP:
    case HTML_N_MAP:
    case HTML_AREA:
	return 0;
    case HTML_DEL:
	switch (displayInsDel) {
	case DISPLAY_INS_DEL_SIMPLE:
	    obuf->flag |= RB_DEL;
	    break;
	case DISPLAY_INS_DEL_NORMAL:
	    HTMLlineproc1("[DEL:", h_env);
	    break;
	case DISPLAY_INS_DEL_FONTIFY:
	    obuf->in_strike++;
	    if (obuf->in_strike == 1) {
		push_tag(obuf, "<s>", HTML_S);
	    }
	    break;
	}
	return 1;
    case HTML_N_DEL:
	switch (displayInsDel) {
	case DISPLAY_INS_DEL_SIMPLE:
	    obuf->flag &= ~RB_DEL;
	    break;
	case DISPLAY_INS_DEL_NORMAL:
	    HTMLlineproc1(":DEL]", h_env);
	case DISPLAY_INS_DEL_FONTIFY:
	    if (obuf->in_strike == 0)
		return 1;
	    if (obuf->in_strike == 1 && close_effect0(obuf, HTML_S))
		obuf->in_strike = 0;
	    if (obuf->in_strike > 0) {
		obuf->in_strike--;
		if (obuf->in_strike == 0) {
		    push_tag(obuf, "</s>", HTML_N_S);
		}
	    }
	    break;
	}
	return 1;
    case HTML_S:
	switch (displayInsDel) {
	case DISPLAY_INS_DEL_SIMPLE:
	    obuf->flag |= RB_S;
	    break;
	case DISPLAY_INS_DEL_NORMAL:
	    HTMLlineproc1("[S:", h_env);
	    break;
	case DISPLAY_INS_DEL_FONTIFY:
	    obuf->in_strike++;
	    if (obuf->in_strike == 1) {
		push_tag(obuf, "<s>", HTML_S);
	    }
	    break;
	}
	return 1;
    case HTML_N_S:
	switch (displayInsDel) {
	case DISPLAY_INS_DEL_SIMPLE:
	    obuf->flag &= ~RB_S;
	    break;
	case DISPLAY_INS_DEL_NORMAL:
	    HTMLlineproc1(":S]", h_env);
	    break;
	case DISPLAY_INS_DEL_FONTIFY:
	    if (obuf->in_strike == 0)
		return 1;
	    if (obuf->in_strike == 1 && close_effect0(obuf, HTML_S))
		obuf->in_strike = 0;
	    if (obuf->in_strike > 0) {
		obuf->in_strike--;
		if (obuf->in_strike == 0) {
		    push_tag(obuf, "</s>", HTML_N_S);
		}
	    }
	}
	return 1;
    case HTML_INS:
	switch (displayInsDel) {
	case DISPLAY_INS_DEL_SIMPLE:
	    break;
	case DISPLAY_INS_DEL_NORMAL:
	    HTMLlineproc1("[INS:", h_env);
	    break;
	case DISPLAY_INS_DEL_FONTIFY:
	    obuf->in_ins++;
	    if (obuf->in_ins == 1) {
		push_tag(obuf, "", HTML_INS);
	    }
	    break;
	}
	return 1;
    case HTML_N_INS:
	switch (displayInsDel) {
	case DISPLAY_INS_DEL_SIMPLE:
	    break;
	case DISPLAY_INS_DEL_NORMAL:
	    HTMLlineproc1(":INS]", h_env);
	    break;
	case DISPLAY_INS_DEL_FONTIFY:
	    if (obuf->in_ins == 0)
		return 1;
	    if (obuf->in_ins == 1 && close_effect0(obuf, HTML_INS))
		obuf->in_ins = 0;
	    if (obuf->in_ins > 0) {
		obuf->in_ins--;
		if (obuf->in_ins == 0) {
		    push_tag(obuf, "", HTML_N_INS);
		}
	    }
	    break;
	}
	return 1;
    case HTML_SUP:
	if (!(obuf->flag & (RB_DEL | RB_S)))
	    HTMLlineproc1("^", h_env);
	return 1;
    case HTML_N_SUP:
	return 1;
    case HTML_SUB:
	if (!(obuf->flag & (RB_DEL | RB_S)))
	    HTMLlineproc1("[", h_env);
	return 1;
    case HTML_N_SUB:
	if (!(obuf->flag & (RB_DEL | RB_S)))
	    HTMLlineproc1("]", h_env);
	return 1;
    case HTML_FONT:
    case HTML_N_FONT:
    case HTML_NOP:
	return 1;
    case HTML_BGSOUND:
	if (view_unseenobject) {
	    if (parsedtag_get_value(tag, ATTR_SRC, &p)) {
		Str s;
		q = html_quote(p);
		s = Sprintf("bgsound(%s)", q, q);
		HTMLlineproc1(s->ptr, h_env);
	    }
	}
	return 1;
    case HTML_EMBED:
	if (view_unseenobject) {
	    if (parsedtag_get_value(tag, ATTR_SRC, &p)) {
		Str s;
		q = html_quote(p);
		s = Sprintf("embed(%s)", q, q);
		HTMLlineproc1(s->ptr, h_env);
	    }
	}
	return 1;
    case HTML_APPLET:
	if (view_unseenobject) {
	    if (parsedtag_get_value(tag, ATTR_ARCHIVE, &p)) {
		Str s;
		q = html_quote(p);
		s = Sprintf("applet archive(%s)", q, q);
		HTMLlineproc1(s->ptr, h_env);
	    }
	}
	return 1;
    case HTML_BODY:
	if (view_unseenobject) {
	    if (parsedtag_get_value(tag, ATTR_BACKGROUND, &p)) {
		Str s;
		q = html_quote(p);
		s = Sprintf("
", q, q);
		HTMLlineproc1(s->ptr, h_env);
	    }
	}
    case HTML_N_HEAD:
	if (obuf->flag & RB_TITLE)
	    HTMLlineproc1("</title>", h_env);
    case HTML_HEAD:
    case HTML_N_BODY:
	return 1;
    default:
	/* obuf->prevchar = '\0'; */
	return 0;
    }
    /* not reached */
    return 0;
}


to_char():  prevent accesses beyond the allocated buffer

Previously very long field masks for floats could access memory
beyond the existing buffer allocated to hold the result.

Reported by Andres Freund and Peter Geoghegan.	Backpatch to all
supported versions.

Security: CVE-2015-0241

NUM_numpart_to_char(NUMProc *Np, int id)
{
	int			end;

	if (IS_ROMAN(Np->Num))
		return;

	/* Note: in this elog() output not set '\0' in 'inout' */

#ifdef DEBUG_TO_FROM_CHAR

	/*
	 * Np->num_curr is number of current item in format-picture, it is not
	 * current position in inout!
	 */
	elog(DEBUG_elog_output,
		 "SIGN_WROTE: %d, CURRENT: %d, NUMBER_P: \"%s\", INOUT: \"%s\"",
		 Np->sign_wrote,
		 Np->num_curr,
		 Np->number_p,
		 Np->inout);
#endif
	Np->num_in = FALSE;

	/*
	 * Write sign if real number will write to output Note: IS_PREDEC_SPACE()
	 * handle "9.9" --> " .1"
	 */
	if (Np->sign_wrote == FALSE &&
		(Np->num_curr >= Np->out_pre_spaces || (IS_ZERO(Np->Num) && Np->Num->zero_start == Np->num_curr)) &&
		(IS_PREDEC_SPACE(Np) == FALSE || (Np->last_relevant && *Np->last_relevant == '.')))
	{
		if (IS_LSIGN(Np->Num))
		{
			if (Np->Num->lsign == NUM_LSIGN_PRE)
			{
				if (Np->sign == '-')
					strcpy(Np->inout_p, Np->L_negative_sign);
				else
					strcpy(Np->inout_p, Np->L_positive_sign);
				Np->inout_p += strlen(Np->inout_p);
				Np->sign_wrote = TRUE;
			}
		}
		else if (IS_BRACKET(Np->Num))
		{
			*Np->inout_p = Np->sign == '+' ? ' ' : '<';
			++Np->inout_p;
			Np->sign_wrote = TRUE;
		}
		else if (Np->sign == '+')
		{
			if (!IS_FILLMODE(Np->Num))
			{
				*Np->inout_p = ' ';		/* Write + */
				++Np->inout_p;
			}
			Np->sign_wrote = TRUE;
		}
		else if (Np->sign == '-')
		{						/* Write - */
			*Np->inout_p = '-';
			++Np->inout_p;
			Np->sign_wrote = TRUE;
		}
	}

	/*
	 * digits / FM / Zero / Dec. point
	 */
	if (id == NUM_9 || id == NUM_0 || id == NUM_D || id == NUM_DEC)
	{
		if (Np->num_curr < Np->out_pre_spaces &&
			(Np->Num->zero_start > Np->num_curr || !IS_ZERO(Np->Num)))
		{
			/*
			 * Write blank space
			 */
			if (!IS_FILLMODE(Np->Num))
			{
				*Np->inout_p = ' ';		/* Write ' ' */
				++Np->inout_p;
			}
		}
		else if (IS_ZERO(Np->Num) &&
				 Np->num_curr < Np->out_pre_spaces &&
				 Np->Num->zero_start <= Np->num_curr)
		{
			/*
			 * Write ZERO
			 */
			*Np->inout_p = '0'; /* Write '0' */
			++Np->inout_p;
			Np->num_in = TRUE;
		}
		else
		{
			/*
			 * Write Decimal point
			 */
			if (*Np->number_p == '.')
			{
				if (!Np->last_relevant || *Np->last_relevant != '.')
				{
					strcpy(Np->inout_p, Np->decimal);	/* Write DEC/D */
					Np->inout_p += strlen(Np->inout_p);
				}

				/*
				 * Ora 'n' -- FM9.9 --> 'n.'
				 */
				else if (IS_FILLMODE(Np->Num) &&
						 Np->last_relevant && *Np->last_relevant == '.')
				{
					strcpy(Np->inout_p, Np->decimal);	/* Write DEC/D */
					Np->inout_p += strlen(Np->inout_p);
				}
			}
			else
			{
				/*
				 * Write Digits
				 */
				if (Np->last_relevant && Np->number_p > Np->last_relevant &&
					id != NUM_0)
					;

				/*
				 * '0.1' -- 9.9 --> '  .1'
				 */
				else if (IS_PREDEC_SPACE(Np))
				{
					if (!IS_FILLMODE(Np->Num))
					{
						*Np->inout_p = ' ';
						++Np->inout_p;
					}

					/*
					 * '0' -- FM9.9 --> '0.'
					 */
					else if (Np->last_relevant && *Np->last_relevant == '.')
					{
						*Np->inout_p = '0';
						++Np->inout_p;
					}
				}
				else
				{
					*Np->inout_p = *Np->number_p;		/* Write DIGIT */
					++Np->inout_p;
					Np->num_in = TRUE;
				}
			}
			++Np->number_p;
		}

		end = Np->num_count + (Np->out_pre_spaces ? 1 : 0) + (IS_DECIMAL(Np->Num) ? 1 : 0);

		if (Np->last_relevant && Np->last_relevant == Np->number_p)
			end = Np->num_curr;

		if (Np->num_curr + 1 == end)
		{
			if (Np->sign_wrote == TRUE && IS_BRACKET(Np->Num))
			{
				*Np->inout_p = Np->sign == '+' ? ' ' : '>';
				++Np->inout_p;
			}
			else if (IS_LSIGN(Np->Num) && Np->Num->lsign == NUM_LSIGN_POST)
			{
				if (Np->sign == '-')
					strcpy(Np->inout_p, Np->L_negative_sign);
				else
					strcpy(Np->inout_p, Np->L_positive_sign);
				Np->inout_p += strlen(Np->inout_p);
			}
		}
	}

	++Np->num_curr;
}

The to_char function in PostgreSQL before 9.0.19, 9.1.x before 9.1.15, 9.2.x before 9.2.10, 9.3.x before 9.3.6, and 9.4.x before 9.4.1 allows remote authenticated users to cause a denial of service (crash) or possibly execute arbitrary code via a (1) large number of digits when processing a numeric formatting template, which triggers a buffer over-read, or (2) crafted timestamp formatting template, which triggers a buffer overflow.


NUM_numpart_to_char(NUMProc *Np, int id)
{
	int			end;

	if (IS_ROMAN(Np->Num))
		return;

	/* Note: in this elog() output not set '\0' in 'inout' */

#ifdef DEBUG_TO_FROM_CHAR

	/*
	 * Np->num_curr is number of current item in format-picture, it is not
	 * current position in inout!
	 */
	elog(DEBUG_elog_output,
		 "SIGN_WROTE: %d, CURRENT: %d, NUMBER_P: \"%s\", INOUT: \"%s\"",
		 Np->sign_wrote,
		 Np->num_curr,
		 Np->number_p,
		 Np->inout);
#endif
	Np->num_in = FALSE;

	/*
	 * Write sign if real number will write to output Note: IS_PREDEC_SPACE()
	 * handle "9.9" --> " .1"
	 */
	if (Np->sign_wrote == FALSE &&
		(Np->num_curr >= Np->out_pre_spaces || (IS_ZERO(Np->Num) && Np->Num->zero_start == Np->num_curr)) &&
		(IS_PREDEC_SPACE(Np) == FALSE || (Np->last_relevant && *Np->last_relevant == '.')))
	{
		if (IS_LSIGN(Np->Num))
		{
			if (Np->Num->lsign == NUM_LSIGN_PRE)
			{
				if (Np->sign == '-')
					strcpy(Np->inout_p, Np->L_negative_sign);
				else
					strcpy(Np->inout_p, Np->L_positive_sign);
				Np->inout_p += strlen(Np->inout_p);
				Np->sign_wrote = TRUE;
			}
		}
		else if (IS_BRACKET(Np->Num))
		{
			*Np->inout_p = Np->sign == '+' ? ' ' : '<';
			++Np->inout_p;
			Np->sign_wrote = TRUE;
		}
		else if (Np->sign == '+')
		{
			if (!IS_FILLMODE(Np->Num))
			{
				*Np->inout_p = ' ';		/* Write + */
				++Np->inout_p;
			}
			Np->sign_wrote = TRUE;
		}
		else if (Np->sign == '-')
		{						/* Write - */
			*Np->inout_p = '-';
			++Np->inout_p;
			Np->sign_wrote = TRUE;
		}
	}

	/*
	 * digits / FM / Zero / Dec. point
	 */
	if (id == NUM_9 || id == NUM_0 || id == NUM_D || id == NUM_DEC)
	{
		if (Np->num_curr < Np->out_pre_spaces &&
			(Np->Num->zero_start > Np->num_curr || !IS_ZERO(Np->Num)))
		{
			/*
			 * Write blank space
			 */
			if (!IS_FILLMODE(Np->Num))
			{
				*Np->inout_p = ' ';		/* Write ' ' */
				++Np->inout_p;
			}
		}
		else if (IS_ZERO(Np->Num) &&
				 Np->num_curr < Np->out_pre_spaces &&
				 Np->Num->zero_start <= Np->num_curr)
		{
			/*
			 * Write ZERO
			 */
			*Np->inout_p = '0'; /* Write '0' */
			++Np->inout_p;
			Np->num_in = TRUE;
		}
		else
		{
			/*
			 * Write Decimal point
			 */
			if (*Np->number_p == '.')
			{
				if (!Np->last_relevant || *Np->last_relevant != '.')
				{
					strcpy(Np->inout_p, Np->decimal);	/* Write DEC/D */
					Np->inout_p += strlen(Np->inout_p);
				}

				/*
				 * Ora 'n' -- FM9.9 --> 'n.'
				 */
				else if (IS_FILLMODE(Np->Num) &&
						 Np->last_relevant && *Np->last_relevant == '.')
				{
					strcpy(Np->inout_p, Np->decimal);	/* Write DEC/D */
					Np->inout_p += strlen(Np->inout_p);
				}
			}
			else
			{
				/*
				 * Write Digits
				 */
				if (Np->last_relevant && Np->number_p > Np->last_relevant &&
					id != NUM_0)
					;

				/*
				 * '0.1' -- 9.9 --> '  .1'
				 */
				else if (IS_PREDEC_SPACE(Np))
				{
					if (!IS_FILLMODE(Np->Num))
					{
						*Np->inout_p = ' ';
						++Np->inout_p;
					}

					/*
					 * '0' -- FM9.9 --> '0.'
					 */
					else if (Np->last_relevant && *Np->last_relevant == '.')
					{
						*Np->inout_p = '0';
						++Np->inout_p;
					}
				}
				else
				{
					*Np->inout_p = *Np->number_p;		/* Write DIGIT */
					++Np->inout_p;
					Np->num_in = TRUE;
				}
			}
			/* do no exceed string length */
			if (*Np->number_p)
				++Np->number_p;
		}

		end = Np->num_count + (Np->out_pre_spaces ? 1 : 0) + (IS_DECIMAL(Np->Num) ? 1 : 0);

		if (Np->last_relevant && Np->last_relevant == Np->number_p)
			end = Np->num_curr;

		if (Np->num_curr + 1 == end)
		{
			if (Np->sign_wrote == TRUE && IS_BRACKET(Np->Num))
			{
				*Np->inout_p = Np->sign == '+' ? ' ' : '>';
				++Np->inout_p;
			}
			else if (IS_LSIGN(Np->Num) && Np->Num->lsign == NUM_LSIGN_POST)
			{
				if (Np->sign == '-')
					strcpy(Np->inout_p, Np->L_negative_sign);
				else
					strcpy(Np->inout_p, Np->L_positive_sign);
				Np->inout_p += strlen(Np->inout_p);
			}
		}
	}

	++Np->num_curr;
}


rtl8xxxu: prevent leaking urb

In rtl8xxxu_submit_int_urb if usb_submit_urb fails the allocated urb
should be released.

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

static int rtl8xxxu_submit_int_urb(struct ieee80211_hw *hw)
{
	struct rtl8xxxu_priv *priv = hw->priv;
	struct urb *urb;
	u32 val32;
	int ret;

	urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!urb)
		return -ENOMEM;

	usb_fill_int_urb(urb, priv->udev, priv->pipe_interrupt,
			 priv->int_buf, USB_INTR_CONTENT_LENGTH,
			 rtl8xxxu_int_complete, priv, 1);
	usb_anchor_urb(urb, &priv->int_anchor);
	ret = usb_submit_urb(urb, GFP_KERNEL);
	if (ret) {
		usb_unanchor_urb(urb);
		goto error;
	}

	val32 = rtl8xxxu_read32(priv, REG_USB_HIMR);
	val32 |= USB_HIMR_CPWM;
	rtl8xxxu_write32(priv, REG_USB_HIMR, val32);

error:
	return ret;
}

A memory leak in the rtl8xxxu_submit_int_urb() function in drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c in the Linux kernel through 5.3.11 allows attackers to cause a denial of service (memory consumption) by triggering usb_submit_urb() failures, aka CID-a2cdd07488e6.


static int rtl8xxxu_submit_int_urb(struct ieee80211_hw *hw)
{
	struct rtl8xxxu_priv *priv = hw->priv;
	struct urb *urb;
	u32 val32;
	int ret;

	urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!urb)
		return -ENOMEM;

	usb_fill_int_urb(urb, priv->udev, priv->pipe_interrupt,
			 priv->int_buf, USB_INTR_CONTENT_LENGTH,
			 rtl8xxxu_int_complete, priv, 1);
	usb_anchor_urb(urb, &priv->int_anchor);
	ret = usb_submit_urb(urb, GFP_KERNEL);
	if (ret) {
		usb_unanchor_urb(urb);
		usb_free_urb(urb);
		goto error;
	}

	val32 = rtl8xxxu_read32(priv, REG_USB_HIMR);
	val32 |= USB_HIMR_CPWM;
	rtl8xxxu_write32(priv, REG_USB_HIMR, val32);

error:
	return ret;
}


static Image *ReadPCLImage(const ImageInfo *image_info,ExceptionInfo *exception)
{
#define CropBox  "CropBox"
#define DeviceCMYK  "DeviceCMYK"
#define MediaBox  "MediaBox"
#define RenderPCLText  "  Rendering PCL...  "

  char
    command[MaxTextExtent],
    *density,
    filename[MaxTextExtent],
    geometry[MaxTextExtent],
    *options,
    input_filename[MaxTextExtent];

  const DelegateInfo
    *delegate_info;

  Image
    *image,
    *next_image;

  ImageInfo
    *read_info;

  int
    c;

  MagickBooleanType
    cmyk,
    status;

  PointInfo
    delta;

  RectangleInfo
    bounding_box,
    page;

  register char
    *p;

  SegmentInfo
    bounds;

  size_t
    height,
    width;

  ssize_t
    count;

  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickCoreSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  /*
    Open image file.
  */
  image=AcquireImage(image_info);
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
  if (status == MagickFalse)
    {
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  status=AcquireUniqueSymbolicLink(image_info->filename,input_filename);
  if (status == MagickFalse)
    {
      ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
        image_info->filename);
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  /*
    Set the page density.
  */
  delta.x=DefaultResolution;
  delta.y=DefaultResolution;
  if ((image->x_resolution == 0.0) || (image->y_resolution == 0.0))
    {
      GeometryInfo
        geometry_info;

      MagickStatusType
        flags;

      flags=ParseGeometry(PSDensityGeometry,&geometry_info);
      image->x_resolution=geometry_info.rho;
      image->y_resolution=geometry_info.sigma;
      if ((flags & SigmaValue) == 0)
        image->y_resolution=image->x_resolution;
    }
  /*
    Determine page geometry from the PCL media box.
  */
  cmyk=image->colorspace == CMYKColorspace ? MagickTrue : MagickFalse;
  count=0;
  (void) memset(&bounding_box,0,sizeof(bounding_box));
  (void) memset(&bounds,0,sizeof(bounds));
  (void) memset(&page,0,sizeof(page));
  (void) memset(command,0,sizeof(command));
  p=command;
  for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
  {
    if (image_info->page != (char *) NULL)
      continue;
    /*
      Note PCL elements.
    */
    *p++=(char) c;
    if ((c != (int) '/') && (c != '\n') &&
        ((size_t) (p-command) < (MaxTextExtent-1)))
      continue;
    *p='\0';
    p=command;
    /*
      Is this a CMYK document?
    */
    if (LocaleNCompare(DeviceCMYK,command,strlen(DeviceCMYK)) == 0)
      cmyk=MagickTrue;
    if (LocaleNCompare(CropBox,command,strlen(CropBox)) == 0)
      {
        /*
          Note region defined by crop box.
        */
        count=(ssize_t) sscanf(command,"CropBox [%lf %lf %lf %lf",
          &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
        if (count != 4)
          count=(ssize_t) sscanf(command,"CropBox[%lf %lf %lf %lf",
            &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
      }
    if (LocaleNCompare(MediaBox,command,strlen(MediaBox)) == 0)
      {
        /*
          Note region defined by media box.
        */
        count=(ssize_t) sscanf(command,"MediaBox [%lf %lf %lf %lf",
          &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
        if (count != 4)
          count=(ssize_t) sscanf(command,"MediaBox[%lf %lf %lf %lf",
            &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
      }
    if (count != 4)
      continue;
    /*
      Set PCL render geometry.
    */
    width=(size_t) floor(bounds.x2-bounds.x1+0.5);
    height=(size_t) floor(bounds.y2-bounds.y1+0.5);
    if (width > page.width)
      page.width=width;
    if (height > page.height)
      page.height=height;
  }
  (void) CloseBlob(image);
  /*
    Render PCL with the GhostPCL delegate.
  */
  if ((page.width == 0) || (page.height == 0))
    (void) ParseAbsoluteGeometry(PSPageGeometry,&page);
  if (image_info->page != (char *) NULL)
    (void) ParseAbsoluteGeometry(image_info->page,&page);
  (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.20g",(double)
    page.width,(double) page.height);
  if (image_info->monochrome != MagickFalse)
    delegate_info=GetDelegateInfo("pcl:mono",(char *) NULL,exception);
  else
     if (cmyk != MagickFalse)
       delegate_info=GetDelegateInfo("pcl:cmyk",(char *) NULL,exception);
     else
       delegate_info=GetDelegateInfo("pcl:color",(char *) NULL,exception);
  if (delegate_info == (const DelegateInfo *) NULL)
    return((Image *) NULL);
  if ((page.width == 0) || (page.height == 0))
    (void) ParseAbsoluteGeometry(PSPageGeometry,&page);
  if (image_info->page != (char *) NULL)
    (void) ParseAbsoluteGeometry(image_info->page,&page);
  density=AcquireString("");
  options=AcquireString("");
  (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",
    image->x_resolution,image->y_resolution);
  page.width=(size_t) floor((double) page.width*image->x_resolution/delta.x+
    0.5);
  page.height=(size_t) floor((double) page.height*image->y_resolution/delta.y+
    0.5);
  (void) FormatLocaleString(options,MaxTextExtent,"-g%.20gx%.20g ",(double)
     page.width,(double) page.height);
  image=DestroyImage(image);
  read_info=CloneImageInfo(image_info);
  *read_info->magick='\0';
  if (read_info->number_scenes != 0)
    {
      if (read_info->number_scenes != 1)
        (void) FormatLocaleString(options,MaxTextExtent,"-dLastPage=%.20g",
          (double) (read_info->scene+read_info->number_scenes));
      else
        (void) FormatLocaleString(options,MaxTextExtent,
          "-dFirstPage=%.20g -dLastPage=%.20g",(double) read_info->scene+1,
          (double) (read_info->scene+read_info->number_scenes));
      read_info->number_scenes=0;
      if (read_info->scenes != (char *) NULL)
        *read_info->scenes='\0';
    }
  (void) CopyMagickString(filename,read_info->filename,MaxTextExtent);
  (void) AcquireUniqueFilename(read_info->filename);
  (void) FormatLocaleString(command,MaxTextExtent,
    GetDelegateCommands(delegate_info),
    read_info->antialias != MagickFalse ? 4 : 1,
    read_info->antialias != MagickFalse ? 4 : 1,density,options,
    read_info->filename,input_filename);
  options=DestroyString(options);
  density=DestroyString(density);
  status=ExternalDelegateCommand(MagickFalse,read_info->verbose,command,
    (char *) NULL,exception) != 0 ? MagickTrue : MagickFalse;
  image=ReadImage(read_info,exception);
  (void) RelinquishUniqueFileResource(read_info->filename);
  (void) RelinquishUniqueFileResource(input_filename);
  read_info=DestroyImageInfo(read_info);
  if (image == (Image *) NULL)
    ThrowReaderException(DelegateError,"PCLDelegateFailed");
  if (LocaleCompare(image->magick,"BMP") == 0)
    {
      Image
        *cmyk_image;

      cmyk_image=ConsolidateCMYKImages(image,&image->exception);
      if (cmyk_image != (Image *) NULL)
        {
          image=DestroyImageList(image);
          image=cmyk_image;
        }
    }
  do
  {
    (void) CopyMagickString(image->filename,filename,MaxTextExtent);
    image->page=page;
    next_image=SyncNextImageInList(image);
    if (next_image != (Image *) NULL)
      image=next_image;
  } while (next_image != (Image *) NULL);
  return(GetFirstImageInList(image));
}

ImageMagick 7.0.8-34 has a memory leak in the ReadPCLImage function in coders/pcl.c.


static Image *ReadPCLImage(const ImageInfo *image_info,ExceptionInfo *exception)
{
#define CropBox  "CropBox"
#define DeviceCMYK  "DeviceCMYK"
#define MediaBox  "MediaBox"
#define RenderPCLText  "  Rendering PCL...  "

  char
    command[MaxTextExtent],
    *density,
    filename[MaxTextExtent],
    geometry[MaxTextExtent],
    *options,
    input_filename[MaxTextExtent];

  const DelegateInfo
    *delegate_info;

  Image
    *image,
    *next_image;

  ImageInfo
    *read_info;

  int
    c;

  MagickBooleanType
    cmyk,
    status;

  PointInfo
    delta;

  RectangleInfo
    bounding_box,
    page;

  register char
    *p;

  SegmentInfo
    bounds;

  size_t
    height,
    width;

  ssize_t
    count;

  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickCoreSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  /*
    Open image file.
  */
  image=AcquireImage(image_info);
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
  if (status == MagickFalse)
    {
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  status=AcquireUniqueSymbolicLink(image_info->filename,input_filename);
  if (status == MagickFalse)
    {
      ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
        image_info->filename);
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  /*
    Set the page density.
  */
  delta.x=DefaultResolution;
  delta.y=DefaultResolution;
  if ((image->x_resolution == 0.0) || (image->y_resolution == 0.0))
    {
      GeometryInfo
        geometry_info;

      MagickStatusType
        flags;

      flags=ParseGeometry(PSDensityGeometry,&geometry_info);
      image->x_resolution=geometry_info.rho;
      image->y_resolution=geometry_info.sigma;
      if ((flags & SigmaValue) == 0)
        image->y_resolution=image->x_resolution;
    }
  /*
    Determine page geometry from the PCL media box.
  */
  cmyk=image->colorspace == CMYKColorspace ? MagickTrue : MagickFalse;
  count=0;
  (void) memset(&bounding_box,0,sizeof(bounding_box));
  (void) memset(&bounds,0,sizeof(bounds));
  (void) memset(&page,0,sizeof(page));
  (void) memset(command,0,sizeof(command));
  p=command;
  for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
  {
    if (image_info->page != (char *) NULL)
      continue;
    /*
      Note PCL elements.
    */
    *p++=(char) c;
    if ((c != (int) '/') && (c != '\n') &&
        ((size_t) (p-command) < (MaxTextExtent-1)))
      continue;
    *p='\0';
    p=command;
    /*
      Is this a CMYK document?
    */
    if (LocaleNCompare(DeviceCMYK,command,strlen(DeviceCMYK)) == 0)
      cmyk=MagickTrue;
    if (LocaleNCompare(CropBox,command,strlen(CropBox)) == 0)
      {
        /*
          Note region defined by crop box.
        */
        count=(ssize_t) sscanf(command,"CropBox [%lf %lf %lf %lf",
          &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
        if (count != 4)
          count=(ssize_t) sscanf(command,"CropBox[%lf %lf %lf %lf",
            &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
      }
    if (LocaleNCompare(MediaBox,command,strlen(MediaBox)) == 0)
      {
        /*
          Note region defined by media box.
        */
        count=(ssize_t) sscanf(command,"MediaBox [%lf %lf %lf %lf",
          &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
        if (count != 4)
          count=(ssize_t) sscanf(command,"MediaBox[%lf %lf %lf %lf",
            &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
      }
    if (count != 4)
      continue;
    /*
      Set PCL render geometry.
    */
    width=(size_t) floor(bounds.x2-bounds.x1+0.5);
    height=(size_t) floor(bounds.y2-bounds.y1+0.5);
    if (width > page.width)
      page.width=width;
    if (height > page.height)
      page.height=height;
  }
  (void) CloseBlob(image);
  /*
    Render PCL with the GhostPCL delegate.
  */
  if ((page.width == 0) || (page.height == 0))
    (void) ParseAbsoluteGeometry(PSPageGeometry,&page);
  if (image_info->page != (char *) NULL)
    (void) ParseAbsoluteGeometry(image_info->page,&page);
  (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.20g",(double)
    page.width,(double) page.height);
  if (image_info->monochrome != MagickFalse)
    delegate_info=GetDelegateInfo("pcl:mono",(char *) NULL,exception);
  else
     if (cmyk != MagickFalse)
       delegate_info=GetDelegateInfo("pcl:cmyk",(char *) NULL,exception);
     else
       delegate_info=GetDelegateInfo("pcl:color",(char *) NULL,exception);
  if (delegate_info == (const DelegateInfo *) NULL)
    {
      image=DestroyImage(image);
      return((Image *) NULL);
    }
  if ((page.width == 0) || (page.height == 0))
    (void) ParseAbsoluteGeometry(PSPageGeometry,&page);
  if (image_info->page != (char *) NULL)
    (void) ParseAbsoluteGeometry(image_info->page,&page);
  density=AcquireString("");
  options=AcquireString("");
  (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",
    image->x_resolution,image->y_resolution);
  page.width=(size_t) floor((double) page.width*image->x_resolution/delta.x+
    0.5);
  page.height=(size_t) floor((double) page.height*image->y_resolution/delta.y+
    0.5);
  (void) FormatLocaleString(options,MaxTextExtent,"-g%.20gx%.20g ",(double)
     page.width,(double) page.height);
  image=DestroyImage(image);
  read_info=CloneImageInfo(image_info);
  *read_info->magick='\0';
  if (read_info->number_scenes != 0)
    {
      if (read_info->number_scenes != 1)
        (void) FormatLocaleString(options,MaxTextExtent,"-dLastPage=%.20g",
          (double) (read_info->scene+read_info->number_scenes));
      else
        (void) FormatLocaleString(options,MaxTextExtent,
          "-dFirstPage=%.20g -dLastPage=%.20g",(double) read_info->scene+1,
          (double) (read_info->scene+read_info->number_scenes));
      read_info->number_scenes=0;
      if (read_info->scenes != (char *) NULL)
        *read_info->scenes='\0';
    }
  (void) CopyMagickString(filename,read_info->filename,MaxTextExtent);
  (void) AcquireUniqueFilename(read_info->filename);
  (void) FormatLocaleString(command,MaxTextExtent,
    GetDelegateCommands(delegate_info),
    read_info->antialias != MagickFalse ? 4 : 1,
    read_info->antialias != MagickFalse ? 4 : 1,density,options,
    read_info->filename,input_filename);
  options=DestroyString(options);
  density=DestroyString(density);
  status=ExternalDelegateCommand(MagickFalse,read_info->verbose,command,
    (char *) NULL,exception) != 0 ? MagickTrue : MagickFalse;
  image=ReadImage(read_info,exception);
  (void) RelinquishUniqueFileResource(read_info->filename);
  (void) RelinquishUniqueFileResource(input_filename);
  read_info=DestroyImageInfo(read_info);
  if (image == (Image *) NULL)
    ThrowReaderException(DelegateError,"PCLDelegateFailed");
  if (LocaleCompare(image->magick,"BMP") == 0)
    {
      Image
        *cmyk_image;

      cmyk_image=ConsolidateCMYKImages(image,&image->exception);
      if (cmyk_image != (Image *) NULL)
        {
          image=DestroyImageList(image);
          image=cmyk_image;
        }
    }
  do
  {
    (void) CopyMagickString(image->filename,filename,MaxTextExtent);
    image->page=page;
    next_image=SyncNextImageInList(image);
    if (next_image != (Image *) NULL)
      image=next_image;
  } while (next_image != (Image *) NULL);
  return(GetFirstImageInList(image));
}


parser: when flattening an eop, must preserve any data buffer

An eop may have a data buffer associated with it as part of the same
memory allocation. Therefore, we need to move "subexpr" up instead of
merging it into "eop".

This *partially* resolves BR 3392707, but that test case still
triggers a violation when using -gcv8.

Reported-by: Suhwan <prada960808@gmail.com>
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>

static int parse_eops(extop **result, bool critical, int elem)
{
    extop *eop = NULL, *prev = NULL;
    extop **tail = result;
    int sign;
    int i = tokval.t_type;
    int oper_num = 0;
    bool do_subexpr = false;

    *tail = NULL;

    /* End of string is obvious; ) ends a sub-expression list e.g. DUP */
    for (i = tokval.t_type; i != TOKEN_EOS; i = stdscan(NULL, &tokval)) {
        char endparen = ')';   /* Is a right paren the end of list? */

        if (i == ')')
            break;

        if (!eop) {
            nasm_new(eop);
            eop->dup  = 1;
            eop->elem = elem;
            do_subexpr = false;
        }
        sign = +1;

        /*
         * end_expression_next() here is to distinguish this from
         * a string used as part of an expression...
         */
        if (i == TOKEN_QMARK) {
            eop->type = EOT_DB_RESERVE;
        } else if (do_subexpr && i == '(') {
            extop *subexpr;

            stdscan(NULL, &tokval); /* Skip paren */
            if (parse_eops(&eop->val.subexpr, critical, eop->elem) < 0)
                goto fail;

            subexpr = eop->val.subexpr;
            if (!subexpr) {
                /* Subexpression is empty */
                eop->type = EOT_NOTHING;
            } else if (!subexpr->next) {
                /* Subexpression is a single element, flatten */
                eop->val   = subexpr->val;
                eop->type  = subexpr->type;
                eop->dup  *= subexpr->dup;
                nasm_free(subexpr);
            } else {
                eop->type = EOT_EXTOP;
            }

            /* We should have ended on a closing paren */
            if (tokval.t_type != ')') {
                nasm_nonfatal("expected `)' after subexpression, got `%s'",
                              i == TOKEN_EOS ?
                              "end of line" : tokval.t_charptr);
                goto fail;
            }
            endparen = 0;       /* This time the paren is not the end */
        } else if (i == '%') {
            /* %(expression_list) */
            do_subexpr = true;
            continue;
        } else if (i == TOKEN_SIZE) {
            /* Element size override */
            eop->elem = tokval.t_inttwo;
            do_subexpr = true;
            continue;
        } else if (i == TOKEN_STR && end_expression_next()) {
            eop->type            = EOT_DB_STRING;
            eop->val.string.data = tokval.t_charptr;
            eop->val.string.len  = tokval.t_inttwo;
        } else if (i == TOKEN_STRFUNC) {
            bool parens = false;
            const char *funcname = tokval.t_charptr;
            enum strfunc func = tokval.t_integer;

            i = stdscan(NULL, &tokval);
            if (i == '(') {
                parens = true;
                endparen = 0;
                i = stdscan(NULL, &tokval);
            }
            if (i != TOKEN_STR) {
                nasm_nonfatal("%s must be followed by a string constant",
                              funcname);
                eop->type = EOT_NOTHING;
            } else {
                eop->type = EOT_DB_STRING_FREE;
                eop->val.string.len =
                    string_transform(tokval.t_charptr, tokval.t_inttwo,
                                     &eop->val.string.data, func);
                if (eop->val.string.len == (size_t)-1) {
                    nasm_nonfatal("invalid input string to %s", funcname);
                    eop->type = EOT_NOTHING;
                }
            }
            if (parens && i && i != ')') {
                i = stdscan(NULL, &tokval);
                if (i != ')')
                    nasm_nonfatal("unterminated %s function", funcname);
            }
        } else if (i == '-' || i == '+') {
            char *save = stdscan_get();
            struct tokenval tmptok;

            sign = (i == '-') ? -1 : 1;
            if (stdscan(NULL, &tmptok) != TOKEN_FLOAT) {
                stdscan_set(save);
                goto is_expression;
            } else {
                tokval = tmptok;
                goto is_float;
            }
        } else if (i == TOKEN_FLOAT) {
            enum floatize fmt;
        is_float:
            eop->type = EOT_DB_FLOAT;

            fmt = float_deffmt(eop->elem);
            if (fmt == FLOAT_ERR) {
                nasm_nonfatal("no %d-bit floating-point format supported",
                              eop->elem << 3);
                eop->val.string.len = 0;
            } else if (eop->elem < 1) {
                nasm_nonfatal("floating-point constant"
                              " encountered in unknown instruction");
                /*
                 * fix suggested by Pedro Gimeno... original line was:
                 * eop->type = EOT_NOTHING;
                 */
                eop->val.string.len = 0;
            } else {
                eop->val.string.len = eop->elem;

                eop = nasm_realloc(eop, sizeof(extop) + eop->val.string.len);
                eop->val.string.data = (char *)eop + sizeof(extop);
                if (!float_const(tokval.t_charptr, sign,
                                 (uint8_t *)eop->val.string.data, fmt))
                    eop->val.string.len = 0;
            }
            if (!eop->val.string.len)
                eop->type = EOT_NOTHING;
        } else {
            /* anything else, assume it is an expression */
            expr *value;

        is_expression:
            value = evaluate(stdscan, NULL, &tokval, NULL,
                             critical, NULL);
            i = tokval.t_type;
            if (!value)                  /* Error in evaluator */
                goto fail;
            if (tokval.t_flag & TFLAG_DUP) {
                /* Expression followed by DUP */
                if (!is_simple(value)) {
                    nasm_nonfatal("non-constant argument supplied to DUP");
                    goto fail;
                } else if (value->value < 0) {
                    nasm_nonfatal("negative argument supplied to DUP");
                    goto fail;
                }
                eop->dup *= (size_t)value->value;
                do_subexpr = true;
                continue;
            }
            if (value_to_extop(value, eop, location.segment)) {
                nasm_nonfatal("expression is not simple or relocatable");
            }
        }

        if (eop->dup == 0 || eop->type == EOT_NOTHING) {
            nasm_free(eop);
        } else if (eop->type == EOT_DB_RESERVE &&
                   prev && prev->type == EOT_DB_RESERVE &&
                   prev->elem == eop->elem) {
            /* Coalesce multiple EOT_DB_RESERVE */
            prev->dup += eop->dup;
            nasm_free(eop);
        } else {
            /* Add this eop to the end of the chain */
            prev = eop;
            *tail = eop;
            tail = &eop->next;
        }

        oper_num++;
        eop = NULL;             /* Done with this operand */

        /*
         * We're about to call stdscan(), which will eat the
         * comma that we're currently sitting on between
         * arguments. However, we'd better check first that it
         * _is_ a comma.
         */
        if (i == TOKEN_EOS || i == endparen)	/* Already at end? */
            break;
        if (i != ',') {
            i = stdscan(NULL, &tokval);		/* eat the comma or final paren */
            if (i == TOKEN_EOS || i == ')')	/* got end of expression */
                break;
            if (i != ',') {
                nasm_nonfatal("comma expected after operand");
                goto fail;
            }
        }
    }

    return oper_num;

fail:
    if (eop)
        nasm_free(eop);
    return -1;
}

In Netwide Assembler (NASM) 2.15rc10, there is heap use-after-free in saa_wbytes in nasmlib/saa.c.


static int parse_eops(extop **result, bool critical, int elem)
{
    extop *eop = NULL, *prev = NULL;
    extop **tail = result;
    int sign;
    int i = tokval.t_type;
    int oper_num = 0;
    bool do_subexpr = false;

    *tail = NULL;

    /* End of string is obvious; ) ends a sub-expression list e.g. DUP */
    for (i = tokval.t_type; i != TOKEN_EOS; i = stdscan(NULL, &tokval)) {
        char endparen = ')';   /* Is a right paren the end of list? */

        if (i == ')')
            break;

        if (!eop) {
            nasm_new(eop);
            eop->dup  = 1;
            eop->elem = elem;
            do_subexpr = false;
        }
        sign = +1;

        /*
         * end_expression_next() here is to distinguish this from
         * a string used as part of an expression...
         */
        if (i == TOKEN_QMARK) {
            eop->type = EOT_DB_RESERVE;
        } else if (do_subexpr && i == '(') {
            extop *subexpr;

            stdscan(NULL, &tokval); /* Skip paren */
            if (parse_eops(&eop->val.subexpr, critical, eop->elem) < 0)
                goto fail;

            subexpr = eop->val.subexpr;
            if (!subexpr) {
                /* Subexpression is empty */
                eop->type = EOT_NOTHING;
            } else if (!subexpr->next) {
                /*
                 * Subexpression is a single element, flatten.
                 * Note that if subexpr has an allocated buffer associated
                 * with it, freeing it would free the buffer, too, so
                 * we need to move subexpr up, not eop down.
                 */
                if (!subexpr->elem)
                    subexpr->elem = eop->elem;
                subexpr->dup *= eop->dup;
                nasm_free(eop);
                eop = subexpr;
            } else {
                eop->type = EOT_EXTOP;
            }

            /* We should have ended on a closing paren */
            if (tokval.t_type != ')') {
                nasm_nonfatal("expected `)' after subexpression, got `%s'",
                              i == TOKEN_EOS ?
                              "end of line" : tokval.t_charptr);
                goto fail;
            }
            endparen = 0;       /* This time the paren is not the end */
        } else if (i == '%') {
            /* %(expression_list) */
            do_subexpr = true;
            continue;
        } else if (i == TOKEN_SIZE) {
            /* Element size override */
            eop->elem = tokval.t_inttwo;
            do_subexpr = true;
            continue;
        } else if (i == TOKEN_STR && end_expression_next()) {
            eop->type            = EOT_DB_STRING;
            eop->val.string.data = tokval.t_charptr;
            eop->val.string.len  = tokval.t_inttwo;
        } else if (i == TOKEN_STRFUNC) {
            bool parens = false;
            const char *funcname = tokval.t_charptr;
            enum strfunc func = tokval.t_integer;

            i = stdscan(NULL, &tokval);
            if (i == '(') {
                parens = true;
                endparen = 0;
                i = stdscan(NULL, &tokval);
            }
            if (i != TOKEN_STR) {
                nasm_nonfatal("%s must be followed by a string constant",
                              funcname);
                eop->type = EOT_NOTHING;
            } else {
                eop->type = EOT_DB_STRING_FREE;
                eop->val.string.len =
                    string_transform(tokval.t_charptr, tokval.t_inttwo,
                                     &eop->val.string.data, func);
                if (eop->val.string.len == (size_t)-1) {
                    nasm_nonfatal("invalid input string to %s", funcname);
                    eop->type = EOT_NOTHING;
                }
            }
            if (parens && i && i != ')') {
                i = stdscan(NULL, &tokval);
                if (i != ')')
                    nasm_nonfatal("unterminated %s function", funcname);
            }
        } else if (i == '-' || i == '+') {
            char *save = stdscan_get();
            struct tokenval tmptok;

            sign = (i == '-') ? -1 : 1;
            if (stdscan(NULL, &tmptok) != TOKEN_FLOAT) {
                stdscan_set(save);
                goto is_expression;
            } else {
                tokval = tmptok;
                goto is_float;
            }
        } else if (i == TOKEN_FLOAT) {
            enum floatize fmt;
        is_float:
            eop->type = EOT_DB_FLOAT;

            fmt = float_deffmt(eop->elem);
            if (fmt == FLOAT_ERR) {
                nasm_nonfatal("no %d-bit floating-point format supported",
                              eop->elem << 3);
                eop->val.string.len = 0;
            } else if (eop->elem < 1) {
                nasm_nonfatal("floating-point constant"
                              " encountered in unknown instruction");
                /*
                 * fix suggested by Pedro Gimeno... original line was:
                 * eop->type = EOT_NOTHING;
                 */
                eop->val.string.len = 0;
            } else {
                eop->val.string.len = eop->elem;

                eop = nasm_realloc(eop, sizeof(extop) + eop->val.string.len);
                eop->val.string.data = (char *)eop + sizeof(extop);
                if (!float_const(tokval.t_charptr, sign,
                                 (uint8_t *)eop->val.string.data, fmt))
                    eop->val.string.len = 0;
            }
            if (!eop->val.string.len)
                eop->type = EOT_NOTHING;
        } else {
            /* anything else, assume it is an expression */
            expr *value;

        is_expression:
            value = evaluate(stdscan, NULL, &tokval, NULL,
                             critical, NULL);
            i = tokval.t_type;
            if (!value)                  /* Error in evaluator */
                goto fail;
            if (tokval.t_flag & TFLAG_DUP) {
                /* Expression followed by DUP */
                if (!is_simple(value)) {
                    nasm_nonfatal("non-constant argument supplied to DUP");
                    goto fail;
                } else if (value->value < 0) {
                    nasm_nonfatal("negative argument supplied to DUP");
                    goto fail;
                }
                eop->dup *= (size_t)value->value;
                do_subexpr = true;
                continue;
            }
            if (value_to_extop(value, eop, location.segment)) {
                nasm_nonfatal("expression is not simple or relocatable");
            }
        }

        if (eop->dup == 0 || eop->type == EOT_NOTHING) {
            nasm_free(eop);
        } else if (eop->type == EOT_DB_RESERVE &&
                   prev && prev->type == EOT_DB_RESERVE &&
                   prev->elem == eop->elem) {
            /* Coalesce multiple EOT_DB_RESERVE */
            prev->dup += eop->dup;
            nasm_free(eop);
        } else {
            /* Add this eop to the end of the chain */
            prev = eop;
            *tail = eop;
            tail = &eop->next;
        }

        oper_num++;
        eop = NULL;             /* Done with this operand */

        /*
         * We're about to call stdscan(), which will eat the
         * comma that we're currently sitting on between
         * arguments. However, we'd better check first that it
         * _is_ a comma.
         */
        if (i == TOKEN_EOS || i == endparen)	/* Already at end? */
            break;
        if (i != ',') {
            i = stdscan(NULL, &tokval);		/* eat the comma or final paren */
            if (i == TOKEN_EOS || i == ')')	/* got end of expression */
                break;
            if (i != ',') {
                nasm_nonfatal("comma expected after operand");
                goto fail;
            }
        }
    }

    return oper_num;

fail:
    if (eop)
        nasm_free(eop);
    return -1;
}


static Image *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception)
{
#define SkipLinesOp  0x01
#define SetColorOp  0x02
#define SkipPixelsOp  0x03
#define ByteDataOp  0x05
#define RunDataOp  0x06
#define EOFOp  0x07
#define ThrowRLEException(exception,message) \
{ \
  if (colormap != (unsigned char *) NULL) \
    colormap=(unsigned char *) RelinquishMagickMemory(colormap); \
  if (pixel_info != (MemoryInfo *) NULL) \
    pixel_info=RelinquishVirtualMemory(pixel_info); \
  ThrowReaderException((exception),(message)); \
}

  char
    magick[12];

  Image
    *image;

  int
    opcode,
    operand,
    status;

  MagickStatusType
    flags;

  MagickSizeType
    number_pixels;

  MemoryInfo
    *pixel_info;

  Quantum
    index;

  register ssize_t
    x;

  register Quantum
    *q;

  register ssize_t
    i;

  register unsigned char
    *p;

  size_t
    bits_per_pixel,
    map_length,
    number_colormaps,
    number_planes,
    number_planes_filled,
    one,
    pixel_info_length;

  ssize_t
    count,
    offset,
    y;

  unsigned char
    background_color[256],
    *colormap,
    pixel,
    plane,
    *pixels;

  /*
    Open image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickCoreSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  image=AcquireImage(image_info,exception);
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
  if (status == MagickFalse)
    return(DestroyImageList(image));
  /*
    Determine if this a RLE file.
  */
  colormap=(unsigned char *) NULL;
  pixel_info=(MemoryInfo *) NULL;
  count=ReadBlob(image,2,(unsigned char *) magick);
  if ((count != 2) || (memcmp(magick,"\122\314",2) != 0))
    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
  do
  {
    /*
      Read image header.
    */
    image->page.x=(ssize_t) ReadBlobLSBShort(image);
    image->page.y=(ssize_t) ReadBlobLSBShort(image);
    image->columns=ReadBlobLSBShort(image);
    image->rows=ReadBlobLSBShort(image);
    flags=(MagickStatusType) ReadBlobByte(image);
    image->alpha_trait=flags & 0x04 ? BlendPixelTrait : UndefinedPixelTrait;
    number_planes=(size_t) ReadBlobByte(image);
    bits_per_pixel=(size_t) ReadBlobByte(image);
    number_colormaps=(size_t) ReadBlobByte(image);
    map_length=(unsigned char) ReadBlobByte(image);
    if (map_length >= 22)
      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    if (EOFBlob(image) != MagickFalse)
      ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
    one=1;
    map_length=one << map_length;
    if ((number_planes == 0) || (number_planes == 2) ||
        ((flags & 0x04) && (number_colormaps > 254)) || (bits_per_pixel != 8) ||
        (image->columns == 0))
      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    if (flags & 0x02)
      {
        /*
          No background color-- initialize to black.
        */
        for (i=0; i < (ssize_t) number_planes; i++)
          background_color[i]=0;
        (void) ReadBlobByte(image);
      }
    else
      {
        /*
          Initialize background color.
        */
        p=background_color;
        for (i=0; i < (ssize_t) number_planes; i++)
          *p++=(unsigned char) ReadBlobByte(image);
      }
    if ((number_planes & 0x01) == 0)
      (void) ReadBlobByte(image);
    if (EOFBlob(image) != MagickFalse)
      ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
    if (number_colormaps != 0)
      {
        /*
          Read image colormaps.
        */
        colormap=(unsigned char *) AcquireQuantumMemory(number_colormaps,
          3*map_length*sizeof(*colormap));
        if (colormap == (unsigned char *) NULL)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        p=colormap;
        for (i=0; i < (ssize_t) number_colormaps; i++)
          for (x=0; x < (ssize_t) map_length; x++)
          {
            *p++=(unsigned char) ScaleQuantumToChar(ScaleShortToQuantum(
              ReadBlobLSBShort(image)));
            if (EOFBlob(image) != MagickFalse)
              ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
          }
      }
    if ((flags & 0x08) != 0)
      {
        char
          *comment;

        size_t
          length;

        /*
          Read image comment.
        */
        length=ReadBlobLSBShort(image);
        if (length != 0)
          {
            comment=(char *) AcquireQuantumMemory(length,sizeof(*comment));
            if (comment == (char *) NULL)
              ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
            count=ReadBlob(image,length-1,(unsigned char *) comment);
            comment[length-1]='\0';
            (void) SetImageProperty(image,"comment",comment,exception);
            comment=DestroyString(comment);
            if ((length & 0x01) == 0)
              (void) ReadBlobByte(image);
          }
      }
    if (EOFBlob(image) != MagickFalse)
      ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
    if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
        break;
    status=SetImageExtent(image,image->columns,image->rows,exception);
    if (status == MagickFalse)
      return(DestroyImageList(image));
    /*
      Allocate RLE pixels.
    */
    if (image->alpha_trait != UndefinedPixelTrait)
      number_planes++;
    number_pixels=(MagickSizeType) image->columns*image->rows;
    number_planes_filled=(number_planes % 2 == 0) ? number_planes :
      number_planes+1;
    if ((number_pixels*number_planes_filled) != (size_t) (number_pixels*
         number_planes_filled))
      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    pixel_info=AcquireVirtualMemory(image->columns,image->rows*
      MagickMax(number_planes_filled,4)*sizeof(*pixels));
    if (pixel_info == (MemoryInfo *) NULL)
      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    pixel_info_length=image->columns*image->rows*
      MagickMax(number_planes_filled,4);
    pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
    (void) ResetMagickMemory(pixels,0,pixel_info_length);
    if ((flags & 0x01) && !(flags & 0x02))
      {
        ssize_t
          j;

        /*
          Set background color.
        */
        p=pixels;
        for (i=0; i < (ssize_t) number_pixels; i++)
        {
          if (image->alpha_trait == UndefinedPixelTrait)
            for (j=0; j < (ssize_t) number_planes; j++)
              *p++=background_color[j];
          else
            {
              for (j=0; j < (ssize_t) (number_planes-1); j++)
                *p++=background_color[j];
              *p++=0;  /* initialize matte channel */
            }
        }
      }
    /*
      Read runlength-encoded image.
    */
    plane=0;
    x=0;
    y=0;
    opcode=ReadBlobByte(image);
    if (opcode == EOF)
      ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
    do
    {
      switch (opcode & 0x3f)
      {
        case SkipLinesOp:
        {
          operand=ReadBlobByte(image);
          if (operand == EOF)
            ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
          if (opcode & 0x40)
            {
              operand=ReadBlobLSBSignedShort(image);
              if (operand == EOF)
                ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
            }
          x=0;
          y+=operand;
          break;
        }
        case SetColorOp:
        {
          operand=ReadBlobByte(image);
          if (operand == EOF)
            ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
          plane=(unsigned char) operand;
          if (plane == 255)
            plane=(unsigned char) (number_planes-1);
          x=0;
          break;
        }
        case SkipPixelsOp:
        {
          operand=ReadBlobByte(image);
          if (operand == EOF)
            ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
          if (opcode & 0x40)
            {
              operand=ReadBlobLSBSignedShort(image);
              if (operand == EOF)
                ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
            }
          x+=operand;
          break;
        }
        case ByteDataOp:
        {
          operand=ReadBlobByte(image);
          if (operand == EOF)
            ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
          if (opcode & 0x40)
            {
              operand=ReadBlobLSBSignedShort(image);
              if (operand == EOF)
                ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
            }
          offset=(ssize_t) (((image->rows-y-1)*image->columns*number_planes)+x*
            number_planes+plane);
          operand++;
          if ((offset < 0) ||
              ((offset+operand*number_planes) > (ssize_t) pixel_info_length))
            {
              if (number_colormaps != 0)
                colormap=(unsigned char *) RelinquishMagickMemory(colormap);
              pixel_info=RelinquishVirtualMemory(pixel_info);
              ThrowReaderException(CorruptImageError,"UnableToReadImageData");
            }
          p=pixels+offset;
          for (i=0; i < (ssize_t) operand; i++)
          {
            pixel=(unsigned char) ReadBlobByte(image);
            if ((y < (ssize_t) image->rows) &&
                ((x+i) < (ssize_t) image->columns))
              *p=pixel;
            p+=number_planes;
          }
          if (operand & 0x01)
            (void) ReadBlobByte(image);
          x+=operand;
          break;
        }
        case RunDataOp:
        {
          operand=ReadBlobByte(image);
          if (operand == EOF)
            ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
          if (opcode & 0x40)
            {
              operand=ReadBlobLSBSignedShort(image);
              if (operand == EOF)
                ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
            }
          pixel=(unsigned char) ReadBlobByte(image);
          (void) ReadBlobByte(image);
          offset=(ssize_t) (((image->rows-y-1)*image->columns*number_planes)+x*
            number_planes+plane);
          operand++;
          if ((offset < 0) ||
              ((offset+operand*number_planes) > (ssize_t) pixel_info_length))
            {
              if (number_colormaps != 0)
                colormap=(unsigned char *) RelinquishMagickMemory(colormap);
              pixel_info=RelinquishVirtualMemory(pixel_info);
              ThrowReaderException(CorruptImageError,"UnableToReadImageData");
            }
          p=pixels+offset;
          for (i=0; i < (ssize_t) operand; i++)
          {
            if ((y < (ssize_t) image->rows) &&
                ((x+i) < (ssize_t) image->columns))
              *p=pixel;
            p+=number_planes;
          }
          x+=operand;
          break;
        }
        default:
          break;
      }
      opcode=ReadBlobByte(image);
      if (opcode == EOF)
        ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
    } while (((opcode & 0x3f) != EOFOp) && (opcode != EOF));
    if (number_colormaps != 0)
      {
        MagickStatusType
          mask;

        /*
          Apply colormap affineation to image.
        */
        mask=(MagickStatusType) (map_length-1);
        p=pixels;
        x=(ssize_t) number_planes;
        if (number_colormaps == 1)
          for (i=0; i < (ssize_t) number_pixels; i++)
          {
            ValidateColormapValue(image,(ssize_t) (*p & mask),&index,exception);
            *p=colormap[(ssize_t) index];
            p++;
          }
        else
          if ((number_planes >= 3) && (number_colormaps >= 3))
            for (i=0; i < (ssize_t) number_pixels; i++)
              for (x=0; x < (ssize_t) number_planes; x++)
              {
                ValidateColormapValue(image,(ssize_t) (x*map_length+
                  (*p & mask)),&index,exception);
                *p=colormap[(ssize_t) index];
                p++;
              }
        if ((i < (ssize_t) number_pixels) || (x < (ssize_t) number_planes))
          {
            colormap=(unsigned char *) RelinquishMagickMemory(colormap);
            pixel_info=RelinquishVirtualMemory(pixel_info);
            ThrowReaderException(CorruptImageError,"UnableToReadImageData");
          }
      }
    /*
      Initialize image structure.
    */
    if (number_planes >= 3)
      {
        /*
          Convert raster image to DirectClass pixel packets.
        */
        p=pixels;
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            break;
          for (x=0; x < (ssize_t) image->columns; x++)
          {
            SetPixelRed(image,ScaleCharToQuantum(*p++),q);
            SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
            SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
            if (image->alpha_trait != UndefinedPixelTrait)
              SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
            q+=GetPixelChannels(image);
          }
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
            break;
          if (image->previous == (Image *) NULL)
            {
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                image->rows);
              if (status == MagickFalse)
                break;
            }
        }
      }
    else
      {
        /*
          Create colormap.
        */
        if (number_colormaps == 0)
          map_length=256;
        if (AcquireImageColormap(image,map_length,exception) == MagickFalse)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        p=colormap;
        if (number_colormaps == 1)
          for (i=0; i < (ssize_t) image->colors; i++)
          {
            /*
              Pseudocolor.
            */
            image->colormap[i].red=(MagickRealType)
              ScaleCharToQuantum((unsigned char) i);
            image->colormap[i].green=(MagickRealType)
              ScaleCharToQuantum((unsigned char) i);
            image->colormap[i].blue=(MagickRealType)
              ScaleCharToQuantum((unsigned char) i);
          }
        else
          if (number_colormaps > 1)
            for (i=0; i < (ssize_t) image->colors; i++)
            {
              image->colormap[i].red=(MagickRealType)
                ScaleCharToQuantum(*p);
              image->colormap[i].green=(MagickRealType)
                ScaleCharToQuantum(*(p+map_length));
              image->colormap[i].blue=(MagickRealType)
                ScaleCharToQuantum(*(p+map_length*2));
              p++;
            }
        p=pixels;
        if (image->alpha_trait == UndefinedPixelTrait)
          {
            /*
              Convert raster image to PseudoClass pixel packets.
            */
            for (y=0; y < (ssize_t) image->rows; y++)
            {
              q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
              if (q == (Quantum *) NULL)
                break;
              for (x=0; x < (ssize_t) image->columns; x++)
              {
                SetPixelIndex(image,(Quantum) *p++,q);
                q+=GetPixelChannels(image);
              }
              if (SyncAuthenticPixels(image,exception) == MagickFalse)
                break;
              if (image->previous == (Image *) NULL)
                {
                  status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
                    y,image->rows);
                  if (status == MagickFalse)
                    break;
                }
            }
            (void) SyncImage(image,exception);
          }
        else
          {
            /*
              Image has a matte channel-- promote to DirectClass.
            */
            for (y=0; y < (ssize_t) image->rows; y++)
            {
              q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
              if (q == (Quantum *) NULL)
                break;
              for (x=0; x < (ssize_t) image->columns; x++)
              {
                ValidateColormapValue(image,(ssize_t) *p++,&index,exception);
                SetPixelRed(image,ClampToQuantum(image->colormap[(ssize_t)
                  index].red),q);
                ValidateColormapValue(image,(ssize_t) *p++,&index,exception);
                SetPixelGreen(image,ClampToQuantum(image->colormap[(ssize_t)
                  index].green),q);
                ValidateColormapValue(image,(ssize_t) *p++,&index,exception);
                SetPixelBlue(image,ClampToQuantum(image->colormap[(ssize_t)
                  index].blue),q);
                SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
                q+=GetPixelChannels(image);
              }
              if (x < (ssize_t) image->columns)
                break;
              if (SyncAuthenticPixels(image,exception) == MagickFalse)
                break;
              if (image->previous == (Image *) NULL)
                {
                  status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
                    y,image->rows);
                  if (status == MagickFalse)
                    break;
                }
            }
            image->colormap=(PixelInfo *) RelinquishMagickMemory(
              image->colormap);
            image->storage_class=DirectClass;
            image->colors=0;
          }
      }
    if (number_colormaps != 0)
      colormap=(unsigned char *) RelinquishMagickMemory(colormap);
    pixel_info=RelinquishVirtualMemory(pixel_info);
    if (EOFBlob(image) != MagickFalse)
      {
        ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
          image->filename);
        break;
      }
    /*
      Proceed to next image.
    */
    if (image_info->number_scenes != 0)
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
        break;
    (void) ReadBlobByte(image);
    count=ReadBlob(image,2,(unsigned char *) magick);
    if ((count != 0) && (memcmp(magick,"\122\314",2) == 0))
      {
        /*
          Allocate next image structure.
        */
        AcquireNextImage(image_info,image,exception);
        if (GetNextImageInList(image) == (Image *) NULL)
          {
            image=DestroyImageList(image);
            return((Image *) NULL);
          }
        image=SyncNextImageInList(image);
        status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
          GetBlobSize(image));
        if (status == MagickFalse)
          break;
      }
  } while ((count != 0) && (memcmp(magick,"\122\314",2) == 0));
  (void) CloseBlob(image);
  return(GetFirstImageInList(image));
}

The ReadRLEImage function in coders\rle.c in ImageMagick 7.0.6-1 has a large loop vulnerability via a crafted rle file that triggers a huge number_pixels value.