git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH 0/3] mixed bag of -Wunused-parameter bugfixes
@ 2018-11-02  5:22 Jeff King
  2018-11-02  5:22 ` [PATCH 1/3] rev-list: handle flags for --indexed-objects Jeff King
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Jeff King @ 2018-11-02  5:22 UTC (permalink / raw)
  To: git

Here are three minor bug-fixes that can be applied independently. The
common thread is that I found them by looking at the results of
compiling with -Wunused-parameter. In each of these cases, the parameter
_should_ be used, and not doing so was a bug.

  [1/3]: rev-list: handle flags for --indexed-objects
  [2/3]: approxidate: handle pending number for "specials"
  [3/3]: pathspec: handle non-terminated strings with :(attr)

 date.c                   | 60 ++++++++++++++++++++++------------------
 dir.c                    |  7 +++++
 revision.c               | 15 ++++++----
 t/t0006-date.sh          |  1 +
 t/t6000-rev-list-misc.sh |  7 +++++
 5 files changed, 57 insertions(+), 33 deletions(-)

-Peff

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] rev-list: handle flags for --indexed-objects
  2018-11-02  5:22 [PATCH 0/3] mixed bag of -Wunused-parameter bugfixes Jeff King
@ 2018-11-02  5:22 ` Jeff King
  2018-11-02  5:23 ` [PATCH 2/3] approxidate: handle pending number for "specials" Jeff King
  2018-11-02  5:23 ` [PATCH 3/3] pathspec: handle non-terminated strings with :(attr) Jeff King
  2 siblings, 0 replies; 7+ messages in thread
From: Jeff King @ 2018-11-02  5:22 UTC (permalink / raw)
  To: git

When a traversal sees the --indexed-objects option, it adds
all blobs and valid cache-trees from the index to the
traversal using add_index_objects_to_pending(). But that
function totally ignores its flags parameter!

That means that doing:

  git rev-list --objects --indexed-objects

and

  git rev-list --objects --not --indexed-objects

produce the same output, because we ignore the UNINTERESTING
flag when walking the index in the second example.

Nobody noticed because this feature was added as a way for
tools like repack to increase their coverage of reachable
objects, meaning it would only be used like the first
example above.

But since it's user facing (and because the documentation
describes it "as if the objects are listed on the command
line"), we should make sure the negative case behaves
sensibly.

Signed-off-by: Jeff King <peff@peff.net>
---
 revision.c               | 15 +++++++++------
 t/t6000-rev-list-misc.sh |  7 +++++++
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/revision.c b/revision.c
index a1ddb9e11c..8e56c9641f 100644
--- a/revision.c
+++ b/revision.c
@@ -1321,13 +1321,14 @@ void add_reflogs_to_pending(struct rev_info *revs, unsigned flags)
 }
 
 static void add_cache_tree(struct cache_tree *it, struct rev_info *revs,
-			   struct strbuf *path)
+			   struct strbuf *path, unsigned int flags)
 {
 	size_t baselen = path->len;
 	int i;
 
 	if (it->entry_count >= 0) {
 		struct tree *tree = lookup_tree(revs->repo, &it->oid);
+		tree->object.flags |= flags;
 		add_pending_object_with_path(revs, &tree->object, "",
 					     040000, path->buf);
 	}
@@ -1335,14 +1336,15 @@ static void add_cache_tree(struct cache_tree *it, struct rev_info *revs,
 	for (i = 0; i < it->subtree_nr; i++) {
 		struct cache_tree_sub *sub = it->down[i];
 		strbuf_addf(path, "%s%s", baselen ? "/" : "", sub->name);
-		add_cache_tree(sub->cache_tree, revs, path);
+		add_cache_tree(sub->cache_tree, revs, path, flags);
 		strbuf_setlen(path, baselen);
 	}
 
 }
 
 static void do_add_index_objects_to_pending(struct rev_info *revs,
-					    struct index_state *istate)
+					    struct index_state *istate,
+					    unsigned int flags)
 {
 	int i;
 
@@ -1356,13 +1358,14 @@ static void do_add_index_objects_to_pending(struct rev_info *revs,
 		blob = lookup_blob(revs->repo, &ce->oid);
 		if (!blob)
 			die("unable to add index blob to traversal");
+		blob->object.flags |= flags;
 		add_pending_object_with_path(revs, &blob->object, "",
 					     ce->ce_mode, ce->name);
 	}
 
 	if (istate->cache_tree) {
 		struct strbuf path = STRBUF_INIT;
-		add_cache_tree(istate->cache_tree, revs, &path);
+		add_cache_tree(istate->cache_tree, revs, &path, flags);
 		strbuf_release(&path);
 	}
 }
