aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTatsuya Kinoshita <tats@debian.org>2017-01-04 14:14:01 +0000
committerTatsuya Kinoshita <tats@debian.org>2017-01-04 14:24:43 +0000
commitcd921375d8de0619b79e2997e8969d3d7659316c (patch)
treef7968c0d99a4eddbe70d12e4aaeab46921ff702a
parentDebian release 0.5.3-33 (diff)
downloadw3m-cd921375d8de0619b79e2997e8969d3d7659316c.tar.gz
w3m-cd921375d8de0619b79e2997e8969d3d7659316c.zip
Update 020_debian.patch to v0.5.3+git20170102
- Fix multiple flaws with malformed text (buffer overflow, use after free, infinite loop)
-rw-r--r--debian/patches/020_debian.patch835
1 files changed, 694 insertions, 141 deletions
diff --git a/debian/patches/020_debian.patch b/debian/patches/020_debian.patch
index 900ef87..9d17218 100644
--- a/debian/patches/020_debian.patch
+++ b/debian/patches/020_debian.patch
@@ -60,10 +60,233 @@ index 8f443c1..5fb6581 100755
$input = "w3m-control: GOTO_LINK";
}
diff --git a/ChangeLog b/ChangeLog
-index 88358ef..90443aa 100644
+index 88358ef..5e77a18 100644
--- a/ChangeLog
+++ b/ChangeLog
-@@ -1,3 +1,1303 @@
+@@ -1,3 +1,1526 @@
++2017-01-02 Tatsuya Kinoshita <tats@debian.org>
++
++ * NEWS: Update NEWS.
++
++2016-12-24 Tatsuya Kinoshita <tats@debian.org>
++
++ * libwc/wtf.c:
++ Prevent overflow beyond the end of string in wtf_parse1().
++ Bug-Debian: https://github.com/tats/w3m/issues/68
++
++ * libwc/wtf.c:
++ Revert "Prevent overflow beyond the end of string in wtf_parse1()".
++ This reverts commit 998b6f91d4b02e8bf90b7744dfabc8cccdf9d4f9.
++ Bug-Debian: https://github.com/tats/w3m/issues/86
++ cf. http://emacs-w3m.namazu.org/ml/msg12505.html
++
++ * form.c:
++ Preserve one byte for end of string character in form_update_line().
++ Bug-Debian: https://github.com/tats/w3m/issues/68#issuecomment-266214643
++
++ * form.c:
++ Prevent invalid form_update_line() call in formUpdateBuffer().
++ Bug-Debian: https://github.com/tats/w3m/issues/82
++
++2016-12-20 Tatsuya Kinoshita <tats@debian.org>
++
++ * form.c:
++ Revert "Preserve one byte for end of string character in form_update_line()".
++ This reverts commit a4152aaaea5cb51c9018880a1295e498c38889bf.
++
++2016-12-18 Tatsuya Kinoshita <tats@debian.org>
++
++ * file.c: Prevent heap-use-after-free read in HTMLlineproc0().
++ Bug-Debian: https://github.com/tats/w3m/issues/81
++
++ * file.c: Prevent infinite loop in feed_textarea().
++ Bug-Debian: https://github.com/tats/w3m/issues/85
++
++ * form.c:
++ Revert "Prevent overflow beyond the end of string in form_update_line()".
++ This reverts commit 9ccaa1dd0dac6f9b35a649ae9901c225421500f6.
++
++ * form.c:
++ Revert "Prevent overflow beyond the end of string in form_update_line()".
++ This reverts commit e0efc127ff20cbeb931847af1c9b353056340fbd.
++
++2016-12-15 Tatsuya Kinoshita <tats@debian.org>
++
++ * libwc/wtf.c:
++ Prevent overflow beyond the end of string for wtf to wcs macros.
++ Bug-Debian: https://github.com/tats/w3m/issues/77
++
++ * libwc/wtf.c:
++ Revert "Prevent overflow beyond the end of string for wtf to wcs macros".
++ This reverts commit b4d27ba5ccffaa38e968c2bf3a8eeb9cd43928ff.
++
++ * file.c, libwc/wtf.c, libwc/wtf.h:
++ Prevent overflow beyond the end of string in caller of get_mclen().
++ Bug-Debian: https://github.com/tats/w3m/issues/59
++ Bug-Debian: https://github.com/tats/w3m/issues/73
++ Bug-Debian: https://github.com/tats/w3m/issues/74
++ Bug-Debian: https://github.com/tats/w3m/issues/75
++ Bug-Debian: https://github.com/tats/w3m/issues/76
++ Bug-Debian: https://github.com/tats/w3m/issues/78
++ Bug-Debian: https://github.com/tats/w3m/issues/79
++ Bug-Debian: https://github.com/tats/w3m/issues/80
++ Bug-Debian: https://github.com/tats/w3m/issues/83
++ Bug-Debian: https://github.com/tats/w3m/issues/84
++
++ * file.c:
++ Revert "Prevent overflow beyond the end of string in proc_mchar()".
++ This reverts commit 512ed467d12615f5ef40d0d28272e5662d8438ea.
++
++ * table.c:
++ Revert "Prevent overflow beyond the end of string in visible_length()".
++ This reverts commit a932f78a6d8c105036ffeedf01215c1f6a0e0b71.
++
++ * table.c:
++ Revert "Prevent overflow beyond the end of string in skip_space()".
++ This reverts commit e757b43bcf8c439c167f62b6d3317ee9518cabbf.
++
++ * table.c:
++ Revert "Prevent overflow beyond the end of string in visible_length_plain()".
++ This reverts commit f763b8ebf5441cb44d2c0234565fadd5eb1c87a5.
++
++ * form.c:
++ Revert "Prevent overflow beyond the end of string in textfieldrep()".
++ This reverts commit 77d8d8d6576d8afc0f6b2e09bb88c7ca9dba58bb.
++
++ * file.c:
++ Revert "Prevent overflow beyond the end of string in proc_mchar()".
++ This reverts commit e79d0ec2a00369a6af24007a1f2bb5e876e2c847.
++
++2016-12-13 Tatsuya Kinoshita <tats@debian.org>
++
++ * file.c: Prevent overflow beyond the end of string in proc_mchar().
++ Bug-Debian: https://github.com/tats/w3m/issues/80
++ cf. https://github.com/tats/w3m/issues/59
++
++ * form.c: Prevent overflow beyond the end of string in textfieldrep().
++ Bug-Debian: https://github.com/tats/w3m/issues/79
++
++ * form.c:
++ Preserve one byte for end of string character in form_update_line().
++ Bug-Debian: https://github.com/tats/w3m/issues/82
++ cf. https://github.com/tats/w3m/issues/68#issuecomment-266214643
++
++2016-12-10 Tatsuya Kinoshita <tats@debian.org>
++
++ * libwc/wtf.c: Prevent overflow beyond the end of string in wtf_len().
++ cf. https://github.com/tats/w3m/issues/57
++
++ * etc.c: Prevent negative array index for realColumn in calcPosition().
++ Bug-Debian: https://github.com/tats/w3m/issues/69
++
++ * libwc/wtf.c:
++ Prevent overflow beyond the end of string in wtf_parse1().
++ Bug-Debian: https://github.com/tats/w3m/issues/68
++
++ * Str.c: Prevent heap-buffer-overflow in Strnew_size().
++ Bug-Debian: https://github.com/tats/w3m/issues/72
++
++ * table.c:
++ Prevent overflow beyond the end of string in visible_length_plain().
++ Bug-Debian: https://github.com/tats/w3m/issues/76
++
++ * libwc/wtf.c:
++ Prevent overflow beyond the end of string for wtf to wcs macros.
++ Bug-Debian: https://github.com/tats/w3m/issues/77
++
++ * form.c:
++ Prevent overflow beyond the end of string in form_update_line().
++ Bug-Debian: https://github.com/tats/w3m/issues/78
++
++2016-12-08 Tatsuya Kinoshita <tats@debian.org>
++
++ * form.c:
++ Prevent overflow beyond the end of string in form_update_line().
++ Bug-Debian: https://github.com/tats/w3m/issues/75
++
++ * table.c: Prevent overflow beyond the end of string in skip_space().
++ Bug-Debian: https://github.com/tats/w3m/issues/74
++
++ * table.c:
++ Prevent overflow beyond the end of string in visible_length().
++ Bug-Debian: https://github.com/tats/w3m/issues/73
++
++ * libwc/wtf.c:
++ Prevent overflow beyond the end of string in wtf_strwidth().
++ Bug-Debian: https://github.com/tats/w3m/issues/57
++
++ * libwc/wtf.c:
++ Revert "Prevent overflow beyond the end of string in wtf_strwidth()".
++ This reverts commit d345c0950dfdef065b7377ecad0e4bc1d2601bf8.
++
++2016-12-07 Tatsuya Kinoshita <tats@debian.org>
++
++ * file.c: Prevent heap-use-after-free in HTMLlineproc0().
++ Bug-Debian: https://github.com/tats/w3m/issues/65
++
++ * file.c: Prevent negative values for offset and pos in push_link().
++ Bug-Debian: https://github.com/tats/w3m/issues/64
++
++ * file.c: Prevent overflow beyond the end of string in proc_mchar().
++ Bug-Debian: https://github.com/tats/w3m/issues/59
++
++ * libwc/wtf.c:
++ Prevent overflow beyond the end of string in wtf_strwidth().
++ Bug-Debian: https://github.com/tats/w3m/issues/57
++
++2016-12-05 Yixun Lan <dlan@gentoo.org>
++
++ * html.h: Explictily include <time.h> to avoid build err.
++ While disable ssl, we will got a undefine time_t err.
++ Bug-Gentoo: https://bugs.gentoo.org/show_bug.cgi?id=601498
++ Origin: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=8ee43ba4e036db70fff258f3edb2f0335385e93f
++
++2016-12-05 Tatsuya Kinoshita <tats@debian.org>
++
++ * table.c:
++ Prevent array index out of bounds for tridvalue in feed_table_tag().
++ Bug-Debian: https://github.com/tats/w3m/issues/71
++
++ * table.c: Prevent negative array index in set_integered_width().
++ Bug-Debian: https://github.com/tats/w3m/issues/70
++
++ * table.c:
++ Prevent array index out of bounds for tabattr in feed_table_tag().
++ Bug-Debian: https://github.com/tats/w3m/issues/60
++
++ * file.c: Prevent negative array index in process_textarea().
++ Bug-Debian: https://github.com/tats/w3m/issues/58
++
++ * file.c:
++ Prevent negative array index for marks in HTMLlineproc2body().
++ Bug-Debian: https://github.com/tats/w3m/issues/61
++
++ * file.c:
++ Prevent negative value of row for pushTable() in HTMLlineproc0().
++ Bug-Debian: https://github.com/tats/w3m/issues/67
++
++ * file.c: Prevent negative array index in getMetaRefreshParam().
++ Bug-Debian: https://github.com/tats/w3m/issues/63
++
++ * anchor.c:
++ Prevent negative array index for marks in shiftAnchorPosition().
++ Bug-Debian: https://github.com/tats/w3m/issues/62
++
++2016-11-27 Kuang-che Wu <kcwu@google.com>
++
++ * file.c: Fix uninitialized variable in process_img(). fix #44.
++ Bug-Debian: https://github.com/tats/w3m/issues/44
++ Origin: https://github.com/tats/w3m/pull/50/commits/41a607b06e4475101de59e5c623b9e5f76594a21
++
++ * menu.c: Fix menu buffer-overflow.
++ Origin: https://github.com/tats/w3m/pull/49/commits/7e1c05dd90cf42a308e854881ea3813aed000d2e
++
++2016-11-27 Tatsuya Kinoshita <tats@debian.org>
++
++ * ChangeLog, NEWS: Add CVE IDs.
++ cf. https://security-tracker.debian.org/tracker/source-package/w3m
++ http://www.openwall.com/lists/oss-security/2016/11/24/1
++
+2016-11-20 Tatsuya Kinoshita <tats@debian.org>
+
+ * NEWS: Update NEWS.
@@ -83,15 +306,15 @@ index 88358ef..90443aa 100644
+
+ * libwc/ucs.c, libwc/ucs.map:
+ Prevent global-buffer-overflow in wc_any_to_ucs().
-+ Bug-Debian: https://github.com/tats/w3m/issues/43
++ Bug-Debian: https://github.com/tats/w3m/issues/43 [CVE-2016-9632]
+
+2016-11-17 Tatsuya Kinoshita <tats@debian.org>
+
+ * url.c: Prevent global-buffer-overflow in parseURL().
-+ Bug-Debian: https://github.com/tats/w3m/issues/41
++ Bug-Debian: https://github.com/tats/w3m/issues/41 [CVE-2016-9630]
+
+ * file.c: Prevent deref null pointer in HTMLlineproc0().
-+ Bug-Debian: https://github.com/tats/w3m/issues/42
++ Bug-Debian: https://github.com/tats/w3m/issues/42 [CVE-2016-9631]
+
+2016-11-15 Tatsuya Kinoshita <tats@debian.org>
+
@@ -108,16 +331,16 @@ index 88358ef..90443aa 100644
+ This reverts commit f393faf55975a94217df479e1bd06ee4403c6958.
+
+ * anchor.c: Prevent deref null pointer in shiftAnchorPosition().
-+ Bug-Debian: https://github.com/tats/w3m/issues/40
++ Bug-Debian: https://github.com/tats/w3m/issues/40 [CVE-2016-9629]
+
+2016-11-14 Tatsuya Kinoshita <tats@debian.org>
+
+ * file.c: Prevent null pointer deref due to bad form id.
-+ Bug-Debian: https://github.com/tats/w3m/issues/39
++ Bug-Debian: https://github.com/tats/w3m/issues/39 [CVE-2016-9628]
+
+ * display.c, file.c, fm.h, symbol.c:
+ Prevent array index out of bounds for symbol.
-+ Bug-Debian: https://github.com/tats/w3m/issues/38
++ Bug-Debian: https://github.com/tats/w3m/issues/38 [CVE-2016-9627]
+
+2016-11-13 Tatsuya Kinoshita <tats@debian.org>
+
@@ -135,12 +358,12 @@ index 88358ef..90443aa 100644
+2016-11-09 Tatsuya Kinoshita <tats@debian.org>
+
+ * table.c: Check indent_level to prevent infinite recursion.
-+ Bug-Debian: https://github.com/tats/w3m/issues/37
++ Bug-Debian: https://github.com/tats/w3m/issues/37 [CVE-2016-9626]
+
+2016-11-07 Tatsuya Kinoshita <tats@debian.org>
+
+ * file.c: Prevent infinite recursion in HTMLlineproc0.
-+ Bug-Debian: https://github.com/tats/w3m/issues/36
++ Bug-Debian: https://github.com/tats/w3m/issues/36 [CVE-2016-9625]
+
+ * NEWS, w3m-doc/install.html.in:
+ Update documents for included w3mdict.cgi.
@@ -156,16 +379,16 @@ index 88358ef..90443aa 100644
+2016-11-07 Tatsuya Kinoshita <tats@debian.org>
+
+ * form.c: Prevent dereference near-null pointer in formUpdateBuffer.
-+ Bug-Debian: https://github.com/tats/w3m/issues/35
++ Bug-Debian: https://github.com/tats/w3m/issues/35 [CVE-2016-9624]
+
+ * file.c: Prevent crash after allocate string of negative size.
-+ Bug-Debian: https://github.com/tats/w3m/issues/33
++ Bug-Debian: https://github.com/tats/w3m/issues/33 [CVE-2016-9623]
+
+ * file.c: Prevent memory exhausted due to repeat appending "</table>".
-+ Bug-Debian: https://github.com/tats/w3m/issues/23
++ Bug-Debian: https://github.com/tats/w3m/issues/23 [CVE-2016-9633]
+
+ * file.c: Prevent null pointer dereference in HTMLlineproc2body.
-+ Bug-Debian: https://github.com/tats/w3m/issues/32
++ Bug-Debian: https://github.com/tats/w3m/issues/32 [CVE-2016-9622]
+
+2016-10-31 Tatsuya Kinoshita <tats@debian.org>
+
@@ -203,7 +426,7 @@ index 88358ef..90443aa 100644
+ Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=838952
+
+ * form.c: Prevent global-buffer-overflow write in formUpdateBuffer.
-+ Bug-Debian: https://github.com/tats/w3m/issues/29 [CVE-2016-9429]
++ Bug-Debian: https://github.com/tats/w3m/issues/29 [CVE-2016-9429] [CVE-2016-9621]
+
+ * form.c: Fix null pointer dereference in formUpdateBuffer.
+ Bug-Debian: https://github.com/tats/w3m/issues/28 [CVE-2016-9443]
@@ -1419,15 +1642,25 @@ index 7d692f9..453072d 100644
do \
(cd $$dir && $(MAKE) $(MAKE_ARGS) uninstall); \
diff --git a/NEWS b/NEWS
-index 66e309d..b80e8ed 100644
+index 66e309d..d8a99d3 100644
--- a/NEWS
+++ b/NEWS
-@@ -1,3 +1,55 @@
+@@ -1,3 +1,65 @@
++Debian's w3m 0.5.3+git20170102
++
++* bug fixes
++ - fix multiple flaws with malformed text
++ (buffer overflow, use after free, infinite loop)
++ - fix uninitialized variable when not USE_IMAGE
++
+Debian's w3m 0.5.3+git20161120
+
+* bug fixes
+ - fix multiple flaws with malformed text
+ (stack overflow, buffer overflow, null deref, out of memory)
++ [CVE-2016-9622], [CVE-2016-9623], [CVE-2016-9624], [CVE-2016-9625],
++ [CVE-2016-9626], [CVE-2016-9627], [CVE-2016-9628], [CVE-2016-9629],
++ [CVE-2016-9630], [CVE-2016-9631], [CVE-2016-9632], [CVE-2016-9633]
+ - fix stack overflow with nested table and textarea [CVE-2016-9439]
+ - fix suspend (^Z) behavior
+
@@ -1452,7 +1685,7 @@ index 66e309d..b80e8ed 100644
+ [CVE-2016-9426], [CVE-2016-9428], [CVE-2016-9429], [CVE-2016-9430],
+ [CVE-2016-9431], [CVE-2016-9432], [CVE-2016-9433], [CVE-2016-9434],
+ [CVE-2016-9435], [CVE-2016-9436], [CVE-2016-9437], [CVE-2016-9438],
-+ [CVE-2016-9440], [CVE-2016-9441], [CVE-2016-9443]
++ [CVE-2016-9440], [CVE-2016-9441], [CVE-2016-9443], [CVE-2016-9621]
+ - fix potential heap buffer corruption due to Strgrow [CVE-2016-9442]
+ - disable SSLv2 and SSLv3 by default [CVE-2014-3566]
+ - set ssl_verify_server to 1 by default
@@ -1493,10 +1726,19 @@ index 8778d80..765c996 100644
If you can read Japanese, see doc-jp/*.
If you can read both, read both and correct English. :-)
diff --git a/Str.c b/Str.c
-index e5a0982..d34129f 100644
+index e5a0982..61fe3ca 100644
--- a/Str.c
+++ b/Str.c
-@@ -56,7 +56,7 @@ Strnew_size(int n)
+@@ -48,6 +48,8 @@ Str
+ Strnew_size(int n)
+ {
+ Str x = GC_MALLOC(sizeof(struct _Str));
++ if (n < 0)
++ n = 0;
+ x->ptr = GC_MALLOC_ATOMIC(n + 1);
+ x->ptr[0] = '\0';
+ x->area_size = n + 1;
+@@ -56,7 +58,7 @@ Strnew_size(int n)
}
Str
@@ -1505,7 +1747,7 @@ index e5a0982..d34129f 100644
{
Str x;
int n;
-@@ -73,7 +73,7 @@ Strnew_charp(char *p)
+@@ -73,7 +75,7 @@ Strnew_charp(char *p)
}
Str
@@ -1514,7 +1756,7 @@ index e5a0982..d34129f 100644
{
va_list ap;
Str r = Strnew();
-@@ -87,7 +87,7 @@ Strnew_m_charp(char *p, ...)
+@@ -87,7 +89,7 @@ Strnew_m_charp(char *p, ...)
}
Str
@@ -1523,7 +1765,7 @@ index e5a0982..d34129f 100644
{
Str x;
-@@ -140,7 +140,7 @@ Strcopy(Str x, Str y)
+@@ -140,7 +142,7 @@ Strcopy(Str x, Str y)
}
void
@@ -1532,7 +1774,7 @@ index e5a0982..d34129f 100644
{
int len;
-@@ -160,7 +160,7 @@ Strcopy_charp(Str x, char *y)
+@@ -160,7 +162,7 @@ Strcopy_charp(Str x, char *y)
}
void
@@ -1541,7 +1783,7 @@ index e5a0982..d34129f 100644
{
int len = n;
-@@ -180,7 +180,7 @@ Strcopy_charp_n(Str x, char *y, int n)
+@@ -180,7 +182,7 @@ Strcopy_charp_n(Str x, char *y, int n)
}
void
@@ -1550,7 +1792,7 @@ index e5a0982..d34129f 100644
{
int newlen;
-@@ -209,7 +209,7 @@ Strcat(Str x, Str y)
+@@ -209,7 +211,7 @@ Strcat(Str x, Str y)
}
void
@@ -1559,7 +1801,7 @@ index e5a0982..d34129f 100644
{
if (y == NULL)
return;
-@@ -232,8 +232,8 @@ Strgrow(Str x)
+@@ -232,8 +234,8 @@ Strgrow(Str x)
{
char *old = x->ptr;
int newlen;
@@ -1570,7 +1812,7 @@ index e5a0982..d34129f 100644
newlen += 2;
x->ptr = GC_MALLOC_ATOMIC(newlen);
x->area_size = newlen;
-@@ -278,8 +278,8 @@ void
+@@ -278,8 +280,8 @@ void
Strchop(Str s)
{
STR_LENGTH_CHECK(s);
@@ -1581,7 +1823,7 @@ index e5a0982..d34129f 100644
s->length--;
}
s->ptr[s->length] = '\0';
-@@ -301,7 +301,7 @@ Strinsert_char(Str s, int pos, char c)
+@@ -301,7 +303,7 @@ Strinsert_char(Str s, int pos, char c)
}
void
@@ -1590,7 +1832,7 @@ index e5a0982..d34129f 100644
{
STR_LENGTH_CHECK(s);
while (*p)
-@@ -530,11 +530,8 @@ Str
+@@ -530,11 +532,8 @@ Str
Strfgets(FILE * f)
{
Str s = Strnew();
@@ -1604,7 +1846,7 @@ index e5a0982..d34129f 100644
Strcat_char(s, c);
if (c == '\n')
break;
-@@ -546,11 +543,8 @@ Str
+@@ -546,11 +545,8 @@ Str
Strfgetall(FILE * f)
{
Str s = Strnew();
@@ -1816,7 +2058,7 @@ index 0000000..fa0d391
+
+#endif /* W3_ALLOC_H */
diff --git a/anchor.c b/anchor.c
-index 27bbd56..10d6c1c 100644
+index 27bbd56..b6d121c 100644
--- a/anchor.c
+++ b/anchor.c
@@ -11,7 +11,7 @@ putAnchor(AnchorList *al, char *url, char *target, Anchor **anchor_return,
@@ -1858,16 +2100,17 @@ index 27bbd56..10d6c1c 100644
'\0', line, pos);
}
-@@ -549,7 +551,7 @@ shiftAnchorPosition(AnchorList *al, HmarkerList *hl, int line, int pos,
+@@ -549,7 +551,8 @@ shiftAnchorPosition(AnchorList *al, HmarkerList *hl, int line, int pos,
break;
if (a->start.pos > pos) {
a->start.pos += shift;
- if (hl->marks[a->hseq].line == line)
-+ if (hl && hl->marks && hl->marks[a->hseq].line == line)
++ if (hl && hl->marks &&
++ a->hseq >= 0 && hl->marks[a->hseq].line == line)
hl->marks[a->hseq].pos = a->start.pos;
}
if (a->end.pos >= pos)
-@@ -641,7 +643,6 @@ addMultirowsForm(Buffer *buf, AnchorList *al)
+@@ -641,7 +644,6 @@ addMultirowsForm(Buffer *buf, AnchorList *al)
{
int i, j, k, col, ecol, pos;
Anchor a_form, *a;
@@ -1875,7 +2118,7 @@ index 27bbd56..10d6c1c 100644
Line *l, *ls;
if (al == NULL || al->nanchor == 0)
-@@ -668,7 +669,6 @@ addMultirowsForm(Buffer *buf, AnchorList *al)
+@@ -668,7 +670,6 @@ addMultirowsForm(Buffer *buf, AnchorList *al)
if (!ls)
continue;
}
@@ -1883,7 +2126,7 @@ index 27bbd56..10d6c1c 100644
col = COLPOS(ls, a_form.start.pos);
ecol = COLPOS(ls, a_form.end.pos);
for (j = 0; l && j < a_form.rows; l = l->next, j++) {
-@@ -685,6 +685,8 @@ addMultirowsForm(Buffer *buf, AnchorList *al)
+@@ -685,6 +686,8 @@ addMultirowsForm(Buffer *buf, AnchorList *al)
a->hseq = a_form.hseq;
a->y = a_form.y;
a->end.pos = pos + ecol - col;
@@ -1892,7 +2135,7 @@ index 27bbd56..10d6c1c 100644
l->lineBuf[pos - 1] = '[';
l->lineBuf[a->end.pos] = ']';
for (k = pos; k < a->end.pos; k++)
-@@ -756,7 +758,7 @@ link_list_panel(Buffer *buf)
+@@ -756,7 +759,7 @@ link_list_panel(Buffer *buf)
p = parsedURL2Str(&pu)->ptr;
u = html_quote(p);
if (DecodeURL)
@@ -1901,7 +2144,7 @@ index 27bbd56..10d6c1c 100644
else
p = u;
}
-@@ -787,7 +789,7 @@ link_list_panel(Buffer *buf)
+@@ -787,7 +790,7 @@ link_list_panel(Buffer *buf)
p = parsedURL2Str(&pu)->ptr;
u = html_quote(p);
if (DecodeURL)
@@ -1910,7 +2153,7 @@ index 27bbd56..10d6c1c 100644
else
p = u;
t = getAnchorText(buf, al, a);
-@@ -809,16 +811,13 @@ link_list_panel(Buffer *buf)
+@@ -809,16 +812,13 @@ link_list_panel(Buffer *buf)
p = parsedURL2Str(&pu)->ptr;
u = html_quote(p);
if (DecodeURL)
@@ -1929,7 +2172,7 @@ index 27bbd56..10d6c1c 100644
Strcat_m_charp(tmp, "<li><a href=\"", u, "\">", t, "</a><br>", p,
"\n", NULL);
a = retrieveAnchor(buf->formitem, a->start.line, a->start.pos);
-@@ -842,19 +841,13 @@ link_list_panel(Buffer *buf)
+@@ -842,19 +842,13 @@ link_list_panel(Buffer *buf)
p = parsedURL2Str(&pu)->ptr;
u = html_quote(p);
if (DecodeURL)
@@ -14183,9 +14426,18 @@ index fdd8f64..45dc95e 100644
if (UseAltEntity)
return alt_latin1[c - 0xa0];
diff --git a/etc.c b/etc.c
-index 8fe1215..dcc6edd 100644
+index 8fe1215..37c4f15 100644
--- a/etc.c
+++ b/etc.c
+@@ -498,7 +498,7 @@ calcPosition(char *l, Lineprop *pr, int len, int pos, int bpos, int mode)
+ static char *prevl = NULL;
+ int i, j;
+
+- if (l == NULL || len == 0)
++ if (l == NULL || len == 0 || pos < 0)
+ return bpos;
+ if (l == prevl && mode == CP_AUTO) {
+ if (pos <= len)
@@ -1365,7 +1365,13 @@ setup_child(int child, int i, int f)
if (!child)
SETPGRP();
@@ -14201,7 +14453,7 @@ index 8fe1215..dcc6edd 100644
QuietMessage = TRUE;
fmInitialized = FALSE;
diff --git a/file.c b/file.c
-index 567d41e..86af3a9 100644
+index 567d41e..4d15ff1 100644
--- a/file.c
+++ b/file.c
@@ -26,6 +26,8 @@
@@ -14496,7 +14748,22 @@ index 567d41e..86af3a9 100644
TRAP_OFF;
return b;
}
-@@ -2469,6 +2455,7 @@ set_breakpoint(struct readbuffer *obuf, int tag_length)
+@@ -2325,8 +2311,12 @@ push_link(int cmd, int offset, int pos)
+ struct link_stack *p;
+ p = New(struct link_stack);
+ p->cmd = cmd;
+- p->offset = offset;
+- p->pos = pos;
++ p->offset = (short)offset;
++ if (p->offset < 0)
++ p->offset = 0;
++ p->pos = (short)pos;
++ if (p->pos < 0)
++ p->pos = 0;
+ p->next = link_stack;
+ link_stack = p;
+ }
+@@ -2469,6 +2459,7 @@ set_breakpoint(struct readbuffer *obuf, int tag_length)
bcopy((void *)&obuf->anchor, (void *)&obuf->bp.anchor,
sizeof(obuf->anchor));
obuf->bp.img_alt = obuf->img_alt;
@@ -14504,7 +14771,7 @@ index 567d41e..86af3a9 100644
obuf->bp.in_bold = obuf->in_bold;
obuf->bp.in_italic = obuf->in_italic;
obuf->bp.in_under = obuf->in_under;
-@@ -2486,6 +2473,7 @@ back_to_breakpoint(struct readbuffer *obuf)
+@@ -2486,6 +2477,7 @@ back_to_breakpoint(struct readbuffer *obuf)
bcopy((void *)&obuf->bp.anchor, (void *)&obuf->anchor,
sizeof(obuf->anchor));
obuf->img_alt = obuf->bp.img_alt;
@@ -14512,7 +14779,7 @@ index 567d41e..86af3a9 100644
obuf->in_bold = obuf->bp.in_bold;
obuf->in_italic = obuf->bp.in_italic;
obuf->in_under = obuf->bp.in_under;
-@@ -2729,7 +2717,7 @@ flushline(struct html_feed_environ *h_env, struct readbuffer *obuf, int indent,
+@@ -2729,7 +2721,7 @@ flushline(struct html_feed_environ *h_env, struct readbuffer *obuf, int indent,
Str line = obuf->line, pass = NULL;
char *hidden_anchor = NULL, *hidden_img = NULL, *hidden_bold = NULL,
*hidden_under = NULL, *hidden_italic = NULL, *hidden_strike = NULL,
@@ -14521,7 +14788,7 @@ index 567d41e..86af3a9 100644
#ifdef DEBUG
if (w3m_debug) {
-@@ -2761,6 +2749,12 @@ flushline(struct html_feed_environ *h_env, struct readbuffer *obuf, int indent,
+@@ -2761,6 +2753,12 @@ flushline(struct html_feed_environ *h_env, struct readbuffer *obuf, int indent,
hidden = hidden_img;
}
}
@@ -14534,7 +14801,7 @@ index 567d41e..86af3a9 100644
if (obuf->in_bold) {
if ((hidden_bold = has_hidden_link(obuf, HTML_B)) != NULL) {
if (!hidden || hidden_bold < hidden)
-@@ -2812,6 +2806,8 @@ flushline(struct html_feed_environ *h_env, struct readbuffer *obuf, int indent,
+@@ -2812,6 +2810,8 @@ flushline(struct html_feed_environ *h_env, struct readbuffer *obuf, int indent,
Strcat_charp(line, "</a>");
if (obuf->img_alt && !hidden_img)
Strcat_charp(line, "</img_alt>");
@@ -14543,7 +14810,7 @@ index 567d41e..86af3a9 100644
if (obuf->in_bold && !hidden_bold)
Strcat_charp(line, "</b>");
if (obuf->in_italic && !hidden_italic)
-@@ -3022,6 +3018,18 @@ flushline(struct html_feed_environ *h_env, struct readbuffer *obuf, int indent,
+@@ -3022,6 +3022,18 @@ flushline(struct html_feed_environ *h_env, struct readbuffer *obuf, int indent,
Strcat_charp(tmp, "\">");
push_tag(obuf, tmp->ptr, HTML_IMG_ALT);
}
@@ -14562,7 +14829,7 @@ index 567d41e..86af3a9 100644
if (!hidden_bold && obuf->in_bold)
push_tag(obuf, "<B>", HTML_B);
if (!hidden_italic && obuf->in_italic)
-@@ -3228,7 +3236,7 @@ process_img(struct parsed_tag *tag, int width)
+@@ -3228,7 +3240,7 @@ process_img(struct parsed_tag *tag, int width)
if (!parsedtag_get_value(tag, ATTR_SRC, &p))
return tmp;
@@ -14571,7 +14838,18 @@ index 567d41e..86af3a9 100644
q = NULL;
parsedtag_get_value(tag, ATTR_ALT, &q);
if (!pseudoInlines && (q == NULL || (*q == '\0' && ignore_null_img_alt)))
-@@ -3322,12 +3330,7 @@ process_img(struct parsed_tag *tag, int width)
+@@ -3255,9 +3267,9 @@ process_img(struct parsed_tag *tag, int width)
+ }
+ #endif
+ }
++ i = -1;
+ #ifdef USE_IMAGE
+ if (use_image) {
+- i = -1;
+ if (parsedtag_get_value(tag, ATTR_HEIGHT, &i)) {
+ if (i > 0) {
+ i = (int)(i * image_scale / 100 + 0.5);
+@@ -3322,12 +3334,7 @@ process_img(struct parsed_tag *tag, int width)
Image image;
ParsedURL u;
@@ -14584,7 +14862,7 @@ index 567d41e..86af3a9 100644
image.url = parsedURL2Str(&u)->ptr;
if (!uncompressed_file_type(u.file, &image.ext))
image.ext = filename_extension(u.file, TRUE);
-@@ -3346,8 +3349,14 @@ process_img(struct parsed_tag *tag, int width)
+@@ -3346,8 +3353,14 @@ process_img(struct parsed_tag *tag, int width)
if (i < 0)
i = pixel_per_line;
}
@@ -14601,7 +14879,7 @@ index 567d41e..86af3a9 100644
Strcat(tmp,
Sprintf("<pre_int><img_alt hseq=\"%d\" src=\"", cur_iseq++));
pre_int = TRUE;
-@@ -3378,19 +3387,21 @@ process_img(struct parsed_tag *tag, int width)
+@@ -3378,19 +3391,21 @@ process_img(struct parsed_tag *tag, int width)
if (i0 >= 0)
Strcat(tmp, Sprintf(" height=%d", i0));
switch (align) {
@@ -14631,7 +14909,7 @@ index 567d41e..86af3a9 100644
case ALIGN_BOTTOM:
top = ni - 1;
bottom = 0;
-@@ -3408,7 +3419,12 @@ process_img(struct parsed_tag *tag, int width)
+@@ -3408,7 +3423,12 @@ process_img(struct parsed_tag *tag, int width)
}
break;
}
@@ -14645,7 +14923,16 @@ index 567d41e..86af3a9 100644
if (xoffset)
Strcat(tmp, Sprintf(" xoffset=%d", xoffset));
if (yoffset)
-@@ -3548,7 +3564,7 @@ process_anchor(struct parsed_tag *tag, char *tagbuf)
+@@ -3435,7 +3455,7 @@ process_img(struct parsed_tag *tag, int width)
+ if (use_image) {
+ if (n > nw) {
+ char *r;
+- for (r = q, n = 0; r; r += get_mclen(r), n += get_mcwidth(r)) {
++ for (r = q, n = 0; *r; r += get_mclen(r), n += get_mcwidth(r)) {
+ if (n + get_mcwidth(r) > nw)
+ break;
+ }
+@@ -3548,7 +3568,7 @@ process_anchor(struct parsed_tag *tag, char *tagbuf)
Str
process_input(struct parsed_tag *tag)
{
@@ -14654,7 +14941,7 @@ index 567d41e..86af3a9 100644
char *q, *p, *r, *p2, *s;
Str tmp = NULL;
char *qq = "";
-@@ -3567,9 +3583,9 @@ process_input(struct parsed_tag *tag)
+@@ -3567,9 +3587,9 @@ process_input(struct parsed_tag *tag)
parsedtag_get_value(tag, ATTR_VALUE, &q);
r = "";
parsedtag_get_value(tag, ATTR_NAME, &r);
@@ -14667,7 +14954,7 @@ index 567d41e..86af3a9 100644
parsedtag_get_value(tag, ATTR_MAXLENGTH, &i);
p2 = NULL;
parsedtag_get_value(tag, ATTR_ALT, &p2);
-@@ -3623,9 +3639,10 @@ process_input(struct parsed_tag *tag)
+@@ -3623,9 +3643,10 @@ process_input(struct parsed_tag *tag)
Strcat(tmp, getLinkNumberStr(0));
Strcat_char(tmp, '(');
}
@@ -14680,7 +14967,7 @@ index 567d41e..86af3a9 100644
if (x)
Strcat_charp(tmp, " checked");
if (y)
-@@ -3670,18 +3687,18 @@ process_input(struct parsed_tag *tag)
+@@ -3670,18 +3691,18 @@ process_input(struct parsed_tag *tag)
case FORM_INPUT_PASSWORD:
i = 0;
if (q) {
@@ -14703,7 +14990,7 @@ index 567d41e..86af3a9 100644
Strcat_char(tmp, ' ');
}
break;
-@@ -3732,6 +3749,75 @@ process_input(struct parsed_tag *tag)
+@@ -3732,6 +3753,75 @@ process_input(struct parsed_tag *tag)
}
Str
@@ -14779,7 +15066,27 @@ index 567d41e..86af3a9 100644
process_select(struct parsed_tag *tag)
{
Str tmp = NULL;
-@@ -4084,6 +4170,7 @@ process_form_int(struct parsed_tag *tag, int fid)
+@@ -3926,7 +4016,7 @@ process_textarea(struct parsed_tag *tag, int width)
+ cur_textarea_size = 20;
+ if (parsedtag_get_value(tag, ATTR_COLS, &p)) {
+ cur_textarea_size = atoi(p);
+- if (p[strlen(p) - 1] == '%')
++ if (strlen(p) > 0 && p[strlen(p) - 1] == '%')
+ cur_textarea_size = width * cur_textarea_size / 100 - 2;
+ if (cur_textarea_size <= 0) {
+ cur_textarea_size = 20;
+@@ -4003,7 +4093,9 @@ feed_textarea(char *str)
+ Strcat_charp(textarea_str[n_textarea], "\r\n");
+ str++;
+ }
+- else if (*str != '\r')
++ else if (*str == '\r')
++ str++;
++ else
+ Strcat_char(textarea_str[n_textarea], *(str++));
+ }
+ }
+@@ -4084,6 +4176,7 @@ process_form_int(struct parsed_tag *tag, int fid)
parsedtag_get_value(tag, ATTR_METHOD, &p);
q = "!CURRENT_URL!";
parsedtag_get_value(tag, ATTR_ACTION, &q);
@@ -14787,7 +15094,7 @@ index 567d41e..86af3a9 100644
r = NULL;
#ifdef USE_M17N
if (parsedtag_get_value(tag, ATTR_ACCEPT_CHARSET, &r))
-@@ -4113,7 +4200,7 @@ process_form_int(struct parsed_tag *tag, int fid)
+@@ -4113,7 +4206,7 @@ process_form_int(struct parsed_tag *tag, int fid)
forms = New_N(FormList *, forms_size);
form_stack = NewAtom_N(int, forms_size);
}
@@ -14796,7 +15103,7 @@ index 567d41e..86af3a9 100644
forms_size += form_max;
forms = New_Reuse(FormList *, forms, forms_size);
form_stack = New_Reuse(int, form_stack, forms_size);
-@@ -4284,15 +4371,15 @@ getMetaRefreshParam(char *q, Str *refresh_uri)
+@@ -4284,15 +4377,16 @@ getMetaRefreshParam(char *q, Str *refresh_uri)
while (*q) {
if (!strncasecmp(q, "url=", 4)) {
q += 4;
@@ -14810,12 +15117,13 @@ index 567d41e..86af3a9 100644
- if (s_tmp->ptr[s_tmp->length - 1] == '\"') { /* "
- */
-+ if (s_tmp->ptr[s_tmp->length - 1] == '\"' /* " */
-+ || s_tmp->ptr[s_tmp->length - 1] == '\'') { /* ' */
++ if (s_tmp->length > 0 &&
++ (s_tmp->ptr[s_tmp->length - 1] == '\"' || /* " */
++ s_tmp->ptr[s_tmp->length - 1] == '\'')) { /* ' */
s_tmp->length--;
s_tmp->ptr[s_tmp->length] = '\0';
}
-@@ -4599,6 +4686,12 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env)
+@@ -4599,6 +4693,12 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env)
case HTML_DD:
CLOSE_A;
CLOSE_DT;
@@ -14828,7 +15136,7 @@ index 567d41e..86af3a9 100644
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,
-@@ -4833,13 +4926,13 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env)
+@@ -4833,13 +4933,13 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env)
#ifdef USE_IMAGE
i = 0;
if (parsedtag_get_value(tag, ATTR_TOP_MARGIN, &i)) {
@@ -14846,7 +15154,7 @@ index 567d41e..86af3a9 100644
}
#endif
return 0;
-@@ -4853,15 +4946,43 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env)
+@@ -4853,15 +4953,43 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env)
case HTML_INPUT_ALT:
i = 0;
if (parsedtag_get_value(tag, ATTR_TOP_MARGIN, &i)) {
@@ -14864,10 +15172,10 @@ index 567d41e..86af3a9 100644
+ }
+ 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);
+ }
@@ -14894,7 +15202,7 @@ index 567d41e..86af3a9 100644
case HTML_TABLE:
close_anchor(h_env, obuf);
obuf->table_level++;
-@@ -4884,6 +5005,8 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env)
+@@ -4884,6 +5012,8 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env)
else
w = BORDER_THIN;
}
@@ -14903,7 +15211,7 @@ index 567d41e..86af3a9 100644
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);
-@@ -4892,9 +5015,24 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env)
+@@ -4892,9 +5022,24 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env)
}
if (parsedtag_exists(tag, ATTR_HBORDER))
w = BORDER_NOWIN;
@@ -14928,7 +15236,7 @@ index 567d41e..86af3a9 100644
#ifdef ID_EXT
parsedtag_get_value(tag, ATTR_ID, &id);
#endif /* ID_EXT */
-@@ -4970,6 +5108,16 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env)
+@@ -4970,6 +5115,16 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env)
case HTML_INPUT:
close_anchor(h_env, obuf);
tmp = process_input(tag);
@@ -14945,7 +15253,7 @@ index 567d41e..86af3a9 100644
if (tmp)
HTMLlineproc1(tmp->ptr, h_env);
return 1;
-@@ -5067,11 +5215,10 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env)
+@@ -5067,11 +5222,10 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env)
}
return 1;
case HTML_BASE:
@@ -14959,7 +15267,7 @@ index 567d41e..86af3a9 100644
parseURL(p, cur_baseURL, NULL);
}
#endif
-@@ -5329,6 +5476,13 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
+@@ -5329,6 +5483,13 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
#ifdef MENU_SELECT
Anchor **a_select = NULL;
#endif
@@ -14973,7 +15281,7 @@ index 567d41e..86af3a9 100644
if (out_size == 0) {
out_size = LINELEN;
-@@ -5523,16 +5677,17 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
+@@ -5523,16 +5684,17 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
hseq = 0;
id = NULL;
if (parsedtag_get_value(tag, ATTR_NAME, &id)) {
@@ -14995,7 +15303,16 @@ index 567d41e..86af3a9 100644
parsedtag_get_value(tag, ATTR_TITLE, &s);
parsedtag_get_value(tag, ATTR_ACCESSKEY, &t);
parsedtag_get_value(tag, ATTR_HSEQ, &hseq);
-@@ -5618,7 +5773,7 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
+@@ -5571,7 +5733,7 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
+ a_href->end.pos = pos;
+ if (a_href->start.line == a_href->end.line &&
+ a_href->start.pos == a_href->end.pos) {
+- if (buf->hmarklist &&
++ if (buf->hmarklist && a_href->hseq >= 0 &&
+ a_href->hseq < buf->hmarklist->nmark)
+ buf->hmarklist->marks[a_href->hseq].invalid = 1;
+ a_href->hseq = -1;
+@@ -5618,7 +5780,7 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
ParsedURL u;
Image *image;
@@ -15004,7 +15321,7 @@ index 567d41e..86af3a9 100644
a_img->image = image = New(Image);
image->url = parsedURL2Str(&u)->ptr;
if (!uncompressed_file_type(u.file, &image->ext))
-@@ -5639,7 +5794,7 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
+@@ -5639,7 +5801,7 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
image->map = q;
image->ismap = ismap;
image->touch = 0;
@@ -15013,7 +15330,7 @@ index 567d41e..86af3a9 100644
IMG_FLAG_SKIP);
}
else if (iseq < 0) {
-@@ -5678,7 +5833,8 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
+@@ -5678,7 +5840,8 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
parsedtag_get_value(tag, ATTR_FID, &form_id);
parsedtag_get_value(tag, ATTR_TOP_MARGIN, &top);
parsedtag_get_value(tag, ATTR_BOTTOM_MARGIN, &bottom);
@@ -15023,7 +15340,7 @@ index 567d41e..86af3a9 100644
break; /* outside of <form>..</form> */
form = forms[form_id];
if (hseq > 0) {
-@@ -5689,6 +5845,21 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
+@@ -5689,6 +5852,21 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
putHmarker(buf->hmarklist, currentLn(buf),
hpos, hseq - 1);
}
@@ -15045,7 +15362,7 @@ index 567d41e..86af3a9 100644
if (!form->target)
form->target = buf->baseTarget;
if (a_textarea &&
-@@ -5761,8 +5932,8 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
+@@ -5761,8 +5939,8 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
break;
if (parsedtag_get_value(tag, ATTR_HREF, &p)) {
MapArea *a;
@@ -15056,7 +15373,7 @@ index 567d41e..86af3a9 100644
t = NULL;
parsedtag_get_value(tag, ATTR_TARGET, &t);
q = "";
-@@ -5811,11 +5982,14 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
+@@ -5811,11 +5989,14 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
break;
case HTML_BASE:
if (parsedtag_get_value(tag, ATTR_HREF, &p)) {
@@ -15073,7 +15390,7 @@ index 567d41e..86af3a9 100644
}
if (parsedtag_get_value(tag, ATTR_TARGET, &p))
buf->baseTarget =
-@@ -5830,8 +6004,8 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
+@@ -5830,8 +6011,8 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
int refresh_interval = getMetaRefreshParam(q, &tmp);
#ifdef USE_ALARM
if (tmp) {
@@ -15084,7 +15401,7 @@ index 567d41e..86af3a9 100644
buf->event = setAlarmEvent(buf->event,
refresh_interval,
AL_IMPLICIT_ONCE,
-@@ -5844,8 +6018,8 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
+@@ -5844,8 +6025,8 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
FUNCNAME_reload, NULL);
#else
if (tmp && refresh_interval == 0) {
@@ -15095,7 +15412,7 @@ index 567d41e..86af3a9 100644
pushEvent(FUNCNAME_gorURL, p);
}
#endif
-@@ -5864,14 +6038,14 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
+@@ -5864,14 +6045,14 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
case HTML_TEXTAREA_INT:
if (parsedtag_get_value(tag, ATTR_TEXTAREANUMBER,
&n_textarea)
@@ -15112,7 +15429,7 @@ index 567d41e..86af3a9 100644
FormItemList *item =
(FormItemList *)a_textarea[n_textarea]->url;
item->init_value = item->value =
-@@ -5881,7 +6055,7 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
+@@ -5881,7 +6062,7 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
#ifdef MENU_SELECT
case HTML_SELECT_INT:
if (parsedtag_get_value(tag, ATTR_SELECTNUMBER, &n_select)
@@ -15121,7 +15438,7 @@ index 567d41e..86af3a9 100644
select_option[n_select].first = NULL;
select_option[n_select].last = NULL;
}
-@@ -5889,7 +6063,7 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
+@@ -5889,7 +6070,7 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
n_select = -1;
break;
case HTML_N_SELECT_INT:
@@ -15130,7 +15447,7 @@ index 567d41e..86af3a9 100644
FormItemList *item =
(FormItemList *)a_select[n_select]->url;
item->select_option = select_option[n_select].first;
-@@ -5929,7 +6103,7 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
+@@ -5929,7 +6110,7 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
#ifdef ID_EXT
id = NULL;
if (parsedtag_get_value(tag, ATTR_ID, &id)) {
@@ -15139,7 +15456,7 @@ index 567d41e..86af3a9 100644
registerName(buf, id, currentLn(buf), pos);
}
if (renderFrameSet &&
-@@ -5964,7 +6138,8 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
+@@ -5964,7 +6145,8 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
fclose(debug);
#endif
for (form_id = 1; form_id <= form_max; form_id++)
@@ -15149,7 +15466,7 @@ index 567d41e..86af3a9 100644
buf->formlist = (form_max >= 0) ? forms[form_max] : NULL;
if (n_textarea)
addMultirowsForm(buf, buf->formitem);
-@@ -5982,7 +6157,8 @@ addLink(Buffer *buf, struct parsed_tag *tag)
+@@ -5982,7 +6164,8 @@ addLink(Buffer *buf, struct parsed_tag *tag)
parsedtag_get_value(tag, ATTR_HREF, &href);
if (href)
@@ -15159,7 +15476,7 @@ index 567d41e..86af3a9 100644
parsedtag_get_value(tag, ATTR_TITLE, &title);
parsedtag_get_value(tag, ATTR_TYPE, &ctype);
parsedtag_get_value(tag, ATTR_REL, &rel);
-@@ -6154,10 +6330,10 @@ HTMLlineproc0(char *line, struct html_feed_environ *h_env, int internal)
+@@ -6154,10 +6337,10 @@ HTMLlineproc0(char *line, struct html_feed_environ *h_env, int internal)
while (*line != '\0') {
char *str, *p;
int is_tag = FALSE;
@@ -15174,7 +15491,16 @@ index 567d41e..86af3a9 100644
if (*line == '<' || obuf->status != R_ST_NORMAL) {
/*
-@@ -6239,7 +6415,7 @@ HTMLlineproc0(char *line, struct html_feed_environ *h_env, int internal)
+@@ -6173,7 +6356,7 @@ HTMLlineproc0(char *line, struct html_feed_environ *h_env, int internal)
+ }
+ if (h_env->tagbuf->length == 0)
+ continue;
+- str = h_env->tagbuf->ptr;
++ str = Strdup(h_env->tagbuf)->ptr;
+ if (*str == '<') {
+ if (str[1] && REALLY_THE_BEGINNING_OF_A_TAG(str))
+ is_tag = TRUE;
+@@ -6239,7 +6422,7 @@ HTMLlineproc0(char *line, struct html_feed_environ *h_env, int internal)
}
proc_normal:
@@ -15183,7 +15509,16 @@ index 567d41e..86af3a9 100644
/*
* within table: in <table>..</table>, all input tokens
* are fed to the table renderer, and then the renderer
-@@ -6272,6 +6448,7 @@ HTMLlineproc0(char *line, struct html_feed_environ *h_env, int internal)
+@@ -6255,6 +6438,8 @@ HTMLlineproc0(char *line, struct html_feed_environ *h_env, int internal)
+ if (obuf->table_level >= 0) {
+ struct table *tbl0 = tables[obuf->table_level];
+ str = Sprintf("<table_alt tid=%d>", tbl0->ntable)->ptr;
++ if (tbl0->row < 0)
++ continue;
+ pushTable(tbl0, tbl);
+ tbl = tbl0;
+ tbl_mode = &table_mode[obuf->table_level];
+@@ -6272,6 +6457,7 @@ HTMLlineproc0(char *line, struct html_feed_environ *h_env, int internal)
do_blankline(h_env, obuf, indent, 0, h_env->limit);
}
save_fonteffect(h_env, obuf);
@@ -15191,7 +15526,17 @@ index 567d41e..86af3a9 100644
renderTable(tbl, tbl_width, h_env);
restore_fonteffect(h_env, obuf);
obuf->flag &= ~RB_IGNORE_P;
-@@ -6756,6 +6933,12 @@ init_henv(struct html_feed_environ *h_env, struct readbuffer *obuf,
+@@ -6429,7 +6615,8 @@ HTMLlineproc0(char *line, struct html_feed_environ *h_env, int internal)
+ indent = h_env->envs[h_env->envc].indent;
+ if (obuf->bp.pos - i > indent) {
+ Str line;
+- append_tags(obuf);
++ append_tags(obuf); /* may reallocate the buffer */
++ bp = obuf->line->ptr + obuf->bp.len;
+ line = Strnew_charp(bp);
+ Strshrink(obuf->line, obuf->line->length - obuf->bp.len);
+ #ifdef FORMAT_NICE
+@@ -6756,6 +6943,12 @@ init_henv(struct html_feed_environ *h_env, struct readbuffer *obuf,
obuf->nobr_level = 0;
bzero((void *)&obuf->anchor, sizeof(obuf->anchor));
obuf->img_alt = 0;
@@ -15204,7 +15549,7 @@ index 567d41e..86af3a9 100644
obuf->in_bold = 0;
obuf->in_italic = 0;
obuf->in_under = 0;
-@@ -6791,6 +6974,15 @@ completeHTMLstream(struct html_feed_environ *h_env, struct readbuffer *obuf)
+@@ -6791,6 +6984,15 @@ completeHTMLstream(struct html_feed_environ *h_env, struct readbuffer *obuf)
push_tag(obuf, "</img_alt>", HTML_N_IMG_ALT);
obuf->img_alt = NULL;
}
@@ -15220,7 +15565,7 @@ index 567d41e..86af3a9 100644
if (obuf->in_bold) {
push_tag(obuf, "</b>", HTML_N_B);
obuf->in_bold = 0;
-@@ -6824,9 +7016,12 @@ completeHTMLstream(struct html_feed_environ *h_env, struct readbuffer *obuf)
+@@ -6824,9 +7026,12 @@ completeHTMLstream(struct html_feed_environ *h_env, struct readbuffer *obuf)
obuf->table_level = MAX_TABLE - 1;
while (obuf->table_level >= 0) {
@@ -15233,7 +15578,7 @@ index 567d41e..86af3a9 100644
}
}
-@@ -6848,6 +7043,8 @@ print_internal_information(struct html_feed_environ *henv)
+@@ -6848,6 +7053,8 @@ print_internal_information(struct html_feed_environ *henv)
if (form_max >= 0) {
FormList *fp;
for (i = 0; i <= form_max; i++) {
@@ -15242,7 +15587,7 @@ index 567d41e..86af3a9 100644
fp = forms[i];
s = Sprintf("<form_int fid=\"%d\" action=\"%s\" method=\"%s\"",
i, html_quote(fp->action->ptr),
-@@ -6963,8 +7160,6 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal)
+@@ -6963,8 +7170,6 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal)
image_flag = IMG_FLAG_AUTO;
else
image_flag = IMG_FLAG_SKIP;
@@ -15251,7 +15596,7 @@ index 567d41e..86af3a9 100644
#endif
if (w3m_halfload) {
-@@ -6987,6 +7182,9 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal)
+@@ -6987,6 +7192,9 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal)
htmlenv1.f = stdout;
else
htmlenv1.buf = newTextLineList();
@@ -15261,7 +15606,7 @@ index 567d41e..86af3a9 100644
if (SETJMP(AbortLoading) != 0) {
HTMLlineproc1("<br>Transfer Interrupted!<br>", &htmlenv1);
-@@ -7048,18 +7246,23 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal)
+@@ -7048,18 +7256,23 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal)
}
#endif
lineBuf2 = convertLine(f, lineBuf2, HTML_MODE, &charset, doc_charset);
@@ -15287,7 +15632,7 @@ index 567d41e..86af3a9 100644
if (htmlenv1.title)
newBuf->buffername = htmlenv1.title;
if (w3m_halfdump) {
-@@ -7096,16 +7299,17 @@ loadHTMLString(Str page)
+@@ -7096,16 +7309,17 @@ loadHTMLString(Str page)
MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL;
Buffer *newBuf;
@@ -15307,7 +15652,7 @@ index 567d41e..86af3a9 100644
#ifdef USE_M17N
newBuf->document_charset = InnerCharset;
#endif
-@@ -7115,6 +7319,7 @@ loadHTMLString(Str page)
+@@ -7115,6 +7329,7 @@ loadHTMLString(Str page)
#endif
TRAP_OFF;
@@ -15315,7 +15660,7 @@ index 567d41e..86af3a9 100644
newBuf->topLine = newBuf->firstLine;
newBuf->lastLine = newBuf->currentLine;
newBuf->currentLine = newBuf->firstLine;
-@@ -7207,7 +7412,7 @@ loadGopherDir(URLFile *uf, ParsedURL *pu, wc_ces * charset)
+@@ -7207,7 +7422,7 @@ loadGopherDir(URLFile *uf, ParsedURL *pu, wc_ces * charset)
q = Strnew_m_charp("gopher://", host->ptr, ":", port->ptr,
"/", file->ptr, NULL)->ptr;
Strcat_m_charp(tmp, "<a href=\"",
@@ -15324,7 +15669,7 @@ index 567d41e..86af3a9 100644
"\">", p, html_quote(name->ptr + 1), "</a>\n", NULL);
}
-@@ -7243,7 +7448,6 @@ loadBuffer(URLFile *uf, Buffer *volatile newBuf)
+@@ -7243,7 +7458,6 @@ loadBuffer(URLFile *uf, Buffer *volatile newBuf)
if (newBuf == NULL)
newBuf = newBuffer(INIT_BUFFER_WIDTH);
@@ -15332,7 +15677,7 @@ index 567d41e..86af3a9 100644
if (SETJMP(AbortLoading) != 0) {
goto _end;
-@@ -7331,6 +7535,7 @@ loadImageBuffer(URLFile *uf, Buffer *newBuf)
+@@ -7331,6 +7545,7 @@ loadImageBuffer(URLFile *uf, Buffer *newBuf)
URLFile f;
MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL;
struct stat st;
@@ -15340,7 +15685,7 @@ index 567d41e..86af3a9 100644
loadImage(newBuf, IMG_FLAG_STOP);
image.url = uf->url;
-@@ -7338,20 +7543,18 @@ loadImageBuffer(URLFile *uf, Buffer *newBuf)
+@@ -7338,20 +7553,18 @@ loadImageBuffer(URLFile *uf, Buffer *newBuf)
image.width = -1;
image.height = -1;
image.cache = NULL;
@@ -15364,7 +15709,7 @@ index 567d41e..86af3a9 100644
TRAP_OFF;
cache->loaded = IMG_FLAG_LOADED;
-@@ -7371,6 +7574,7 @@ loadImageBuffer(URLFile *uf, Buffer *newBuf)
+@@ -7371,6 +7584,7 @@ loadImageBuffer(URLFile *uf, Buffer *newBuf)
init_stream(&f, SCM_LOCAL, newStrStream(tmp));
loadHTMLstream(&f, newBuf, src, TRUE);
@@ -15372,7 +15717,7 @@ index 567d41e..86af3a9 100644
if (src)
fclose(src);
-@@ -7411,7 +7615,7 @@ conv_symbol(Line *l)
+@@ -7411,7 +7625,7 @@ conv_symbol(Line *l)
symbol = get_symbol(DisplayCharset, &w);
#endif
}
@@ -15381,7 +15726,7 @@ index 567d41e..86af3a9 100644
#ifdef USE_M17N
p += len - 1;
pr += len - 1;
-@@ -7580,8 +7784,11 @@ openGeneralPagerBuffer(InputStream stream)
+@@ -7580,8 +7794,11 @@ openGeneralPagerBuffer(InputStream stream)
#ifdef USE_M17N
content_charset = 0;
#endif
@@ -15394,7 +15739,7 @@ index 567d41e..86af3a9 100644
readHeader(&uf, t_buf, TRUE, NULL);
t = checkContentType(t_buf);
if (t == NULL)
-@@ -7609,14 +7816,13 @@ openGeneralPagerBuffer(InputStream stream)
+@@ -7609,14 +7826,13 @@ openGeneralPagerBuffer(InputStream stream)
#ifdef USE_IMAGE
else if (activeImage && displayImage && !useExtImageViewer &&
!(w3m_dump & ~DUMP_FRAME) && !strncasecmp(t, "image/", 6)) {
@@ -15411,7 +15756,7 @@ index 567d41e..86af3a9 100644
UFclose(&uf);
if (buf == NULL || buf == NO_BUFFER)
return buf;
-@@ -7629,8 +7835,6 @@ openGeneralPagerBuffer(InputStream stream)
+@@ -7629,8 +7845,6 @@ openGeneralPagerBuffer(InputStream stream)
}
}
buf->real_type = t;
@@ -15420,7 +15765,7 @@ index 567d41e..86af3a9 100644
return buf;
}
-@@ -7766,6 +7970,8 @@ save2tmp(URLFile uf, char *tmpf)
+@@ -7766,6 +7980,8 @@ save2tmp(URLFile uf, char *tmpf)
clen_t linelen = 0, trbyte = 0;
MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL;
static JMP_BUF env_bak;
@@ -15429,7 +15774,7 @@ index 567d41e..86af3a9 100644
ff = fopen(tmpf, "wb");
if (ff == NULL) {
-@@ -7802,30 +8008,29 @@ save2tmp(URLFile uf, char *tmpf)
+@@ -7802,30 +8018,29 @@ save2tmp(URLFile uf, char *tmpf)
else
#endif /* USE_NNTP */
{
@@ -15472,7 +15817,7 @@ index 567d41e..86af3a9 100644
{
Str tmpf, command;
struct mailcap *mcap;
-@@ -7834,7 +8039,7 @@ doExternal(URLFile uf, char *path, char *type, Buffer **bufp,
+@@ -7834,7 +8049,7 @@ doExternal(URLFile uf, char *path, char *type, Buffer **bufp,
char *header, *src = NULL, *ext = uf.ext;
if (!(mcap = searchExtViewer(type)))
@@ -15481,7 +15826,7 @@ index 567d41e..86af3a9 100644
if (mcap->nametemplate) {
tmpf = unquote_mailcap(mcap->nametemplate, NULL, "", NULL, NULL);
-@@ -7867,15 +8072,13 @@ doExternal(URLFile uf, char *path, char *type, Buffer **bufp,
+@@ -7867,15 +8082,13 @@ doExternal(URLFile uf, char *path, char *type, Buffer **bufp,
UFclose(&uf);
myExec(command->ptr);
}
@@ -15499,7 +15844,7 @@ index 567d41e..86af3a9 100644
}
}
if (mcap->flags & (MAILCAP_HTMLOUTPUT | MAILCAP_COPIOUSOUTPUT)) {
-@@ -7918,14 +8121,13 @@ doExternal(URLFile uf, char *path, char *type, Buffer **bufp,
+@@ -7918,14 +8131,13 @@ doExternal(URLFile uf, char *path, char *type, Buffer **bufp,
buf = NO_BUFFER;
}
if (buf && buf != NO_BUFFER) {
@@ -15518,7 +15863,7 @@ index 567d41e..86af3a9 100644
}
static int
-@@ -7935,7 +8137,8 @@ _MoveFile(char *path1, char *path2)
+@@ -7935,7 +8147,8 @@ _MoveFile(char *path1, char *path2)
FILE *f2;
int is_pipe;
clen_t linelen = 0, trbyte = 0;
@@ -15528,7 +15873,7 @@ index 567d41e..86af3a9 100644
f1 = openIS(path1);
if (f1 == NULL)
-@@ -7953,12 +8156,13 @@ _MoveFile(char *path1, char *path2)
+@@ -7953,12 +8166,13 @@ _MoveFile(char *path1, char *path2)
return -1;
}
current_content_length = 0;
@@ -15546,7 +15891,7 @@ index 567d41e..86af3a9 100644
ISclose(f1);
if (is_pipe)
pclose(f2);
-@@ -7998,7 +8202,7 @@ _doFileCopy(char *tmpf, char *defstr, int download)
+@@ -7998,7 +8212,7 @@ _doFileCopy(char *tmpf, char *defstr, int download)
else {
if (q) {
p = unescape_spaces(Strnew_charp(q))->ptr;
@@ -15555,7 +15900,7 @@ index 567d41e..86af3a9 100644
}
p = expandPath(p);
if (checkOverWrite(p) < 0)
-@@ -8317,21 +8521,23 @@ uncompress_stream(URLFile *uf, char **src)
+@@ -8317,21 +8531,23 @@ uncompress_stream(URLFile *uf, char **src)
}
if (pid2 == 0) {
/* child2 */
@@ -15584,7 +15929,7 @@ index 567d41e..86af3a9 100644
exit(0);
}
/* child1 */
-@@ -8378,7 +8584,7 @@ lessopen_stream(char *path)
+@@ -8378,7 +8594,7 @@ lessopen_stream(char *path)
}
c = getc(fp);
if (c == EOF) {
@@ -15797,7 +16142,7 @@ index 8378939..96d3ab3 100644
global double image_scale init(100);
#endif
diff --git a/form.c b/form.c
-index b7556ca..1aaaf19 100644
+index b7556ca..0605513 100644
--- a/form.c
+++ b/form.c
@@ -10,8 +10,10 @@
@@ -15835,7 +16180,17 @@ index b7556ca..1aaaf19 100644
}
void
-@@ -438,6 +442,9 @@ formUpdateBuffer(Anchor *a, Buffer *buf, FormItemList *form)
+@@ -316,7 +320,8 @@ form_update_line(Line *line, char **str, int spos, int epos, int width,
+ pos += width - w;
+
+ len = line->len + pos + spos - epos;
+- buf = New_N(char, len);
++ buf = New_N(char, len + 1);
++ buf[len] = '\0';
+ prop = New_N(Lineprop, len);
+ bcopy((void *)line->lineBuf, (void *)buf, spos * sizeof(char));
+ bcopy((void *)line->propBuf, (void *)prop, spos * sizeof(Lineprop));
+@@ -438,6 +443,9 @@ formUpdateBuffer(Anchor *a, Buffer *buf, FormItemList *form)
switch (form->type) {
case FORM_INPUT_CHECKBOX:
case FORM_INPUT_RADIO:
@@ -15845,7 +16200,7 @@ index b7556ca..1aaaf19 100644
if (form->checked)
buf->currentLine->lineBuf[spos] = '*';
else
-@@ -455,8 +462,14 @@ formUpdateBuffer(Anchor *a, Buffer *buf, FormItemList *form)
+@@ -455,8 +463,14 @@ formUpdateBuffer(Anchor *a, Buffer *buf, FormItemList *form)
}
else
#endif /* MENU_SELECT */
@@ -15860,16 +16215,17 @@ index b7556ca..1aaaf19 100644
if (form->type == FORM_TEXTAREA) {
int n = a->y - buf->currentLine->linenumber;
if (n > 0)
-@@ -477,6 +490,8 @@ formUpdateBuffer(Anchor *a, Buffer *buf, FormItemList *form)
+@@ -477,6 +491,9 @@ formUpdateBuffer(Anchor *a, Buffer *buf, FormItemList *form)
spos = a->start.pos;
epos = a->end.pos;
}
-+ if (a->start.line != a->end.line || spos > epos || epos >= l->len || spos < 0 || epos < 0)
++ if (a->start.line != a->end.line || spos > epos || epos >= l->len ||
++ spos < 0 || epos < 0 || COLPOS(l, epos) < col)
+ break;
pos = form_update_line(l, &p, spos, epos, COLPOS(l, epos) - col,
rows > 1,
form->type == FORM_INPUT_PASSWORD);
-@@ -787,7 +802,7 @@ struct pre_form {
+@@ -787,7 +804,7 @@ struct pre_form {
static struct pre_form *PreForm = NULL;
static struct pre_form *
@@ -15878,7 +16234,7 @@ index b7556ca..1aaaf19 100644
{
ParsedURL pu;
struct pre_form *new;
-@@ -796,21 +811,13 @@ add_pre_form(struct pre_form *prev, char *url, char *name, char *action)
+@@ -796,21 +813,13 @@ add_pre_form(struct pre_form *prev, char *url, char *name, char *action)
new = prev->next = New(struct pre_form);
else
new = PreForm = New(struct pre_form);
@@ -15904,7 +16260,7 @@ index b7556ca..1aaaf19 100644
new->name = (name && *name) ? name : NULL;
new->action = (action && *action) ? action : NULL;
new->item = NULL;
-@@ -834,7 +841,7 @@ add_pre_form_item(struct pre_form *pf, struct pre_form_item *prev, int type,
+@@ -834,7 +843,7 @@ add_pre_form_item(struct pre_form *pf, struct pre_form_item *prev, int type,
new->name = name;
new->value = value;
if (checked && *checked && (!strcmp(checked, "0") ||
@@ -15913,7 +16269,7 @@ index b7556ca..1aaaf19 100644
|| !strcasecmp(checked, "no")))
new->checked = 0;
else
-@@ -875,6 +882,7 @@ loadPreForm(void)
+@@ -875,6 +884,7 @@ loadPreForm(void)
return;
while (1) {
char *p, *s, *arg;
@@ -15921,7 +16277,7 @@ index b7556ca..1aaaf19 100644
line = Strfgets(fp);
if (line->length == 0)
-@@ -890,18 +898,20 @@ loadPreForm(void)
+@@ -890,18 +900,20 @@ loadPreForm(void)
if (*p == '#' || *p == '\0')
continue; /* comment or empty line */
s = getWord(&p);
@@ -15944,7 +16300,7 @@ index b7556ca..1aaaf19 100644
if (!strcmp(s, "form")) {
if (!arg || !*arg)
continue;
-@@ -913,7 +923,7 @@ loadPreForm(void)
+@@ -913,7 +925,7 @@ loadPreForm(void)
}
if (pf->item) {
struct pre_form *prev = pf;
@@ -16236,10 +16592,10 @@ index bca227e..d9f08e9 100644
{NULL, NULL, 0, 0}, /* 142 Undefined */
{NULL, NULL, 0, 0}, /* 143 Undefined */
diff --git a/html.h b/html.h
-index 7abbd3b..c490655 100644
+index 7abbd3b..2a9a431 100644
--- a/html.h
+++ b/html.h
-@@ -1,20 +1,18 @@
+@@ -1,20 +1,20 @@
/* $Id: html.h,v 1.31 2010/08/14 01:29:40 htrb Exp $ */
#ifndef _HTML_H
#define _HTML_H
@@ -16251,7 +16607,8 @@ index 7abbd3b..c490655 100644
#endif /* USE_SSL */
-#include "istream.h"
--
++#include <time.h>
+
#define StrUFgets(f) StrISgets((f)->stream)
#define StrmyUFgets(f) StrmyISgets((f)->stream)
#define UFgetc(f) ISgetc((f)->stream)
@@ -16262,7 +16619,7 @@ index 7abbd3b..c490655 100644
#define UFfileno(f) ISfileno((f)->stream)
struct cmdtable {
-@@ -62,11 +60,12 @@ typedef struct _ParsedURL {
+@@ -62,11 +62,12 @@ typedef struct _ParsedURL {
int is_nocache;
} ParsedURL;
@@ -16276,7 +16633,7 @@ index 7abbd3b..c490655 100644
char *ext;
int compression;
int content_encoding;
-@@ -214,21 +213,22 @@ typedef struct {
+@@ -214,21 +215,22 @@ typedef struct {
#define HTML_BIG 122
#define HTML_N_BIG 123
#define HTML_BUTTON 124
@@ -18131,6 +18488,154 @@ index dfac6d9..bed5dff 100644
static wc_wchar_t
ucs_cs94_conv(wc_ccs ccs, wc_uint16 c)
{
+diff --git a/libwc/wtf.c b/libwc/wtf.c
+index b8cfdc7..94d95c1 100644
+--- a/libwc/wtf.c
++++ b/libwc/wtf.c
+@@ -120,29 +120,36 @@ int
+ wtf_strwidth(wc_uchar *p)
+ {
+ int w = 0;
++ wc_uchar *q = p + strlen(p);
+
+- while (*p) {
++ while (p < q) {
+ w += wtf_width(p);
+ p += WTF_LEN_MAP[*p];
+ }
+ return w;
+ }
+
+-/*
+ size_t
+ wtf_len1(wc_uchar *p)
+ {
+- return (size_t)WTF_LEN_MAP[*p];
++ size_t len, len_max = WTF_LEN_MAP[*p];
++
++ for (len = 0; *(p + len); len++)
++ if (len == len_max)
++ break;
++ if (len == 0)
++ len = 1;
++ return len;
+ }
+-*/
+
+ size_t
+ wtf_len(wc_uchar *p)
+ {
+ wc_uchar *q = p;
++ wc_uchar *strz = p + strlen(p);
+
+ q += WTF_LEN_MAP[*q];
+- while (*q && ! WTF_WIDTH_MAP[*q])
++ while (q < strz && ! WTF_WIDTH_MAP[*q])
+ q += WTF_LEN_MAP[*q];
+ return q - p;
+ }
+@@ -166,15 +173,17 @@ wtf_type(wc_uchar *p)
+ ((p)[3] = (((c) >> 7) & 0x7f) | 0x80), \
+ ((p)[4] = ( (c) & 0x7f) | 0x80)
+ #define wtf_to_wcs16(p) \
++ ((p)[0] == 0 || (p)[1] == 0 || (p)[2] == 0 ? 0 : \
+ ((wc_uint32)((p)[0] & 0x03) << 14) \
+ | ((wc_uint32)((p)[1] & 0x7f) << 7) \
+- | ((wc_uint32)((p)[2] & 0x7f) )
++ | ((wc_uint32)((p)[2] & 0x7f) ))
+ #define wtf_to_wcs32(p) \
++ ((p)[0] == 0 || (p)[1] == 0 || (p)[2] == 0 || (p)[3] == 0 || (p)[4] == 0 ? 0 : \
+ ((wc_uint32)((p)[0] & 0x0f) << 28) \
+ | ((wc_uint32)((p)[1] & 0x7f) << 21) \
+ | ((wc_uint32)((p)[2] & 0x7f) << 14) \
+ | ((wc_uint32)((p)[3] & 0x7f) << 7) \
+- | ((wc_uint32)((p)[4] & 0x7f) )
++ | ((wc_uint32)((p)[4] & 0x7f) ))
+
+ void
+ wtf_push(Str os, wc_ccs ccs, wc_uint32 code)
+@@ -388,7 +397,7 @@ wtf_parse1(wc_uchar **p)
+ cc.code = *(q++);
+ } else if (*q > 0xa0) {
+ cc.ccs = wtf_gr_ccs;
+- if (WC_CCS_IS_WIDE(cc.ccs)) {
++ if (WC_CCS_IS_WIDE(cc.ccs) && *(q+1)) {
+ cc.code = ((wc_uint32)*q << 8) | *(q+1);
+ q += 2;
+ } else
+@@ -401,27 +410,47 @@ wtf_parse1(wc_uchar **p)
+ case WC_CCS_A_CS942:
+ case WC_CCS_A_PCS:
+ case WC_CCS_A_UNKNOWN:
+- cc.ccs |= *(q++) & 0x7f;
+- cc.code = *(q++);
++ if (*q && *(q+1)) {
++ cc.ccs |= *(q++) & 0x7f;
++ cc.code = *(q++);
++ } else {
++ cc.ccs = WC_CCS_US_ASCII;
++ cc.code = (wc_uint32)' ';
++ }
+ break;
+ case WC_CCS_A_CS94W:
+ case WC_CCS_A_CS96W:
+ case WC_CCS_A_PCSW:
+- cc.ccs |= *(q++) & 0x7f;
+- cc.code = ((wc_uint32)*q << 8) | *(q+1);
+- q += 2;
++ if (*q && *(q+1) && *(q+2)) {
++ cc.ccs |= *(q++) & 0x7f;
++ cc.code = ((wc_uint32)*q << 8) | *(q+1);
++ q += 2;
++ } else {
++ cc.ccs = WC_CCS_US_ASCII;
++ cc.code = (wc_uint32)' ';
++ }
+ break;
+ case WC_CCS_A_WCS16:
+ case WC_CCS_A_WCS16W:
+- cc.ccs |= (*q & 0x7c) >> 2;
+- cc.code = wtf_to_wcs16(q);
+- q += 3;
++ if (*q && *(q+1) && *(q+2)) {
++ cc.ccs |= (*q & 0x7c) >> 2;
++ cc.code = wtf_to_wcs16(q);
++ q += 3;
++ } else {
++ cc.ccs = WC_CCS_US_ASCII;
++ cc.code = (wc_uint32)' ';
++ }
+ break;
+ case WC_CCS_A_WCS32:
+ case WC_CCS_A_WCS32W:
+- cc.ccs |= (*q & 0x70) >> 4;
+- cc.code = wtf_to_wcs32(q);
+- q += 5;
++ if (*q && *(q+1) && *(q+2) && *(q+3) && *(q+4)) {
++ cc.ccs |= (*q & 0x70) >> 4;
++ cc.code = wtf_to_wcs32(q);
++ q += 5;
++ } else {
++ cc.ccs = WC_CCS_US_ASCII;
++ cc.code = (wc_uint32)' ';
++ }
+ break;
+ default:
+ /* case 0: */
+diff --git a/libwc/wtf.h b/libwc/wtf.h
+index ad47973..435526f 100644
+--- a/libwc/wtf.h
++++ b/libwc/wtf.h
+@@ -59,8 +59,7 @@ extern void wtf_init(wc_ces ces1, wc_ces ces2);
+ #define wtf_width(p) (WcOption.use_wide ? (int)WTF_WIDTH_MAP[(wc_uchar)*(p)] \
+ : ((int)WTF_WIDTH_MAP[(wc_uchar)*(p)] ? 1 : 0))
+ extern int wtf_strwidth(wc_uchar *p);
+-/* extern size_t wtf_len1(wc_uchar *p); */
+-#define wtf_len1(p) ((int)WTF_LEN_MAP[(wc_uchar)*(p)])
++extern size_t wtf_len1(wc_uchar *p);
+ extern size_t wtf_len(wc_uchar *p);
+ /* extern int wtf_type(wc_uchar *p); */
+ #define wtf_type(p) WTF_TYPE_MAP[(wc_uchar)*(p)]
diff --git a/linein.c b/linein.c
index b7e81b6..d8f9023 100644
--- a/linein.c
@@ -20008,7 +20513,7 @@ index 64fd0ad..bc7a5be 100644
#define SWAPI(a,b) { int tmp = a; a = b; b = tmp; }
diff --git a/menu.c b/menu.c
-index 774b1bd..01acc31 100644
+index 774b1bd..b0c890d 100644
--- a/menu.c
+++ b/menu.c
@@ -57,6 +57,7 @@ static int mCancel(char c);
@@ -20172,6 +20677,15 @@ index 774b1bd..01acc31 100644
Strcat_charp(str, p);
break;
}
+@@ -1696,7 +1741,7 @@ initMenu(void)
+ FILE *mf;
+ MenuList *list;
+
+- w3mMenuList = New_N(MenuList, 3);
++ w3mMenuList = New_N(MenuList, 4);
+ w3mMenuList[0].id = "Main";
+ w3mMenuList[0].menu = &MainMenu;
+ w3mMenuList[0].item = MainMenuItem;
@@ -1845,10 +1890,8 @@ link_menu(Buffer *buf)
Strcat_charp(str, " ");
if (!l->url)
@@ -26690,7 +27204,7 @@ index 50475ae..c047c56 100644
buf[i] = (*p == ' ') ? NBSP_CODE : *p;
diff --git a/table.c b/table.c
-index e1243ff..572ebd6 100644
+index e1243ff..221db92 100644
--- a/table.c
+++ b/table.c
@@ -188,7 +188,7 @@ dv2sv(double *dv, short *iv, int size)
@@ -26728,6 +27242,24 @@ index e1243ff..572ebd6 100644
int alignment;
TextLineListItem *ti;
struct table *t = tbl->tables[id].ptr;
+@@ -961,7 +960,7 @@ set_integered_width(struct table *t, double *dwidth, short *iwidth)
+ for (step = 0; step < 2; step++) {
+ for (i = 0; i <= t->maxcol; i += n) {
+ int nn;
+- char *idx;
++ short *idx;
+ double nsum;
+ if (sum < 0.5)
+ return;
+@@ -982,7 +981,7 @@ set_integered_width(struct table *t, double *dwidth, short *iwidth)
+ (double)rulewidth - mod[ii] > 0.5)
+ fixed[ii] = 1;
+ }
+- idx = NewAtom_N(char, n);
++ idx = NewAtom_N(short, n);
+ for (k = 0; k < cell->maxcell; k++) {
+ int kk, w, width, m;
+ j = cell->index[k];
@@ -1624,6 +1623,15 @@ get_table_width(struct table *t, short *orgwidth, short *cellwidth, int flag)
#define fixed_table_width(t)\
(get_table_width(t,t->fixed_width,t->cell.fixed_width,CHECK_MINIMUM))
@@ -26788,7 +27320,28 @@ index e1243ff..572ebd6 100644
setwidth(tbl, mode);
feed_table_inline_tag(tbl, line, mode, -1);
clearcontentssize(tbl, mode);
-@@ -2600,12 +2620,16 @@ feed_table_tag(struct table *tbl, char *line, struct table_mode *mode,
+@@ -2546,8 +2566,10 @@ feed_table_tag(struct table *tbl, char *line, struct table_mode *mode,
+ }
+ }
+ #ifdef ID_EXT
+- if (parsedtag_get_value(tag, ATTR_ID, &p))
++ if (parsedtag_get_value(tag, ATTR_ID, &p)) {
++ check_row(tbl, tbl->row);
+ tbl->tridvalue[tbl->row] = Strnew_charp(p);
++ }
+ #endif /* ID_EXT */
+ tbl->trattr = align | valign;
+ break;
+@@ -2572,7 +2594,7 @@ feed_table_tag(struct table *tbl, char *line, struct table_mode *mode,
+ }
+ tbl->col++;
+ check_row(tbl, tbl->row);
+- while (tbl->tabattr[tbl->row][tbl->col]) {
++ while (tbl->col < MAXCOL && tbl->tabattr[tbl->row][tbl->col]) {
+ tbl->col++;
+ }
+ if (tbl->col > MAXCOL - 1) {
+@@ -2600,12 +2622,16 @@ feed_table_tag(struct table *tbl, char *line, struct table_mode *mode,
if ((tbl->row + rowspan) >= tbl->max_rowsize)
check_row(tbl, tbl->row + rowspan);
}
@@ -26805,7 +27358,7 @@ index e1243ff..572ebd6 100644
if (parsedtag_get_value(tag, ATTR_ALIGN, &i)) {
switch (i) {
case ALIGN_LEFT:
-@@ -2878,6 +2902,14 @@ feed_table_tag(struct table *tbl, char *line, struct table_mode *mode,
+@@ -2878,6 +2904,14 @@ feed_table_tag(struct table *tbl, char *line, struct table_mode *mode,
tmp = process_input(tag);
feed_table1(tbl, tmp, mode, width);
break;
@@ -26820,7 +27373,7 @@ index e1243ff..572ebd6 100644
case HTML_SELECT:
tmp = process_select(tag);
if (tmp)
-@@ -3010,7 +3042,6 @@ feed_table_tag(struct table *tbl, char *line, struct table_mode *mode,
+@@ -3010,7 +3044,6 @@ feed_table_tag(struct table *tbl, char *line, struct table_mode *mode,
break;
case HTML_TABLE_ALT:
id = -1;