[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
lynx-dev Re: [PATCH 2.8.4dev.18] GridText.c cleanup
From: |
Ilya Zakharevich |
Subject: |
lynx-dev Re: [PATCH 2.8.4dev.18] GridText.c cleanup |
Date: |
Thu, 8 Mar 2001 02:33:14 -0500 |
User-agent: |
Mutt/1.2.5i |
On Sat, Mar 03, 2001 at 01:10:00AM -0500, Ilya Zakharevich wrote:
> On Sun, Feb 25, 2001 at 01:46:54AM -0500, Ilya Zakharevich wrote:
> > This patch does not add any new functionality. All I did was I went
> > through more than 1000 lines of extremely badly written obfuscated C code
> > worthy of a first year CS student...
>
> The patch in the current message is an addition to that patch of
> several days ago. It adds the following:
This part III of the patch removes the last significant obfuscation
from split_line(). It also starts to collect the fruits of the
cleanup. It removes a bug which lead to style change markup pointing
past end-of-string (might be benign).
It also removes a bug which lead to a significant memory overhead,
garish display, and possibly other side effect. The bug is caused by
off-by-one error in the removal-of-zero-length-markup logic. Due to
this bug, zero-length markup was never removed, which lead to
accumulation of style change entries, eventually to a buffer overflow.
At this moment lynx stylification engine would give up, resulting in
uncomprehensible ocean of colors on the display. To demonstrate, make
a select entry with more than 46 entries. [My auto-display-charset
logic added 2 new encodings to the table of Lynx, bringing the number
to 46 on the 'o'ption form. ;-]
Enjoy,
Ilya
--- ./src/GridText.c-as-sent2 Sun Feb 25 05:57:18 2001
+++ ./src/GridText.c Thu Mar 8 02:16:20 2001
@@ -155,17 +155,6 @@ typedef struct _stylechange {
} HTStyleChange;
#endif
-#define STYLES_ARE_OPPOSITE(p1,p2) \
- ((p1)->style == (p2)->style \
- && (((p1)->direction == STACK_OFF \
- && (p2)->direction == STACK_ON) \
- || ((p1)->direction == ABS_OFF \
- && (p2)->direction == ABS_ON) \
- || ((p1)->direction == STACK_ON \
- && (p2)->direction == STACK_OFF) \
- || ((p1)->direction == ABS_ON \
- && (p2)->direction == ABS_OFF)))
-
typedef struct _line {
struct _line *next;
struct _line *prev;
@@ -2469,7 +2458,8 @@ PRIVATE HTLine * insert_blanks_in_line A
#if defined(USE_COLOR_STYLE)
int istyle = 0;
#endif
- int added_chars = 0, shift = 0, head_processed = 1;
+ int added_chars = 0, shift = 0;
+ int head_processed;
HTLine * mod_line;
char *newdata, *s = line->data, *copied = line->data, *t;
@@ -2489,6 +2479,7 @@ PRIVATE HTLine * insert_blanks_in_line A
return NULL;
if (!prev_anchor)
prev_anchor = text->first_anchor;
+ head_processed = (prev_anchor && prev_anchor->line_num < line_number);
memcpy(mod_line, line, LINE_SIZE(1));
t = newdata = mod_line->data;
ip = 0;
@@ -2548,6 +2539,35 @@ PRIVATE HTLine * insert_blanks_in_line A
return mod_line;
}
+PRIVATE HTStyleChange * skip_matched_and_correct_offsets ARGS3(
+ HTStyleChange *, end,
+ HTStyleChange *, start,
+ unsigned, split_pos)
+{ /* Found an OFF change not part of an adjacent matched pair.
+ * Walk backward looking for the corresponding ON change.
+ * Move everything after split_pos to be at split_pos.
+ * This can only work correctly if all changes are correctly
+ * nested! If this fails, assume it is safer to leave whatever
+ * comes before the OFF on the previous line alone. */
+ int level = 0;
+ HTStyleChange *tmp = end;
+
+ for (; tmp >= start; tmp--) {
+ if (tmp->style == end->style) {
+ if (tmp->direction == STACK_OFF)
+ level--;
+ else if (tmp->direction == STACK_ON) {
+ if (++level == 0)
+ return tmp;
+ } else
+ return 0;
+ }
+ if (tmp->horizpos > split_pos)
+ tmp->horizpos = split_pos;
+ }
+ return 0;
+}
+
PRIVATE void split_line ARGS2(
HText *, text,
unsigned, split)
@@ -2790,87 +2810,61 @@ PRIVATE void split_line ARGS2(
to--;
from--;
}
- /* FROM may be invalid, otherwise it either an ON change at or
+ /* FROM may be invalid, otherwise it is either an ON change at or
before s_pre, or is an OFF change at or before s_post. */
+
scan = from;
at_end = from;
/* Now on the previous line we have a correctly nested but
possibly non-terminated sequence of style changes.
Terminate it, and duplicate unterminated changes at the
- beginning of the new line.
-
- SCAN always goes backwards, skipping ajacent matching
- ON/OFF pairs, and finding a matching ON change to any other
- OFF change. Anything else is an ON change which need to
- be terminated. AT_END may go backwards to cancel two opposite
- changes at end. */
- while (at_end >= previous->styles && to >= line->styles) {
- if (at_end > previous->styles
- && at_end->horizpos == at_end[-1].horizpos
- && STYLES_ARE_OPPOSITE(at_end, at_end - 1)) {
- /*
- * Discard pairs of ON/OFF for the same color style, but only
- * if they appear at the same position. - kw
- */
- at_end -= 2;
- if (scan > at_end)
- scan = at_end;
- } else if (scan >= previous->styles && scan->direction /* ON */
- && at_end - previous->styles + 1 < MAX_STYLES_ON_LINE) {
- /* Found an ON change which isn't followed by a
- * corresponding OFF. Append the missing OFF change at
- * the end, and add an ON change at the beginning of
- * the current line. - kw */
- to->horizpos = 0;
- to->direction = STACK_ON;
- to->style = scan->style;
- at_end++;
- at_end->style = to->style;
- at_end->direction = ABS_OFF;
- at_end->horizpos = previous->size;
- to--;
- scan--;
- } else if (scan > previous->styles &&
- STYLES_ARE_OPPOSITE(scan, scan-1)) {
- /* Skip pairs of adjacent ON/OFF or OFF/ON changes. */
- scan -= 2;
- } else if (scan >= previous->styles && !scan->direction) { /* OFF */
- /*
- * Found an OFF change not part of an adjacent matched pair.
- * Walk backward looking for the corresponding ON change.
- * If we find it, skip the ON/OFF and everything in between.
- * This can only work correctly if all changes are correctly
- * nested! If this fails, assume it is safer to leave whatever
- * comes before the OFF on the previous line alone. Setting
- * spare to 0 ensures that it won't be used in a following
- * iteration. - kw
- */
- int level=-1;
- int itmp;
- HTStyleChange *tmp = scan - 1;
-
- for (; tmp >= previous->styles; tmp--) {
- if (tmp->style == scan->style) {
- if (tmp->direction == STACK_OFF) {
- level--;
- } else if (tmp->direction == STACK_ON) {
- if (++level == 0)
- break;
- } else
- break;
- }
+ beginning of the new line. */
+ while (scan >= previous->styles && at_end >= previous->styles) {
+ /* The algorithm: scan back though the styles on the previous line.
+ a) If OFF, skip the matched group.
+ Report a bug on failure.
+ b) If ON, (try to) cancel the corresponding ON at at_end,
+ and the corresponding OFF at to;
+ If not, put the corresponding OFF at at_end, and copy to to;
+ */
+ if (scan->direction == STACK_OFF) {
+ scan = skip_matched_and_correct_offsets(scan, previous->styles,
+ s_pre);
+ if (!scan) {
+ CTRACE((tfp, "BUG: styles improperly nested.\n"));
+ break;
}
- if (level == 0)
- scan = tmp - 1;
- else
- scan = previous->styles - 1; /* Stop */
- } else /* Nothing applied, so we are done with the loop. - kw */
- break;
- }
- if (at_end >= previous->styles && at_end->direction) {
- CTRACE((tfp, "%s\n%s%s\n",
- "........... Too many character styles on line:",
- "........... ", previous->data));
+ } else if (scan->direction == STACK_ON) {
+ if ( at_end->direction == STACK_ON
+ && at_end->style == scan->style
+ && at_end->horizpos >= s_pre )
+ at_end--;
+ else if (at_end >= previous->styles + MAX_STYLES_ON_LINE - 1) {
+ CTRACE((tfp, "BUG: style overflow before split_line.\n"));
+ break;
+ } else {
+ at_end++;
+ at_end->direction = STACK_OFF;
+ at_end->style = scan->style;
+ at_end->horizpos = s_pre;
+ }
+ if ( to < line->styles + MAX_STYLES_ON_LINE - 1
+ && to[1].direction == STACK_OFF
+ && to[1].horizpos <= SpecialAttrChars
+ && to[1].style == scan->style )
+ to++;
+ else if (to >= line->styles) {
+ *to = *scan;
+ to->horizpos = SpecialAttrChars;
+ to--;
+ } else {
+ CTRACE((tfp, "BUG: style overflow after split_line.\n"));
+ break;
+ }
+ }
+ if (scan->horizpos > s_pre)
+ scan->horizpos = s_pre;
+ scan--;
}
line->numstyles = line->styles + MAX_STYLES_ON_LINE - 1 - to;
if (line->numstyles > 0 && line->numstyles < MAX_STYLES_ON_LINE) {
@@ -2881,7 +2875,7 @@ PRIVATE void split_line ARGS2(
} else if (line->numstyles == 0)
line->styles[0].horizpos = ~0; /* ?!!! */
previous->numstyles = at_end - previous->styles + 1;
- if (at_end < previous->styles)
+ if (previous->numstyles == 0)
previous->styles[0].horizpos = ~0; /* ?!!! */
}
#endif /*USE_COLOR_STYLE*/
@@ -4331,9 +4330,9 @@ PUBLIC void _internal_HTC ARGS3(HText *,
line = text->last_line;
if (line->numstyles > 0 && dir == 0 &&
- line->styles[line->numstyles].direction &&
- line->styles[line->numstyles].style == style &&
- (int) line->styles[line->numstyles].horizpos
+ line->styles[line->numstyles-1].direction &&
+ line->styles[line->numstyles-1].style == style &&
+ (int) line->styles[line->numstyles-1].horizpos
== (int)line->size - ctrl_chars_on_this_line) {
/*
* If this is an OFF change directly preceded by an
; To UNSUBSCRIBE: Send "unsubscribe lynx-dev" to address@hidden