@@ -1372,7 +1375,7 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned int flags)
 	struct worktree **worktrees, **p;
 
 	read_index(revs->repo->index);
-	do_add_index_objects_to_pending(revs, revs->repo->index);
+	do_add_index_objects_to_pending(revs, revs->repo->index, flags);
 
 	if (revs->single_worktree)
 		return;
@@ -1388,7 +1391,7 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned int flags)
 		if (read_index_from(&istate,
 				    worktree_git_path(wt, "index"),
 				    get_worktree_git_dir(wt)) > 0)
-			do_add_index_objects_to_pending(revs, &istate);
+			do_add_index_objects_to_pending(revs, &istate, flags);
 		discard_index(&istate);
 	}
 	free_worktrees(worktrees);
diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh
index fb4d295aa0..0507999729 100755
--- a/t/t6000-rev-list-misc.sh
+++ b/t/t6000-rev-list-misc.sh
@@ -90,11 +90,18 @@ test_expect_success 'rev-list can show index objects' '
 	9200b628cf9dc883a85a7abc8d6e6730baee589c two
 	EOF
 	echo only-in-index >only-in-index &&
+	test_when_finished "git reset --hard" &&
 	git add only-in-index &&
 	git rev-list --objects --indexed-objects >actual &&
 	test_cmp expect actual
 '
 
+test_expect_success 'rev-list can negate index objects' '
+	git rev-parse HEAD >expect &&
+	git rev-list -1 --objects HEAD --not --indexed-objects >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success '--bisect and --first-parent can not be combined' '
 	test_must_fail git rev-list --bisect --first-parent HEAD
 '
-- 
2.19.1.1336.g081079ac04


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/3] approxidate: handle pending number for "specials"
  2018-11-02  5:22 [PATCH 0/3] mixed bag of -Wunused-parameter bugfixes Jeff King
  2018-11-02  5:22 ` [PATCH 1/3] rev-list: handle flags for --indexed-objects Jeff King
@ 2018-11-02  5:23 ` Jeff King
  2018-11-07  0:48   ` Carlo Arenas
  2018-11-02  5:23 ` [PATCH 3/3] pathspec: handle non-terminated strings with :(attr) Jeff King
  2 siblings, 1 reply; 7+ messages in thread
From: Jeff King @ 2018-11-02  5:23 UTC (permalink / raw)
  To: git

The approxidate parser has a table of special keywords like
"yesterday", "noon", "pm", etc. Some of these, like "pm", do
the right thing if we've recently seen a number: "3pm" is
what you'd think.

However, most of them do not look at or modify the
pending-number flag at all, which means a number may "jump"
across a significant keyword and be used unexpectedly. For
example, when parsing:

  January 5th noon pm

we'd connect the "5" to "pm", and ignore it as a
day-of-month. This is obviously a bit silly, as "noon"
already implies "pm". And other mis-parsed things are
generally as silly ("January 5th noon, years ago" would
connect the 5 to "years", but probably nobody would type
that).

However, the fix is simple: when we see a keyword like
"noon", we should flush the pending number (as we would if
we hit another number, or the end of the string). In a few
of the specials that actually modify the day, we can simply
throw away the number (saying "Jan 5 yesterday" should not
respect the number at all).

Note that we have to either move or forward-declare the
static pending_number() to make it accessible to these
functions; this patch moves it.

