Compare commits
No commits in common. "c8" and "c8-beta" have entirely different histories.
@ -1,99 +0,0 @@
|
||||
From ed0c7c7e0e8f7298352646b2fd6e06a11e242ace Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Tim=20R=C3=BChsen?= <tim.ruehsen@gmx.de>
|
||||
Date: Sun, 2 Jun 2024 12:40:16 +0200
|
||||
Subject: Properly re-implement userinfo parsing (rfc2396)
|
||||
|
||||
* src/url.c (url_skip_credentials): Properly re-implement userinfo parsing (rfc2396)
|
||||
|
||||
The reason why the implementation is based on RFC 2396, an outdated standard,
|
||||
is that the whole file is based on that RFC, and mixing standard here might be
|
||||
dangerous.
|
||||
---
|
||||
src/url.c | 40 ++++++++++++++++++++++++++++++++++------
|
||||
1 file changed, 34 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/url.c b/src/url.c
|
||||
index 69e948b..07c3bc8 100644
|
||||
--- a/src/url.c
|
||||
+++ b/src/url.c
|
||||
@@ -41,6 +41,7 @@ as that of the covered work. */
|
||||
#include "url.h"
|
||||
#include "host.h" /* for is_valid_ipv6_address */
|
||||
#include "c-strcase.h"
|
||||
+#include "c-ctype.h"
|
||||
|
||||
#ifdef HAVE_ICONV
|
||||
# include <iconv.h>
|
||||
@@ -526,12 +527,39 @@ scheme_leading_string (enum url_scheme scheme)
|
||||
static const char *
|
||||
url_skip_credentials (const char *url)
|
||||
{
|
||||
- /* Look for '@' that comes before terminators, such as '/', '?',
|
||||
- '#', or ';'. */
|
||||
- const char *p = (const char *)strpbrk (url, "@/?#;");
|
||||
- if (!p || *p != '@')
|
||||
- return url;
|
||||
- return p + 1;
|
||||
+ /*
|
||||
+ * This whole file implements https://www.rfc-editor.org/rfc/rfc2396 .
|
||||
+ * RFC 2396 is outdated since 2005 and needs a rewrite or a thorough re-visit.
|
||||
+ *
|
||||
+ * The RFC says
|
||||
+ * server = [ [ userinfo "@" ] hostport ]
|
||||
+ * userinfo = *( unreserved | escaped | ";" | ":" | "&" | "=" | "+" | "$" | "," )
|
||||
+ * unreserved = alphanum | mark
|
||||
+ * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
|
||||
+ */
|
||||
+ static const char *allowed = "-_.!~*'();:&=+$,";
|
||||
+
|
||||
+ for (const char *p = url; *p; p++)
|
||||
+ {
|
||||
+ if (c_isalnum(*p))
|
||||
+ continue;
|
||||
+
|
||||
+ if (strchr(allowed, *p))
|
||||
+ continue;
|
||||
+
|
||||
+ if (*p == '%' && c_isxdigit(p[1]) && c_isxdigit(p[2]))
|
||||
+ {
|
||||
+ p += 2;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (*p == '@')
|
||||
+ return p + 1;
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return url;
|
||||
}
|
||||
|
||||
/* Parse credentials contained in [BEG, END). The region is expected
|
||||
--
|
||||
cgit v1.1
|
||||
|
||||
diff --git a/tests/Test-proxied-https-auth.px.old b/tests/Test-proxied-https-auth.px
|
||||
index 83e0210..76617ce 100755
|
||||
--- a/tests/Test-proxied-https-auth.px.old
|
||||
+++ b/tests/Test-proxied-https-auth.px
|
||||
@@ -32,6 +32,7 @@ if (defined $srcdir) {
|
||||
use HTTP::Daemon;
|
||||
use HTTP::Request;
|
||||
# Skip this test rather than fail it when the module isn't installed
|
||||
+exit 77;
|
||||
if (!eval {require IO::Socket::SSL;1;}) {
|
||||
print STDERR "This test needs the perl module \"IO::Socket::SSL\".\n";
|
||||
print STDERR "Install e.g. on Debian with 'apt-get install libio-socket-ssl-perl'\n";
|
||||
diff --git a/tests/Test-proxied-https-auth-keepalive.px.old b/tests/Test-proxied-https-auth-keepalive.px
|
||||
index 2a18ccf..80a8603 100755
|
||||
--- a/tests/Test-proxied-https-auth-keepalive.px.old
|
||||
+++ b/tests/Test-proxied-https-auth-keepalive.px
|
||||
@@ -32,6 +32,7 @@ if (defined $srcdir) {
|
||||
use HTTP::Daemon;
|
||||
use HTTP::Request;
|
||||
# Skip this test rather than fail it when the module isn't installed
|
||||
+exit 77;
|
||||
if (!eval {require IO::Socket::SSL;1;}) {
|
||||
print STDERR "This test needs the perl module \"IO::Socket::SSL\".\n";
|
||||
print STDERR "Install e.g. on Debian with 'apt-get install libio-socket-ssl-perl'\n";
|
||||
@ -1,103 +0,0 @@
|
||||
From b2f6dfe67d78c82071842e3d7ea3447b3ff24e8f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Tim=20R=C3=BChsen?= <tim.ruehsen@gmx.de>
|
||||
Date: Mon, 29 Jun 2026 18:32:02 +0200
|
||||
Subject: [PATCH 1/3] * src/metalink.c (clean_metalink_string): Fix buffer
|
||||
underflow
|
||||
|
||||
Reported-by: TristanInSec@gmail.com
|
||||
---
|
||||
src/metalink.c | 9 +++------
|
||||
1 file changed, 3 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/metalink.c b/src/metalink.c
|
||||
index 47c8acc..58a9fd5 100644
|
||||
--- a/src/metalink.c
|
||||
+++ b/src/metalink.c
|
||||
@@ -1043,7 +1043,6 @@ void
|
||||
clean_metalink_string (char **str)
|
||||
{
|
||||
int c;
|
||||
- size_t len;
|
||||
char *new, *beg, *end;
|
||||
|
||||
if (!str || !*str)
|
||||
@@ -1051,7 +1050,7 @@ clean_metalink_string (char **str)
|
||||
|
||||
beg = *str;
|
||||
|
||||
- while ((c = *beg) && (c == '\n' || c == '\r' || c == '\t' || c == ' '))
|
||||
+ while (isspace(*beg))
|
||||
beg++;
|
||||
|
||||
end = beg;
|
||||
@@ -1064,12 +1063,10 @@ clean_metalink_string (char **str)
|
||||
/* If we are at the end of the string, search the first legit
|
||||
character going backward. */
|
||||
if (*end == '\0')
|
||||
- while ((c = *(end - 1)) && (c == '\n' || c == '\r' || c == '\t' || c == ' '))
|
||||
+ while (end > beg && !isspace(*(end - 1)))
|
||||
end--;
|
||||
|
||||
- len = end - beg;
|
||||
-
|
||||
- new = xmemdup0 (beg, len);
|
||||
+ new = xmemdup0 (beg, end - beg);
|
||||
xfree (*str);
|
||||
*str = new;
|
||||
}
|
||||
|
||||
From 989ba32056757509631d6588e47a59a9a06f8a36 Mon Sep 17 00:00:00 2001
|
||||
From: ChenYanpan <chenyanpan@xfusion.com>
|
||||
Date: Wed, 8 Jul 2026 12:09:55 +0800
|
||||
Subject: [PATCH 2/3] * src/metalink.c (clean_metalink_string): Fix inverted
|
||||
trailing-space check
|
||||
|
||||
37a40fcb added an `end > beg' bound guard to prevent a buffer
|
||||
underflow, but accidentally flipped the condition from `isspace' to
|
||||
`!isspace'. The loop therefore walked back over non-space characters
|
||||
instead of trailing whitespace, collapsing any string without a
|
||||
trailing newline to "". Every Metalink/HTTP resource URL was wiped,
|
||||
so wget could not follow any mirror and
|
||||
testenv/Test-metalink-http.py failed ("Expected file test.meta not
|
||||
found"). Restore the `isspace' condition.
|
||||
|
||||
Copyright-paperwork-exempt: Yes
|
||||
---
|
||||
src/metalink.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/metalink.c b/src/metalink.c
|
||||
index 58a9fd5..084c262 100644
|
||||
--- a/src/metalink.c
|
||||
+++ b/src/metalink.c
|
||||
@@ -1063,7 +1063,7 @@ clean_metalink_string (char **str)
|
||||
/* If we are at the end of the string, search the first legit
|
||||
character going backward. */
|
||||
if (*end == '\0')
|
||||
- while (end > beg && !isspace(*(end - 1)))
|
||||
+ while (end > beg && isspace(*(end - 1)))
|
||||
end--;
|
||||
|
||||
new = xmemdup0 (beg, end - beg);
|
||||
|
||||
From 26af7a227b1af4219ba66898afbedec62c26bcd8 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Tim=20R=C3=BChsen?= <tim.ruehsen@gmx.de>
|
||||
Date: Thu, 9 Jul 2026 14:50:40 +0200
|
||||
Subject: [PATCH 3/3] * src/metalink.c: Include ctype.h
|
||||
|
||||
---
|
||||
src/metalink.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/metalink.c b/src/metalink.c
|
||||
index 084c262..96bfd46 100644
|
||||
--- a/src/metalink.c
|
||||
+++ b/src/metalink.c
|
||||
@@ -46,6 +46,7 @@ as that of the covered work. */
|
||||
#include "c-strcase.h"
|
||||
#include <errno.h>
|
||||
#include <unistd.h> /* For unlink. */
|
||||
+#include <ctype.h>
|
||||
#include <metalink/metalink_parser.h>
|
||||
#ifdef HAVE_GPGME
|
||||
#include <gpgme.h>
|
||||
@ -1,65 +0,0 @@
|
||||
From 3514c0f2ad4e3d8a2e9ad0893accdb7a21cae729 Mon Sep 17 00:00:00 2001
|
||||
From: Arkadi Vainbrand <arkadva8@gmail.com>
|
||||
Date: Tue, 13 Jan 2026 12:22:04 +0200
|
||||
Subject: [PATCH] Fix buffer size handling in filename conversion
|
||||
|
||||
* src/url.c (convert_fname): Fix buffer overflow.
|
||||
|
||||
Copyright-paperwork-exempt: Yes
|
||||
Signed-off-by: Arkadi Vainbrand <arkadva8@gmail.com>
|
||||
---
|
||||
src/url.c | 20 +++++++++++++-------
|
||||
1 file changed, 13 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/url.c b/src/url.c
|
||||
index ebe0536..848b88f 100644
|
||||
--- a/src/url.c
|
||||
+++ b/src/url.c
|
||||
@@ -1583,7 +1583,7 @@ convert_fname (char *fname)
|
||||
const char *from_encoding = opt.encoding_remote;
|
||||
const char *to_encoding = opt.locale;
|
||||
iconv_t cd;
|
||||
- size_t len, done, inlen, outlen;
|
||||
+ size_t len, inlen, outlen;
|
||||
char *s;
|
||||
const char *orig_fname;
|
||||
|
||||
@@ -1605,7 +1605,6 @@ convert_fname (char *fname)
|
||||
inlen = strlen (fname);
|
||||
len = outlen = inlen * 2;
|
||||
converted_fname = s = xmalloc (outlen + 1);
|
||||
- done = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@@ -1613,7 +1612,7 @@ convert_fname (char *fname)
|
||||
if (iconv (cd, (ICONV_CONST char **) &fname, &inlen, &s, &outlen) == 0
|
||||
&& iconv (cd, NULL, NULL, &s, &outlen) == 0)
|
||||
{
|
||||
- *(converted_fname + len - outlen - done) = '\0';
|
||||
+ *s = '\0';
|
||||
iconv_close (cd);
|
||||
DEBUGP (("Converted file name '%s' (%s) -> '%s' (%s)\n",
|
||||
orig_fname, from_encoding, converted_fname, to_encoding));
|
||||
@@ -1636,10 +1635,17 @@ convert_fname (char *fname)
|
||||
}
|
||||
else if (errno == E2BIG) /* Output buffer full */
|
||||
{
|
||||
- done = len;
|
||||
- len = outlen = done + inlen * 2;
|
||||
- converted_fname = xrealloc (converted_fname, outlen + 1);
|
||||
- s = converted_fname + done;
|
||||
+ size_t used = s - converted_fname;
|
||||
+ size_t newlen = used + inlen * 2 + 1;
|
||||
+
|
||||
+ /* Ensure we actually grow the buffer */
|
||||
+ if (newlen <= len)
|
||||
+ newlen = len * 2;
|
||||
+
|
||||
+ converted_fname = xrealloc (converted_fname, newlen + 1);
|
||||
+ len = newlen;
|
||||
+ s = converted_fname + used;
|
||||
+ outlen = len - used;
|
||||
}
|
||||
else /* Weird, we got an unspecified error */
|
||||
{
|
||||
@ -1,264 +0,0 @@
|
||||
From 2133f09782cefec5f174218d8d984744277fa891 Mon Sep 17 00:00:00 2001
|
||||
From: RHEL Packaging Agent <redhat-ymir-agent@redhat.com>
|
||||
Date: Wed, 15 Jul 2026 10:38:03 +0000
|
||||
Subject: [PATCH] Fix CVE-2026-58472: integer+buffer overflow in
|
||||
html_quote_string()
|
||||
|
||||
Backport of upstream commits dd692d9 and f76978a, adapted to use
|
||||
INT_ADD_WRAPV (available in wget 1.19.5 gnulib) instead of INT_ADD_OK
|
||||
(not available in this gnulib version).
|
||||
|
||||
* src/convert.c (html_quote_string): Fix integer+buffer overflow using
|
||||
overflow-safe integer arithmetic via INT_ADD_WRAPV.
|
||||
Fix string size calculation regression (+1 per special character).
|
||||
Add unit tests for construct_relative, match_except_index,
|
||||
find_fragment, and html_quote_string.
|
||||
* tests/unit-tests.c: Register new test functions.
|
||||
* tests/unit-tests.h: Declare new test functions.
|
||||
---
|
||||
src/convert.c | 171 +++++++++++++++++++++++++++++++++++++++++++--
|
||||
tests/unit-tests.c | 4 ++
|
||||
tests/unit-tests.h | 4 ++
|
||||
3 files changed, 172 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/convert.c b/src/convert.c
|
||||
index e6ca8fbb..1284d991 100644
|
||||
--- a/src/convert.c
|
||||
+++ b/src/convert.c
|
||||
@@ -36,6 +36,7 @@ as that of the covered work. */
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
+#include <intprops.h>
|
||||
#include "convert.h"
|
||||
#include "url.h"
|
||||
#include "recur.h"
|
||||
@@ -47,6 +48,9 @@ as that of the covered work. */
|
||||
#include "css-url.h"
|
||||
#include "iri.h"
|
||||
#include "xstrndup.h"
|
||||
+#ifdef TESTING
|
||||
+#include "../tests/unit-tests.h"
|
||||
+#endif
|
||||
|
||||
static struct hash_table *dl_file_url_map;
|
||||
struct hash_table *dl_url_file_map;
|
||||
@@ -1131,21 +1135,37 @@ html_quote_string (const char *s)
|
||||
{
|
||||
const char *b = s;
|
||||
char *p, *res;
|
||||
- int i;
|
||||
+ size_t i;
|
||||
+ int ok;
|
||||
|
||||
/* Pass through the string, and count the new size. */
|
||||
- for (i = 0; *s; s++, i++)
|
||||
+ for (i = 0; *s; s++)
|
||||
{
|
||||
if (*s == '&')
|
||||
- i += 4; /* `amp;' */
|
||||
+ ok = !INT_ADD_WRAPV (i, 4 + 1, &i); /* `amp;' */
|
||||
else if (*s == '<' || *s == '>')
|
||||
- i += 3; /* `lt;' and `gt;' */
|
||||
+ ok = !INT_ADD_WRAPV (i, 3 + 1, &i); /* `lt;' and `gt;' */
|
||||
else if (*s == '\"')
|
||||
- i += 5; /* `quot;' */
|
||||
+ ok = !INT_ADD_WRAPV (i, 5 + 1, &i); /* `quot;' */
|
||||
else if (*s == ' ')
|
||||
- i += 4; /* #32; */
|
||||
+ ok = !INT_ADD_WRAPV (i, 4 + 1, &i); /* #32; */
|
||||
+ else
|
||||
+ ok = !INT_ADD_WRAPV (i, 1, &i);
|
||||
+
|
||||
+ if (!ok)
|
||||
+ {
|
||||
+ DEBUGP (("Overflow detected in html_quote_string().\n"));
|
||||
+ abort();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (INT_ADD_WRAPV (i, 1, &i))
|
||||
+ {
|
||||
+ DEBUGP (("Overflow detected in html_quote_string().\n"));
|
||||
+ abort();
|
||||
}
|
||||
- res = xmalloc (i + 1);
|
||||
+
|
||||
+ res = xmalloc (i);
|
||||
s = b;
|
||||
for (p = res; *s; s++)
|
||||
{
|
||||
@@ -1187,6 +1207,143 @@ html_quote_string (const char *s)
|
||||
return res;
|
||||
}
|
||||
|
||||
+#ifdef TESTING
|
||||
+
|
||||
+const char *
|
||||
+test_construct_relative (void)
|
||||
+{
|
||||
+ static const struct {
|
||||
+ const char *basefile;
|
||||
+ const char *linkfile;
|
||||
+ const char *expected;
|
||||
+ } test_array[] = {
|
||||
+ { "foo", "bar", "bar" },
|
||||
+ { "A/foo", "A/bar", "bar" },
|
||||
+ { "A/foo", "A/B/bar", "B/bar" },
|
||||
+ { "A/X/foo", "A/Y/bar", "../Y/bar" },
|
||||
+ { "X/", "Y/bar", "../Y/bar" },
|
||||
+ { "/foo", "/bar", "bar" },
|
||||
+ { "/a/b/c", "/a/b/d", "d" },
|
||||
+ { "/a/b/c", "/a/b/c/d", "c/d" },
|
||||
+ { "/a/b/c", "/a/b/c/d/e", "c/d/e" },
|
||||
+ { "/a/b/c", "/x/y/z", "../../x/y/z" },
|
||||
+ { "a/b", "c/d", "../c/d" },
|
||||
+ { "./foo", "./bar", "bar" },
|
||||
+ };
|
||||
+
|
||||
+ for (unsigned i = 0; i < countof (test_array); ++i)
|
||||
+ {
|
||||
+ char *result = construct_relative (test_array[i].basefile,
|
||||
+ test_array[i].linkfile);
|
||||
+ mu_assert ("test_construct_relative: wrong result",
|
||||
+ strcmp (result, test_array[i].expected) == 0);
|
||||
+ xfree (result);
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+const char *
|
||||
+test_match_except_index (void)
|
||||
+{
|
||||
+ static const struct {
|
||||
+ const char *s1;
|
||||
+ const char *s2;
|
||||
+ bool expected;
|
||||
+ } test_array[] = {
|
||||
+ { "foo/index.html", "foo/", true },
|
||||
+ { "foo/", "foo/index.html", true },
|
||||
+ { "foo", "foo/index.html", true },
|
||||
+ { "foo", "foo/", true },
|
||||
+ { "foo", "foo", true },
|
||||
+ { "/foo/index.html", "/foo/", true },
|
||||
+ { "/foo/", "/foo/index.html", true },
|
||||
+ { "/foo", "/foo/index.html", true },
|
||||
+ { "/foo", "/foo/", true },
|
||||
+ { "foo/bar", "foo/qux", false },
|
||||
+ { "foo/bar", "bar/foo", false },
|
||||
+ };
|
||||
+
|
||||
+ for (unsigned i = 0; i < countof (test_array); ++i)
|
||||
+ {
|
||||
+ bool result = match_except_index (test_array[i].s1, test_array[i].s2);
|
||||
+ mu_assert ("test_match_except_index: wrong result",
|
||||
+ result == test_array[i].expected);
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+const char *
|
||||
+test_find_fragment (void)
|
||||
+{
|
||||
+ static const struct {
|
||||
+ const char *input;
|
||||
+ int size;
|
||||
+ bool has_fragment;
|
||||
+ const char *fragment;
|
||||
+ } test_array[] = {
|
||||
+ { "http://example.com#section", 26, true, "#section" },
|
||||
+ { "http://example.com", 18, false, NULL },
|
||||
+ { "http://example.com?a=1#frag", 24, true, "#frag" },
|
||||
+ { "http://example.com?a=1%26#frag", 28, true, "#frag" },
|
||||
+ { "http://example.com?a=1&b=2#frag", 30, true, "#frag" },
|
||||
+ { "a#b", 3, true, "#b" },
|
||||
+ { "a", 1, false, NULL },
|
||||
+ };
|
||||
+ const char *bp, *ep;
|
||||
+
|
||||
+ for (unsigned i = 0; i < countof (test_array); ++i)
|
||||
+ {
|
||||
+ bool result = find_fragment (test_array[i].input,
|
||||
+ test_array[i].size, &bp, &ep);
|
||||
+ mu_assert ("test_find_fragment: wrong result",
|
||||
+ result == test_array[i].has_fragment);
|
||||
+ if (test_array[i].has_fragment)
|
||||
+ {
|
||||
+ mu_assert ("test_find_fragment: wrong fragment", bp != NULL);
|
||||
+ mu_assert ("test_find_fragment: fragment mismatch",
|
||||
+ strncmp (bp, test_array[i].fragment,
|
||||
+ strlen (test_array[i].fragment)) == 0 &&
|
||||
+ ep == test_array[i].input + test_array[i].size);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+const char *
|
||||
+test_html_quote_string (void)
|
||||
+{
|
||||
+ static const struct {
|
||||
+ const char *input;
|
||||
+ const char *expected;
|
||||
+ } test_array[] = {
|
||||
+ { "hello", "hello" },
|
||||
+ { "a&b", "a&b" },
|
||||
+ { "<tag>", "<tag>" },
|
||||
+ { "\"quote\"", ""quote"" },
|
||||
+ { "space here", "space here" },
|
||||
+ { "&<>\" ", "&<>" " },
|
||||
+ { "no special", "no special" },
|
||||
+ { "&&&&", "&&&&" },
|
||||
+ { "<<>>", "<<>>" },
|
||||
+ { "" , "" },
|
||||
+ };
|
||||
+
|
||||
+ for (unsigned i = 0; i < countof (test_array); ++i)
|
||||
+ {
|
||||
+ char *result = html_quote_string (test_array[i].input);
|
||||
+ mu_assert ("test_html_quote_string: wrong result",
|
||||
+ strcmp (result, test_array[i].expected) == 0);
|
||||
+ xfree (result);
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+#endif /* TESTING */
|
||||
+
|
||||
/*
|
||||
* vim: et ts=2 sw=2
|
||||
*/
|
||||
diff --git a/tests/unit-tests.c b/tests/unit-tests.c
|
||||
index 0db434be..f3149343 100644
|
||||
--- a/tests/unit-tests.c
|
||||
+++ b/tests/unit-tests.c
|
||||
@@ -64,6 +64,10 @@ all_tests(void)
|
||||
mu_run_test (test_hsts_url_rewrite_congruent);
|
||||
mu_run_test (test_hsts_read_database);
|
||||
#endif
|
||||
+ mu_run_test (test_construct_relative);
|
||||
+ mu_run_test (test_match_except_index);
|
||||
+ mu_run_test (test_find_fragment);
|
||||
+ mu_run_test (test_html_quote_string);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
diff --git a/tests/unit-tests.h b/tests/unit-tests.h
|
||||
index 74552120..002a785f 100644
|
||||
--- a/tests/unit-tests.h
|
||||
+++ b/tests/unit-tests.h
|
||||
@@ -60,6 +60,10 @@ const char *test_hsts_new_entry(void);
|
||||
const char *test_hsts_url_rewrite_superdomain(void);
|
||||
const char *test_hsts_url_rewrite_congruent(void);
|
||||
const char *test_hsts_read_database(void);
|
||||
+const char *test_construct_relative(void);
|
||||
+const char *test_match_except_index(void);
|
||||
+const char *test_find_fragment(void);
|
||||
+const char *test_html_quote_string(void);
|
||||
|
||||
#endif /* TEST_H */
|
||||
|
||||
@ -1,110 +0,0 @@
|
||||
From e1f2559efad5e2733ded804f9f1ba8acd8c4de61 Mon Sep 17 00:00:00 2001
|
||||
From: Michal Ruprich <michalruprich@gmail.com>
|
||||
Date: Tue, 14 Jul 2026 16:35:42 +0200
|
||||
Subject: [PATCH] Moving async signal unsafe functions out of signal handler
|
||||
|
||||
There is a very rare race condition in function redirect_output_signal().
|
||||
If SIGHUP is received while wget is in malloc() function and a new
|
||||
logfile is opened with fopen, another malloc() is called. malloc() is
|
||||
not an async signal safe function and should not be called from within a
|
||||
signal handler.
|
||||
|
||||
* src/main.c (redirect_output_signal): do not call redirect_output(),
|
||||
add an atomic flag.
|
||||
* src/log.c (check_redirect_output): move redirect_output() here since this
|
||||
is not in a signal handler
|
||||
|
||||
Copyright-paperwork-exempt: Yes
|
||||
---
|
||||
src/log.c | 26 ++++++++++++++++++++++++++
|
||||
src/main.c | 21 ++++++++-------------
|
||||
2 files changed, 34 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/src/log.c b/src/log.c
|
||||
index fe8c3982..17511327 100644
|
||||
--- a/src/log.c
|
||||
+++ b/src/log.c
|
||||
@@ -37,11 +37,16 @@ as that of the covered work. */
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
+#include <signal.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "exits.h"
|
||||
#include "log.h"
|
||||
|
||||
+#if defined(SIGHUP) || defined(SIGUSR1)
|
||||
+extern volatile sig_atomic_t redirect_output_sig;
|
||||
+#endif
|
||||
+
|
||||
/* 2005-10-25 SMS.
|
||||
VMS log files are often VFC record format, not stream, so fputs() can
|
||||
produce multiple records, even when there's no newline terminator in
|
||||
@@ -973,6 +978,27 @@ static void
|
||||
check_redirect_output (void)
|
||||
{
|
||||
#ifndef WINDOWS
|
||||
+#if defined(SIGHUP) || defined(SIGUSR1)
|
||||
+ {
|
||||
+ int sig = redirect_output_sig;
|
||||
+ if (sig)
|
||||
+ {
|
||||
+ redirect_output_sig = 0;
|
||||
+ const char *signal_name = "WTF?!";
|
||||
+#ifdef SIGHUP
|
||||
+ if (sig == SIGHUP)
|
||||
+ signal_name = "SIGHUP";
|
||||
+#endif
|
||||
+#ifdef SIGUSR1
|
||||
+ if (sig == SIGUSR1)
|
||||
+ signal_name = "SIGUSR1";
|
||||
+#endif
|
||||
+ redirect_output (true, signal_name);
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+#endif /* defined(SIGHUP) || defined(SIGUSR1) */
|
||||
+
|
||||
/* If it was redirected already to log file by SIGHUP, SIGUSR1 or -o parameter,
|
||||
* it was permanent.
|
||||
* If there was no SIGHUP or SIGUSR1 and shell is interactive
|
||||
diff --git a/src/main.c b/src/main.c
|
||||
index a10a17f3..3926f501 100644
|
||||
--- a/src/main.c
|
||||
+++ b/src/main.c
|
||||
@@ -123,23 +123,18 @@ int numurls = 0;
|
||||
#if defined(SIGHUP) || defined(SIGUSR1)
|
||||
/* Hangup signal handler. When wget receives SIGHUP or SIGUSR1, it
|
||||
will proceed operation as usual, trying to write into a log file.
|
||||
- If that is impossible, the output will be turned off. */
|
||||
+ If that is impossible, the output will be turned off.
|
||||
+
|
||||
+ Only async-signal-safe operations are performed here. The actual
|
||||
+ redirect (which needs malloc/fopen) is deferred to
|
||||
+ check_redirect_output(), called from the logging functions. */
|
||||
+
|
||||
+volatile sig_atomic_t redirect_output_sig = 0;
|
||||
|
||||
static void
|
||||
redirect_output_signal (int sig)
|
||||
{
|
||||
- const char *signal_name = "WTF?!";
|
||||
-
|
||||
-#ifdef SIGHUP
|
||||
- if (sig == SIGHUP)
|
||||
- signal_name = "SIGHUP";
|
||||
-#endif
|
||||
-#ifdef SIGUSR1
|
||||
- if (sig == SIGUSR1)
|
||||
- signal_name = "SIGUSR1";
|
||||
-#endif
|
||||
-
|
||||
- redirect_output (true,signal_name);
|
||||
+ redirect_output_sig = sig;
|
||||
progress_schedule_redirect ();
|
||||
signal (sig, redirect_output_signal);
|
||||
}
|
||||
--
|
||||
GitLab
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
Summary: A utility for retrieving files using the HTTP or FTP protocols
|
||||
Name: wget
|
||||
Version: 1.19.5
|
||||
Release: 16%{?dist}
|
||||
Release: 11%{?dist}
|
||||
License: GPLv3+
|
||||
Group: Applications/Internet
|
||||
Url: http://www.gnu.org/software/wget/
|
||||
@ -23,18 +23,6 @@ Patch10: wget-1.19.5-no_proxy-tests.patch
|
||||
# http://git.savannah.gnu.org/cgit/wget.git/commit/?id=706e71564cadc7192ac21efbf51b661c967f35b5
|
||||
Patch11: wget-1.19.5-ca-cert-too-verbose.patch
|
||||
Patch12: wget-1.19.5-no-log-when-quiet.patch
|
||||
Patch13: wget-1.19.5-CVE-2024-38428.patch
|
||||
# https://gitlab.com/gnuwget/wget/-/commit/dd692d9cea5335b181d877ae917fe6e75587a812
|
||||
# https://gitlab.com/gnuwget/wget/-/commit/f76978a51ba9365e7ecaed96c1cfb73197a38ca2
|
||||
Patch14: wget-1.19.5-CVE-2026-58472.patch
|
||||
# https://gitlab.com/gnuwget/wget/-/commit/3514c0f2ad4e3d8a2e9ad0893accdb7a21cae729
|
||||
Patch15: wget-1.19.5-CVE-2026-58471.patch
|
||||
# https://gitlab.com/gnuwget/wget/-/commit/37a40fcb450153f69537c7cbc2a7a4fb0b6f7826
|
||||
# https://gitlab.com/gnuwget/wget/-/commit/7b1cdecc49bc77bde220fc575c8a00386c3f3bcf
|
||||
# https://gitlab.com/gnuwget/wget/-/commit/82d945ff5dc9942b78b2bf736aac298c24fe00a1
|
||||
Patch16: wget-1.19.5-CVE-2026-58469.patch
|
||||
# https://gitlab.com/gnuwget/wget/-/merge_requests/72
|
||||
Patch17: wget-1.19.5-async-safe-signal-handler.patch
|
||||
|
||||
Provides: webclient
|
||||
Provides: bundled(gnulib)
|
||||
@ -72,11 +60,6 @@ grep "PACKAGE_STRING='wget .* (Red Hat modified)'" configure || exit 1
|
||||
%patch10 -p1 -b .no_proxy-test
|
||||
%patch11 -p1 -b .too_verbose
|
||||
%patch12 -p1 -b .no-log-quiet
|
||||
%patch13 -p1 -b .CVE-2024-38428
|
||||
%patch14 -p1 -b .CVE-2026-58472
|
||||
%patch15 -p1 -b .CVE-2026-58471
|
||||
%patch16 -p1 -b .CVE-2026-58469
|
||||
%patch17 -p1 -b .async-signal-handler
|
||||
|
||||
%build
|
||||
%configure \
|
||||
@ -123,24 +106,6 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%{_infodir}/*
|
||||
|
||||
%changelog
|
||||
* Tue Aug 04 2026 Michal Ruprich <mruprich@redhat.com> - 1.19.5-16
|
||||
- Resolves: RHEL-145875 - async unsafe code in signal handler context
|
||||
|
||||
* Tue Jul 21 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 1.19.5-15
|
||||
- Fix CVE-2026-58469: buffer underflow in clean_metalink_string()
|
||||
- Resolves: RHEL-212496
|
||||
|
||||
* Wed Jul 15 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 1.19.5-14
|
||||
- Fix CVE-2026-58471: buffer overflow in convert_fname()
|
||||
- Resolves: RHEL-194519
|
||||
|
||||
* Wed Jul 15 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 1.19.5-13
|
||||
- Fix CVE-2026-58472: integer and buffer overflow in html_quote_string()
|
||||
- Resolves: RHEL-210627
|
||||
|
||||
* Wed Jul 10 2024 Michal Ruprich <mruprich@redhat.com> - 1.19.5-12
|
||||
- Resolves: RHEL-43559 - Misinterpretation of input may lead to improper behavior
|
||||
|
||||
* Tue Dec 13 2022 Michal Ruprich <mruprich@redhat.com> - 1.19.5-11
|
||||
- Resolves: #2152731 - Running wget with -O and -q in the background yields a file wget-log
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user