user/dev discussion of public-inbox itself
 help / color / mirror / code / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* [PATCH 0/3] lei pathname canonicalization fixes
@ 2021-08-11 11:26  7% Eric Wong
  2021-08-11 11:26  5% ` [PATCH 3/3] lei: attempt to canonicalize away "/../" pathnames Eric Wong
  0 siblings, 1 reply; 2+ results
From: Eric Wong @ 2021-08-11 11:26 UTC (permalink / raw)
  To: meta

Pathnames with "x/../y" components weren't being canonicalized
properly after creation, and some of it was being put into the
lei_mail_sync.sqlite3 DB and configs for saved searches.

This will become more important as we start using inotify more
to track keyword changes on messages.

Eric Wong (3):
  treewide: use *nix-specific dirname regexps
  lei_saved_search: canonicalized relative save paths
  lei: attempt to canonicalize away "/../" pathnames

 lib/PublicInbox/IMAPTracker.pm    |  4 ++--
 lib/PublicInbox/LEI.pm            | 16 +++++++++++-----
 lib/PublicInbox/LeiALE.pm         |  8 ++++----
 lib/PublicInbox/LeiBlob.pm        |  4 ++--
 lib/PublicInbox/LeiInit.pm        |  3 +--
 lib/PublicInbox/LeiLcat.pm        |  2 +-
 lib/PublicInbox/LeiOverview.pm    |  2 +-
 lib/PublicInbox/LeiQuery.pm       |  2 +-
 lib/PublicInbox/LeiRediff.pm      |  2 +-
 lib/PublicInbox/LeiSavedSearch.pm |  9 ++++++++-
 lib/PublicInbox/LeiUp.pm          |  2 +-
 lib/PublicInbox/OverIdx.pm        |  4 ++--
 lib/PublicInbox/Xapcmd.pm         |  5 ++---
 script/public-inbox-init          |  3 +--
 t/init.t                          |  1 -
 t/lei-q-save.t                    |  9 +++++++++
 t/lei_xsearch.t                   |  8 +++++---
 17 files changed, 52 insertions(+), 32 deletions(-)

^ permalink raw reply	[relevance 7%]

* [PATCH 3/3] lei: attempt to canonicalize away "/../" pathnames
  2021-08-11 11:26  7% [PATCH 0/3] lei pathname canonicalization fixes Eric Wong
@ 2021-08-11 11:26  5% ` Eric Wong
  0 siblings, 0 replies; 2+ results
From: Eric Wong @ 2021-08-11 11:26 UTC (permalink / raw)
  To: meta

As documented, File::Spec->canonpath does not canonicalize
"/../".  While we want to do our best to preserve symlinks in
pathnames, leaving "/../" can mislead our inotify|kqueue usage.
---
 lib/PublicInbox/LEI.pm         | 14 ++++++++++----
 lib/PublicInbox/LeiALE.pm      |  8 ++++----
 lib/PublicInbox/LeiBlob.pm     |  4 ++--
 lib/PublicInbox/LeiInit.pm     |  3 +--
 lib/PublicInbox/LeiLcat.pm     |  2 +-
 lib/PublicInbox/LeiOverview.pm |  2 +-
 lib/PublicInbox/LeiQuery.pm    |  2 +-
 lib/PublicInbox/LeiRediff.pm   |  2 +-
 lib/PublicInbox/LeiUp.pm       |  2 +-
 t/lei_xsearch.t                |  8 +++++---
 10 files changed, 27 insertions(+), 20 deletions(-)