Signed-off-by: Jeff King <peff@peff.net>
---
 date.c          | 60 +++++++++++++++++++++++++++----------------------
 t/t0006-date.sh |  1 +
 2 files changed, 34 insertions(+), 27 deletions(-)

diff --git a/date.c b/date.c
index 49f943e25b..7adce327a3 100644
--- a/date.c
+++ b/date.c
@@ -887,13 +887,42 @@ static time_t update_tm(struct tm *tm, struct tm *now, time_t sec)
 	return n;
 }
 
+/*
+ * Do we have a pending number at the end, or when
+ * we see a new one? Let's assume it's a month day,
+ * as in "Dec 6, 1992"
+ */
+static void pending_number(struct tm *tm, int *num)
+{
+	int number = *num;
+
+	if (number) {
+		*num = 0;
+		if (tm->tm_mday < 0 && number < 32)
+			tm->tm_mday = number;
+		else if (tm->tm_mon < 0 && number < 13)
+			tm->tm_mon = number-1;
+		else if (tm->tm_year < 0) {
+			if (number > 1969 && number < 2100)
+				tm->tm_year = number - 1900;
+			else if (number > 69 && number < 100)
+				tm->tm_year = number;
+			else if (number < 38)
+				tm->tm_year = 100 + number;
+			/* We screw up for number = 00 ? */
+		}
+	}
+}
+
 static void date_now(struct tm *tm, struct tm *now, int *num)
 {
+	*num = 0;
 	update_tm(tm, now, 0);
 }
 
 static void date_yesterday(struct tm *tm, struct tm *now, int *num)
 {
+	*num = 0;
 	update_tm(tm, now, 24*60*60);
 }
 
@@ -908,16 +937,19 @@ static void date_time(struct tm *tm, struct tm *now, int hour)
 
 static void date_midnight(struct tm *tm, struct tm *now, int *num)
 {
+	pending_number(tm, num);
 	date_time(tm, now, 0);
 }
 
 static void date_noon(struct tm *tm, struct tm *now, int *num)
 {
+	pending_number(tm, num);
 	date_time(tm, now, 12);
 }
 
 static void date_tea(struct tm *tm, struct tm *now, int *num)
 {
+	pending_number(tm, num);
 	date_time(tm, now, 17);
 }
 
@@ -953,6 +985,7 @@ static void date_never(struct tm *tm, struct tm *now, int *num)
 {
 	time_t n = 0;
 	localtime_r(&n, tm);
+	*num = 0;
 }
 
 static const struct special {
@@ -1110,33 +1143,6 @@ static const char *approxidate_digit(const char *date, struct tm *tm, int *num,
 	return end;
 }
 
-/*
- * Do we have a pending number at the end, or when
- * we see a new one? Let's assume it's a month day,
- * as in "Dec 6, 1992"
- */
-static void pending_number(struct tm *tm, int *num)
-{
-	int number = *num;
-
-	if (number) {
-		*num = 0;
-		if (tm->tm_mday < 0 && number < 32)
-			tm->tm_mday = number;
-		else if (tm->tm_mon < 0 && number < 13)
-			tm->tm_mon = number-1;
-		else if (tm->tm_year < 0) {
-			if (number > 1969 && number < 2100)
-				tm->tm_year = number - 1900;
-			else if (number > 69 && number < 100)
-				tm->tm_year = number;
-			else if (number < 38)
-				tm->tm_year = 100 + number;
-			/* We screw up for number = 00 ? */
-		}
-	}
-}
-
 static timestamp_t approxidate_str(const char *date,
 				   const struct timeval *tv,
 				   int *error_ret)
diff --git a/t/t0006-date.sh b/t/t0006-date.sh
index 64ff86df8e..b7ea5fbc36 100755
--- a/t/t0006-date.sh
+++ b/t/t0006-date.sh
@@ -113,6 +113,7 @@ check_approxidate '3:00' '2009-08-30 03:00:00'
 check_approxidate '15:00' '2009-08-30 15:00:00'
 check_approxidate 'noon today' '2009-08-30 12:00:00'
 check_approxidate 'noon yesterday' '2009-08-29 12:00:00'
+check_approxidate 'January 5th noon pm' '2009-01-05 12:00:00'
 
 check_approxidate 'last tuesday' '2009-08-25 19:20:00'
 check_approxidate 'July 5th' '2009-07-05 19:20:00'
-- 
2.19.1.1336.g081079ac04


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/3] pathspec: handle non-terminated strings with :(attr)
  2018-11-02  5:22 [PATCH 0/3] mixed bag of -Wunused-parameter bugfixes Jeff King
  2018-11-02  5:22 ` [PATCH 1/3] rev-list: handle flags for --indexed-objects Jeff King
  2018-11-02  5:23 ` [PATCH 2/3] approxidate: handle pending number for "specials" Jeff King