diff --git a/lib/PublicInbox/LEI.pm b/lib/PublicInbox/LEI.pm
index be4754df..54fac7b4 100644
--- a/lib/PublicInbox/LEI.pm
+++ b/lib/PublicInbox/LEI.pm
@@ -94,6 +94,12 @@ sub rel2abs {
 # abs_path resolves symlinks in parent iff all parents exist
 sub abs_path { Cwd::abs_path($_[1]) // rel2abs(@_) }
 
+sub canonpath_harder {
+	my $p = $_[-1]; # $_[0] may be self
+	$p = File::Spec->canonpath($p);
+	$p =~ m!(?:/*|\A)\.\.(?:/*|\z)! && -e $p ? Cwd::abs_path($p) : $p;
+}
+
 sub share_path ($) { # $HOME/.local/share/lei/$FOO
 	my ($self) = @_;
 	rel2abs($self, ($self->{env}->{XDG_DATA_HOME} //
@@ -808,8 +814,8 @@ sub _lei_cfg ($;$) {
 	my $cfg = PublicInbox::Config->git_config_dump($f);
 	$cfg->{-st} = $cur_st;
 	$cfg->{'-f'} = $f;
-	if ($sto && File::Spec->canonpath($sto_dir // store_path($self))
-			eq File::Spec->canonpath($cfg->{'leistore.dir'} //
+	if ($sto && canonpath_harder($sto_dir // store_path($self))
+			eq canonpath_harder($cfg->{'leistore.dir'} //
 						store_path($self))) {
 		$cfg->{-lei_store} = $sto;
 		$cfg->{-lei_note_event} = $lne;
@@ -1382,7 +1388,7 @@ sub refresh_watches {
 			next;
 		}
 		if ($url =~ /\Amaildir:(.+)/i) {
-			my $d = File::Spec->canonpath($1);
+			my $d = canonpath_harder($1);
 			if ($state eq 'pause') {
 				cancel_maildir_watch($d, $cfg_f);
 			} elsif (!exists($MDIR2CFGPATH->{$d}->{$cfg_f})) {
@@ -1400,7 +1406,7 @@ sub refresh_watches {
 			next if exists $seen{$url};
 			delete $old->{$url};
 			if ($url =~ /\Amaildir:(.+)/i) {
-				my $d = File::Spec->canonpath($1);
+				my $d = canonpath_harder($1);
 				cancel_maildir_watch($d, $cfg_f);
 			} else { # TODO: imap/nntp/jmap
 				$lei->child_error(1, "E: watch $url TODO");
diff --git a/lib/PublicInbox/LeiALE.pm b/lib/PublicInbox/LeiALE.pm
index cb570ab4..cc9a2095 100644
--- a/lib/PublicInbox/LeiALE.pm
+++ b/lib/PublicInbox/LeiALE.pm
@@ -33,7 +33,7 @@ sub new {
 	for my $loc ($lei->externals_each) { # locals only
 		$lxs->prepare_external($loc) if -d $loc;
 	}
-	$self->refresh_externals($lxs);
+	$self->refresh_externals($lxs, $lei);
 	$self;
 }
 
@@ -50,7 +50,7 @@ sub overs_all { # for xoids_for (called only in lei workers?)
 }
 
 sub refresh_externals {
-	my ($self, $lxs) = @_;
+	my ($self, $lxs, $lei) = @_;
 	$self->git->cleanup;
 	my $lk = $self->lock_for_scope;
 	my $cur_lxs = ref($lxs)->new;
@@ -72,7 +72,7 @@ sub refresh_externals {
 	}
 	my @ibxish = $cur_lxs->locals;
 	for my $x ($lxs->locals) {
-		my $d = File::Spec->canonpath($x->{inboxdir} // $x->{topdir});
+		my $d = $lei->canonpath_harder($x->{inboxdir} // $x->{topdir});
 		$seen_ibxish{$d} //= do {
 			$new .= "$d\n";
 			push @ibxish, $x;
@@ -95,7 +95,7 @@ sub refresh_externals {
 		$old = <$fh> // die "readline($f): $!";
 	}
 	for my $x (@ibxish) {
-		$new .= File::Spec->canonpath($x->git->{git_dir})."/objects\n";
+		$new .= $lei->canonpath_harder($x->git->{git_dir})."/objects\n";
 	}
 	$self->{ibxish} = \@ibxish;
 	return if $old eq $new;
diff --git a/lib/PublicInbox/LeiBlob.pm b/lib/PublicInbox/LeiBlob.pm
index 09217964..3158ca3b 100644
--- a/lib/PublicInbox/LeiBlob.pm
+++ b/lib/PublicInbox/LeiBlob.pm
@@ -112,7 +112,7 @@ sub lei_blob {
 	if ($opt->{mail} // ($has_hints ? 0 : 1)) {
 		if (grep(defined, @$opt{qw(include only)})) {
 			$lxs = $lei->lxs_prepare;
-			$lei->ale->refresh_externals($lxs);
+			$lei->ale->refresh_externals($lxs, $lei);
 		}
 		my $rdr = {};
 		if ($opt->{mail}) {
@@ -155,7 +155,7 @@ sub lei_blob {
 	return $lei->fail('no --git-dir to try') unless @$git_dirs;
 	unless ($lxs) {
 		$lxs = $lei->lxs_prepare or return;
-		$lei->ale->refresh_externals($lxs);
+		$lei->ale->refresh_externals($lxs, $lei);
 	}
 	if ($lxs->remotes) {
 		require PublicInbox::LeiRemote;
diff --git a/lib/PublicInbox/LeiInit.pm b/lib/PublicInbox/LeiInit.pm
index c6c0c01b..6558ac0a 100644
--- a/lib/PublicInbox/LeiInit.pm
+++ b/lib/PublicInbox/LeiInit.pm
@@ -4,7 +4,6 @@
 # for the "lei init" command, not sure if it's even needed...
 package PublicInbox::LeiInit;
 use v5.10.1;
-use File::Spec;
 
 sub lei_init {
 	my ($self, $dir) = @_;
@@ -13,7 +12,7 @@ sub lei_init {
 	$dir //= $self->store_path;
 	$dir = $self->rel2abs($dir);
 	my @cur = stat($cur) if defined($cur);
-	$cur = File::Spec->canonpath($cur // $dir);
+	$cur = $self->canonpath_harder($cur // $dir);
 	my @dir = stat($dir);
 	my $exists = "# leistore.dir=$cur already initialized" if @dir;
 	if (@cur) {
diff --git a/lib/PublicInbox/LeiLcat.pm b/lib/PublicInbox/LeiLcat.pm
index cb5eb5b4..4a0c24a9 100644
--- a/lib/PublicInbox/LeiLcat.pm
+++ b/lib/PublicInbox/LeiLcat.pm
@@ -128,7 +128,7 @@ sub _stdin { # PublicInbox::InputPipe::consume callback for --stdin
 sub lei_lcat {
 	my ($lei, @argv) = @_;
 	my $lxs = $lei->lxs_prepare or return;
-	$lei->ale->refresh_externals($lxs);
+	$lei->ale->refresh_externals($lxs, $lei);
 	my $sto = $lei->_lei_store(1);
 	$lei->{lse} = $sto->search;
 	my $opt = $lei->{opt};
diff --git a/lib/PublicInbox/LeiOverview.pm b/lib/PublicInbox/LeiOverview.pm
index e4242d9b..223db222 100644
--- a/lib/PublicInbox/LeiOverview.pm
+++ b/lib/PublicInbox/LeiOverview.pm
@@ -76,7 +76,7 @@ sub new {
 	$fmt //= $devfd >= 0 ? 'json' : (detect_fmt($lei, $dst) or return);
 
 	if (index($dst, '://') < 0) { # not a URL, so assume path
-		 $dst = File::Spec->canonpath($dst);
+		 $dst = $lei->canonpath_harder($dst);
 	} # else URL
 
 	my $self = bless { fmt => $fmt, dst => $dst }, $class;
diff --git a/lib/PublicInbox/LeiQuery.pm b/lib/PublicInbox/LeiQuery.pm
index eb7b98d4..37b660f9 100644
--- a/lib/PublicInbox/LeiQuery.pm
+++ b/lib/PublicInbox/LeiQuery.pm
@@ -116,7 +116,7 @@ sub lei_q {
 	my ($self, @argv) = @_;
 	PublicInbox::Config->json; # preload before forking
 	my $lxs = lxs_prepare($self) or return;
-	$self->ale->refresh_externals($lxs);
+	$self->ale->refresh_externals($lxs, $self);
 	my $opt = $self->{opt};
 	my %mset_opt = map { $_ => $opt->{$_} } qw(threads limit offset);
 	$mset_opt{asc} = $opt->{'reverse'} ? 1 : 0;
diff --git a/lib/PublicInbox/LeiRediff.pm b/lib/PublicInbox/LeiRediff.pm
index 7607b44f..0ba5897c 100644
--- a/lib/PublicInbox/LeiRediff.pm
+++ b/lib/PublicInbox/LeiRediff.pm
@@ -215,7 +215,7 @@ sub lei_rediff {
 		$lei->{curl} //= which('curl') or return
 			$lei->fail('curl needed for', $lxs->remotes);
 	}
-	$lei->ale->refresh_externals($lxs);
+	$lei->ale->refresh_externals($lxs, $lei);
 	my $self = bless {
 		-force_eml => 1, # for LeiInput->input_fh
 		lxs => $lxs,
diff --git a/lib/PublicInbox/LeiUp.pm b/lib/PublicInbox/LeiUp.pm
index 9069232b..3356d11e 100644
--- a/lib/PublicInbox/LeiUp.pm
+++ b/lib/PublicInbox/LeiUp.pm
@@ -42,7 +42,7 @@ sub up1 ($$) {
 	}
 	$lei->{lss} = $lss; # for LeiOverview->new
 	my $lxs = $lei->lxs_prepare or return;
-	$lei->ale->refresh_externals($lxs);
+	$lei->ale->refresh_externals($lxs, $lei);
 	$lei->_start_query;
 }
 
diff --git a/t/lei_xsearch.t b/t/lei_xsearch.t
index 3eb44233..d9ddb297 100644
--- a/t/lei_xsearch.t
+++ b/t/lei_xsearch.t
@@ -11,6 +11,7 @@ require PublicInbox::ExtSearchIdx;
 require_git 2.6;
 require_ok 'PublicInbox::LeiXSearch';
 require_ok 'PublicInbox::LeiALE';
+require_ok 'PublicInbox::LEI';
 my ($home, $for_destroy) = tmpdir();
 my @ibx;
 for my $V (1..2) {
@@ -88,18 +89,19 @@ is($lxs->over, undef, '->over fails');
 	my $smsg = $lxs->smsg_for($mitem) or BAIL_OUT 'smsg_for broken';
 
 	my $ale = PublicInbox::LeiALE::_new("$home/ale");
-	$ale->refresh_externals($lxs);
+	my $lei = bless {}, 'PublicInbox::LEI';
+	$ale->refresh_externals($lxs, $lei);
 	my $exp = [ $smsg->{blob}, 'blob', -s 't/utf8.eml' ];
 	is_deeply([ $ale->git->check($smsg->{blob}) ], $exp, 'ale->git->check');
 
 	$lxs = PublicInbox::LeiXSearch->new;
 	$lxs->prepare_external($v2ibx);
-	$ale->refresh_externals($lxs);
+	$ale->refresh_externals($lxs, $lei);
 	is_deeply([ $ale->git->check($smsg->{blob}) ], $exp,
 			'ale->git->check remembered inactive external');
 
 	rename("$home/v1tmp", "$home/v1moved") or BAIL_OUT "rename: $!";
-	$ale->refresh_externals($lxs);
+	$ale->refresh_externals($lxs, $lei);
 	is($ale->git->check($smsg->{blob}), undef,
 			'missing after directory gone');
 }

^ permalink raw reply related	[relevance 5%]

Results 1-2 of 2 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2021-08-11 11:26  7% [PATCH 0/3] lei pathname canonicalization fixes Eric Wong
2021-08-11 11:26  5% ` [PATCH 3/3] lei: attempt to canonicalize away "/../" pathnames Eric Wong

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

	https://80x24.org/public-inbox.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).