@ 2018-11-02  5:23 ` Jeff King
  2 siblings, 0 replies; 7+ messages in thread
From: Jeff King @ 2018-11-02  5:23 UTC (permalink / raw)
  To: git

The pathspec code always takes names to be matched as a
name/namelen pair, but match_attrs() never looks at namelen,
and just treats "name" like a NUL-terminated string, passing
it to git_check_attr().

This usually works anyway. Every caller passes a
NUL-terminated string, and in all but one the passed-in
length is the same as the length of the string (the
exception is dir_path_match(), which may pass a smaller
length to drop a trailing slash). So we won't currently ever
read random memory, and the one case I found actually
happens to work correctly because the attr code can handle
the trailing slash itself.

But it's still worth addressing, as the function interface
implies that the name does not have to be NUL-terminated,
making this an accident waiting to happen.

Since teaching git_check_attr() to take a ptr/len pair would
be a big refactor, we'll just allocate a new string. We can
do this only when necessary, which avoids paying the cost
for most callers.

Signed-off-by: Jeff King <peff@peff.net>
---
 dir.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/dir.c b/dir.c
index 47c2fca8dc..ab6477d777 100644
--- a/dir.c
+++ b/dir.c
@@ -281,8 +281,15 @@ static int match_attrs(const struct index_state *istate,
 		       const struct pathspec_item *item)
 {
 	int i;
+	char *to_free = NULL;
+
+	if (name[namelen])
+		name = to_free = xmemdupz(name, namelen);
 
 	git_check_attr(istate, name, item->attr_check);
+
+	free(to_free);
+
 	for (i = 0; i < item->attr_match_nr; i++) {
 		const char *value;
 		int matched;
-- 
2.19.1.1336.g081079ac04

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] approxidate: handle pending number for "specials"
  2018-11-02  5:23 ` [PATCH 2/3] approxidate: handle pending number for "specials" Jeff King
@ 2018-11-07  0:48   ` Carlo Arenas
  2018-11-07  1:12     ` Jeff King
  0 siblings, 1 reply; 7+ messages in thread
From: Carlo Arenas @ 2018-11-07  0:48 UTC (permalink / raw)
  To: peff; +Cc: git

On Thu, Nov 1, 2018 at 10:24 PM Jeff King <peff@peff.net> wrote:
>
>  static void date_yesterday(struct tm *tm, struct tm *now, int *num)
>  {
> +       *num = 0;

the only caller (date_time) for this sends num = NULL, so this
triggers a segfault.

the only reference I could find to that apparently unused parameter comes from:
93cfa7c7a8 ("approxidate_careful() reports errorneous date string", 2010-01-26)
and seems to indicate it is optional and therefore a check for NULL
might make sense for all other cases

Carlo

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] approxidate: handle pending number for "specials"
  2018-11-07  0:48   ` Carlo Arenas
@ 2018-11-07  1:12     ` Jeff King
  2018-11-07  2:08       ` Junio C Hamano
  0 siblings, 1 reply; 7+ messages in thread
From: Jeff King @ 2018-11-07  1:12 UTC (permalink / raw)
  To: Carlo Arenas; +Cc: Junio C Hamano, git

On Tue, Nov 06, 2018 at 04:48:28PM -0800, Carlo Arenas wrote:

> On Thu, Nov 1, 2018 at 10:24 PM Jeff King <peff@peff.net> wrote:
> >
> >  static void date_yesterday(struct tm *tm, struct tm *now, int *num)
> >  {
> > +       *num = 0;
> 
> the only caller (date_time) for this sends num = NULL, so this
> triggers a segfault.

Oof. Thanks for catching.

That's not the only caller. Usually this is called via a function
pointer from the "struct special" array. date_time() is just reusing the
other helper as a quick way to do a one-day subtraction.

> the only reference I could find to that apparently unused parameter comes from:
> 93cfa7c7a8 ("approxidate_careful() reports errorneous date string", 2010-01-26)
> and seems to indicate it is optional and therefore a check for NULL
> might make sense for all other cases

I think date_yesterday() is the only one of those special functions that
gets called like this. Here's what I think we should do to fix it (this
can go right on top of jk/misc-unused-fixes, which is already in next).

-- >8 --
Subject: [PATCH] approxidate: fix NULL dereference in date_time()

When we see a time like "noon", we pass "12" to our date_time() helper,
which sets the hour to 12pm. If the current time is before noon, then we
wrap around to yesterday using date_yesterday(). But unlike the normal
calls to date_yesterday() from approxidate_alpha(), we pass a NULL "num"
parameter. Since c27cc94fad (approxidate: handle pending number for
"specials", 2018-11-02), that causes a segfault.

One way to fix this is by checking for NULL. But arguably date_time() is
abusing our helper by passing NULL in the first place (and this is the
only case where one of these "special" parsers is used this way). So
instead, let's have it just do the 1-day subtraction itself. It's still
just a one-liner due to our update_tm() helper.

Note that the test added here is a little funny, as we say "10am noon",
which makes the "10am" seem pointless.  But this bug can only be
triggered when it the currently-parsed hour is before the special time.
The latest special time is "tea" at 1700, but t0006 uses a hard-coded
TEST_DATE_NOW of 1900. We could reset TEST_DATE_NOW, but that may lead
to confusion in other tests. Just saying "10am noon" makes this test
self-contained.

Reported-by: Carlo Arenas <carenas@gmail.com>
Signed-off-by: Jeff King <peff@peff.net>
---
 date.c          | 2 +-
 t/t0006-date.sh | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/date.c b/date.c
index 7adce327a3..9bc15df6f9 100644
--- a/date.c
+++ b/date.c
@@ -929,7 +929,7 @@ static void date_yesterday(struct tm *tm, struct tm *now, int *num)
 static void date_time(struct tm *tm, struct tm *now, int hour)
 {
 	if (tm->tm_hour < hour)
-		date_yesterday(tm, now, NULL);
+		update_tm(tm, now, 24*60*60);
 	tm->tm_hour = hour;
 	tm->tm_min = 0;
 	tm->tm_sec = 0;
diff --git a/t/t0006-date.sh b/t/t0006-date.sh
index b7ea5fbc36..ffb2975e48 100755
--- a/t/t0006-date.sh
+++ b/t/t0006-date.sh
@@ -114,6 +114,7 @@ check_approxidate '15:00' '2009-08-30 15:00:00'
 check_approxidate 'noon today' '2009-08-30 12:00:00'
 check_approxidate 'noon yesterday' '2009-08-29 12:00:00'
 check_approxidate 'January 5th noon pm' '2009-01-05 12:00:00'
+check_approxidate '10am noon' '2009-08-29 12:00:00'
 
 check_approxidate 'last tuesday' '2009-08-25 19:20:00'
 check_approxidate 'July 5th' '2009-07-05 19:20:00'
-- 
2.19.1.1534.g3beb3b7d96


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] approxidate: handle pending number for "specials"
  2018-11-07  1:12     ` Jeff King
@ 2018-11-07  2:08       ` Junio C Hamano
  0 siblings, 0 replies; 7+ messages in thread
From: Junio C Hamano @ 2018-11-07  2:08 UTC (permalink / raw)
  To: Jeff King; +Cc: Carlo Arenas, git

Jeff King <peff@peff.net> writes:

> On Tue, Nov 06, 2018 at 04:48:28PM -0800, Carlo Arenas wrote:
>
> I think date_yesterday() is the only one of those special functions that
> gets called like this. Here's what I think we should do to fix it (this
> can go right on top of jk/misc-unused-fixes, which is already in next).

Thanks, both.  I think the patch makes sense.

> -- >8 --
> Subject: [PATCH] approxidate: fix NULL dereference in date_time()
>
> When we see a time like "noon", we pass "12" to our date_time() helper,
> which sets the hour to 12pm. If the current time is before noon, then we
> wrap around to yesterday using date_yesterday(). But unlike the normal
> calls to date_yesterday() from approxidate_alpha(), we pass a NULL "num"
> parameter. Since c27cc94fad (approxidate: handle pending number for
> "specials", 2018-11-02), that causes a segfault.
>
> One way to fix this is by checking for NULL. But arguably date_time() is
> abusing our helper by passing NULL in the first place (and this is the
> only case where one of these "special" parsers is used this way). So
> instead, let's have it just do the 1-day subtraction itself. It's still
> just a one-liner due to our update_tm() helper.
>
> Note that the test added here is a little funny, as we say "10am noon",
> which makes the "10am" seem pointless.  But this bug can only be
> triggered when it the currently-parsed hour is before the special time.
> The latest special time is "tea" at 1700, but t0006 uses a hard-coded
> TEST_DATE_NOW of 1900. We could reset TEST_DATE_NOW, but that may lead
> to confusion in other tests. Just saying "10am noon" makes this test
> self-contained.
>
> Reported-by: Carlo Arenas <carenas@gmail.com>
> Signed-off-by: Jeff King <peff@peff.net>
> ---
>  date.c          | 2 +-
>  t/t0006-date.sh | 1 +
>  2 files changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/date.c b/date.c
> index 7adce327a3..9bc15df6f9 100644
> --- a/date.c
> +++ b/date.c
> @@ -929,7 +929,7 @@ static void date_yesterday(struct tm *tm, struct tm *now, int *num)
>  static void date_time(struct tm *tm, struct tm *now, int hour)
>  {
>  	if (tm->tm_hour < hour)
> -		date_yesterday(tm, now, NULL);
> +		update_tm(tm, now, 24*60*60);
>  	tm->tm_hour = hour;
>  	tm->tm_min = 0;
>  	tm->tm_sec = 0;
> diff --git a/t/t0006-date.sh b/t/t0006-date.sh
> index b7ea5fbc36..ffb2975e48 100755
> --- a/t/t0006-date.sh
> +++ b/t/t0006-date.sh
> @@ -114,6 +114,7 @@ check_approxidate '15:00' '2009-08-30 15:00:00'
>  check_approxidate 'noon today' '2009-08-30 12:00:00'
>  check_approxidate 'noon yesterday' '2009-08-29 12:00:00'
>  check_approxidate 'January 5th noon pm' '2009-01-05 12:00:00'
> +check_approxidate '10am noon' '2009-08-29 12:00:00'
>  
>  check_approxidate 'last tuesday' '2009-08-25 19:20:00'
>  check_approxidate 'July 5th' '2009-07-05 19:20:00'

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2018-11-07  2:08 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-02  5:22 [PATCH 0/3] mixed bag of -Wunused-parameter bugfixes Jeff King
2018-11-02  5:22 ` [PATCH 1/3] rev-list: handle flags for --indexed-objects Jeff King
2018-11-02  5:23 ` [PATCH 2/3] approxidate: handle pending number for "specials" Jeff King
2018-11-07  0:48   ` Carlo Arenas
2018-11-07  1:12     ` Jeff King
2018-11-07  2:08       ` Junio C Hamano
2018-11-02  5:23 ` [PATCH 3/3] pathspec: handle non-terminated strings with :(attr) Jeff King

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).