[Git][debian-proftpd-team/proftpd][master] Add a bunch of fixes from upstream.

Hilmar Preuße (@hilmar-guest) gitlab at salsa.debian.org
Fri Feb 18 23:13:20 GMT 2022



Hilmar Preuße pushed to branch master at Debian ProFTPD Team / proftpd


Commits:
fbc2d571 by Hilmar Preusse at 2022-02-19T00:12:53+01:00
Add a bunch of fixes from upstream.

- - - - -


7 changed files:

- debian/changelog
- + debian/patches/bug_4467
- debian/patches/series
- + debian/patches/upstream_1322
- + debian/patches/upstream_1325
- + debian/patches/upstream_1346
- + debian/patches/upstream_long_AuthGroupFile_lines


Changes:

=====================================
debian/changelog
=====================================
@@ -7,6 +7,12 @@ proftpd-dfsg (1.3.7c+dfsg-2) UNRELEASED; urgency=medium
     - Rules-Requires-Root: binary
     - More small stuff
   * Fix syntax values in proftpd.conf example (Closes: #1002467)
+  * Add a bunch of fixes from upstream:
+    + upstream_1322
+    + upstream_1325
+    + upstream_1346
+    + upstream_long_AuthGroupFile_lines
+    + bug_4467
 
   [ Debian Janitor ]
   * Remove constraints unnecessary since buster:


=====================================
debian/patches/bug_4467
=====================================
@@ -0,0 +1,34 @@
+From ed101eed833bdb53d6bcecdb4448040bd4ce9b5f Mon Sep 17 00:00:00 2001
+From: TJ Saunders <tj at castaglia.org>
+Date: Sat, 29 Jan 2022 11:20:14 -0800
+Subject: [PATCH] Backport of fix for Bug#4467 to the 1.3.7 branch.
+
+---
+ NEWS               | 2 ++
+ modules/mod_xfer.c | 5 ++---
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/modules/mod_xfer.c b/modules/mod_xfer.c
+index 9348118c00..b7fcf74e94 100644
+--- a/modules/mod_xfer.c
++++ b/modules/mod_xfer.c
+@@ -2,7 +2,7 @@
+  * ProFTPD - FTP server daemon
+  * Copyright (c) 1997, 1998 Public Flood Software
+  * Copyright (c) 1999, 2000 MacGyver aka Habeeb J. Dihu <macgyver at tos.net>
+- * Copyright (c) 2001-2020 The ProFTPD Project team
++ * Copyright (c) 2001-2022 The ProFTPD Project team
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+@@ -1014,9 +1014,8 @@ static void stor_abort(pool *p) {
+         } 
+       }
+     }
+-  }
+ 
+-  if (session.xfer.path != NULL) {
++  } else if (session.xfer.path != NULL) {
+     if (delete_stores != NULL &&
+         *delete_stores == TRUE) {
+       pr_log_debug(DEBUG5, "removing aborted file '%s'", session.xfer.path);


=====================================
debian/patches/series
=====================================
@@ -19,3 +19,8 @@ proftpd-mysql-password-backend.diff
 #2eadd82f392573235432a9cb60266f6472d08884.diff
 #upstream_1284
 spelling_error_in_contrib_mod_tls.c
+upstream_1322
+upstream_1325
+upstream_1346
+upstream_long_AuthGroupFile_lines
+bug_4467


=====================================
debian/patches/upstream_1322
=====================================
@@ -0,0 +1,154 @@
+From e428a379fc97db8400a497045a57a69468666901 Mon Sep 17 00:00:00 2001
+From: TJ Saunders <tj at castaglia.org>
+Date: Sat, 4 Sep 2021 10:19:01 -0700
+Subject: [PATCH] Issue #1321: When processing very long lines from an
+ `AuthGroupFile`, allocate larger buffers in smaller increments, as
+ `fgetgrent(3)` does.
+
+---
+ modules/mod_auth_file.c                       | 11 ++-
+ tests/t/lib/ProFTPD/TestSuite/Utils.pm        |  4 +-
+ .../ProFTPD/Tests/Modules/mod_auth_file.pm    | 80 +++++++++++++++++++
+ 3 files changed, 92 insertions(+), 3 deletions(-)
+
+--- proftpd.orig/modules/mod_auth_file.c
++++ proftpd/modules/mod_auth_file.c
+@@ -332,6 +332,9 @@
+ static char *af_getgrentline(char **buf, int *buflen, pr_fh_t *fh,
+     unsigned int *lineno) {
+   char *cp = *buf;
++  int original_buflen;
++
++  original_buflen = *buflen;
+ 
+   while (pr_fsio_gets(cp, (*buflen) - (cp - *buf), fh) != NULL) {
+     pr_signals_handle();
+@@ -343,8 +346,12 @@
+       return *buf;
+     }
+ 
+-    /* No -- allocate a larger buffer, doubling buflen. */
+-    *buflen += *buflen;
++    /* No -- allocate a larger buffer.  Note that doubling the buflen
++     * each time may cause issues; fgetgrent(3) would increment the
++     * allocated buffer by the original buffer length each time.  So we
++     * do the same (Issue #1321).
++     */
++    *buflen += original_buflen;
+ 
+     {
+       char *new_buf;
+--- proftpd.orig/tests/t/lib/ProFTPD/TestSuite/Utils.pm
++++ proftpd/tests/t/lib/ProFTPD/TestSuite/Utils.pm
+@@ -1210,6 +1210,8 @@
+   my $gid = shift;
+   $gid = 500 unless defined($gid);
+   my $home_dir = shift;
++  my $groups = shift;
++  $groups = $user unless defined($groups);
+ 
+   my $config_file = "$tmpdir/$name.conf";
+   my $pid_file = File::Spec->rel2abs("$tmpdir/$name.pid");
+@@ -1238,7 +1240,7 @@
+ 
+   auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
+     '/bin/bash');
+-  auth_group_write($auth_group_file, $group, $gid, $user);
++  auth_group_write($auth_group_file, $group, $gid, $groups);
+ 
+   my $setup = {
+     auth_user_file => $auth_user_file,
+--- proftpd.orig/tests/t/lib/ProFTPD/Tests/Modules/mod_auth_file.pm
++++ proftpd/tests/t/lib/ProFTPD/Tests/Modules/mod_auth_file.pm
+@@ -122,6 +122,10 @@
+     test_class => [qw(bug forking)],
+   },
+ 
++  auth_file_line_too_long_issue1321 => {
++    order => ++$order,
++    test_class => [qw(bug forking)],
++  },
+ };
+ 
+ sub new {
+@@ -2271,4 +2275,80 @@
+   unlink($log_file);
+ }
+ 
++sub auth_file_line_too_long_issue1321 {
++  my $self = shift;
++  my $tmpdir = $self->{tmpdir};
++
++  # For Issue #1321, we create a very long AuthGroupFile entry with many
++  # group names.
++
++  my $groups = 'proftpd';
++  for (my $i = 0; $i < 200; $i++) {
++    $groups .= ",quite.long.example.group.$i";
++  }
++
++  my $setup = test_setup($tmpdir, 'authfile', undef, undef, undef, undef, undef,
++    undef, $groups);
++
++  my $config = {
++    PidFile => $setup->{pid_file},
++    ScoreboardFile => $setup->{scoreboard_file},
++    SystemLog => $setup->{log_file},
++
++    AuthUserFile => $setup->{auth_user_file},
++    AuthGroupFile => $setup->{auth_group_file},
++
++    IfModules => {
++      'mod_delay.c' => {
++        DelayEngine => 'off',
++      },
++    },
++  };
++
++  my ($port, $config_user, $config_group) = config_write($setup->{config_file},
++    $config);
++
++  # Open pipes, for use between the parent and child processes.  Specifically,
++  # the child will indicate when it's done with its test by writing a message
++  # to the parent.
++  my ($rfh, $wfh);
++  unless (pipe($rfh, $wfh)) {
++    die("Can't open pipe: $!");
++  }
++
++  my $ex;
++
++  # Fork child
++  $self->handle_sigchld();
++  defined(my $pid = fork()) or die("Can't fork: $!");
++  if ($pid) {
++    eval {
++      my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
++      $client->login($setup->{user}, $setup->{passwd});
++      $client->quit();
++    };
++    if ($@) {
++      $ex = $@;
++    }
++
++    $wfh->print("done\n");
++    $wfh->flush();
++
++  } else {
++    eval { server_wait($setup->{config_file}, $rfh) };
++    if ($@) {
++      warn($@);
++      exit 1;
++    }
++
++    exit 0;
++  }
++
++  # Stop server
++  server_stop($setup->{pid_file});
++  $self->assert_child_ok($pid);
++
++  test_cleanup($setup->{log_file}, $ex);
++}
++
+ 1;


=====================================
debian/patches/upstream_1325
=====================================
@@ -0,0 +1,569 @@
+From 6e3d8debc14f1b532fae27994120f591b39fb183 Mon Sep 17 00:00:00 2001
+From: TJ Saunders <tj at castaglia.org>
+Date: Sat, 11 Sep 2021 14:22:31 -0700
+Subject: [PATCH] Backport fix for Issue #1325 to the 1.3.7 branch.
+
+---
+ NEWS                                       |   1 +
+ modules/mod_ls.c                           |   6 +-
+ tests/t/lib/ProFTPD/Tests/Commands/NLST.pm | 453 +++++++++++++++++++--
+ 3 files changed, 412 insertions(+), 48 deletions(-)
+
+diff --git a/modules/mod_ls.c b/modules/mod_ls.c
+index 45a3187bd9..c7a44c450a 100644
+--- a/modules/mod_ls.c
++++ b/modules/mod_ls.c
+@@ -2,7 +2,7 @@
+  * ProFTPD - FTP server daemon
+  * Copyright (c) 1997, 1998 Public Flood Software
+  * Copyright (c) 1999, 2000 MacGyver aka Habeeb J. Dihu <macgyver at tos.net>
+- * Copyright (c) 2001-2020 The ProFTPD Project
++ * Copyright (c) 2001-2021 The ProFTPD Project
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+@@ -3163,10 +3163,6 @@ MODRET ls_nlst(cmd_rec *cmd) {
+       p = *path;
+       path++;
+ 
+-      if (*p == '.' && (!opt_A || is_dotdir(p))) {
+-        continue;
+-      }
+-
+       pr_fs_clear_cache2(p);
+       if (pr_fsio_stat(p, &st) == 0) {
+         /* If it's a directory... */
+diff --git a/tests/t/lib/ProFTPD/Tests/Commands/NLST.pm b/tests/t/lib/ProFTPD/Tests/Commands/NLST.pm
+index 7fa5c84177..eac38ea24d 100644
+--- a/tests/t/lib/ProFTPD/Tests/Commands/NLST.pm
++++ b/tests/t/lib/ProFTPD/Tests/Commands/NLST.pm
+@@ -157,6 +157,16 @@ my $TESTS = {
+     test_class => [qw(forking rootprivs)],
+   },
+ 
++  nlst_glob_with_rel_path_issue1325 => {
++    order => ++$order,
++    test_class => [qw(bug forking)],
++  },
++
++  nlst_glob_with_rel_path_dotdir_issue1325 => {
++    order => ++$order,
++    test_class => [qw(bug forking)],
++  },
++
+ };
+ 
+ sub new {
+@@ -3616,22 +3626,7 @@ sub nlst_rel_path_chrooted_bug2496 {
+ sub nlst_parent_dir_bug4011 {
+   my $self = shift;
+   my $tmpdir = $self->{tmpdir};
+-
+-  my $config_file = "$tmpdir/cmds.conf";
+-  my $pid_file = File::Spec->rel2abs("$tmpdir/cmds.pid");
+-  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/cmds.scoreboard");
+-
+-  my $log_file = test_get_logfile();
+-
+-  my $auth_user_file = File::Spec->rel2abs("$tmpdir/cmds.passwd");
+-  my $auth_group_file = File::Spec->rel2abs("$tmpdir/cmds.group");
+-
+-  my $user = 'proftpd';
+-  my $passwd = 'test';
+-  my $group = 'ftpd';
+-  my $home_dir = File::Spec->rel2abs($tmpdir);
+-  my $uid = 500;
+-  my $gid = 500;
++  my $setup = test_setup($tmpdir, 'cmds');
+ 
+   my $sub_dir1 = File::Spec->rel2abs("$tmpdir/dir1");
+   my $sub_dir2 = File::Spec->rel2abs("$tmpdir/dir1/dir2");
+@@ -3662,26 +3657,22 @@ sub nlst_parent_dir_bug4011 {
+   # Make sure that, if we're running as root, that the home directory has
+   # permissions/privs set for the account we create
+   if ($< == 0) {
+-    unless (chmod(0755, $home_dir, $sub_dir1)) {
+-      die("Can't set perms on $home_dir to 0755: $!");
++    unless (chmod(0755, $sub_dir1)) {
++      die("Can't set perms on $sub_dir1 to 0755: $!");
+     }
+ 
+-    unless (chown($uid, $gid, $home_dir, $sub_dir1)) {
+-      die("Can't set owner of $home_dir to $uid/$gid: $!");
++    unless (chown($setup->{uid}, $setup->{gid}, $sub_dir1)) {
++      die("Can't set owner of $sub_dir1 to $setup->{uid}/$setup->{gid}: $!");
+     }
+   }
+ 
+-  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
+-    '/bin/bash');
+-  auth_group_write($auth_group_file, $group, $gid, $user);
+-
+   my $config = {
+-    PidFile => $pid_file,
+-    ScoreboardFile => $scoreboard_file,
+-    SystemLog => $log_file,
++    PidFile => $setup->{pid_file},
++    ScoreboardFile => $setup->{scoreboard_file},
++    SystemLog => $setup->{log_file},
+ 
+-    AuthUserFile => $auth_user_file,
+-    AuthGroupFile => $auth_group_file,
++    AuthUserFile => $setup->{auth_user_file},
++    AuthGroupFile => $setup->{auth_group_file},
+ 
+     IfModules => {
+       'mod_delay.c' => {
+@@ -3690,7 +3681,8 @@ sub nlst_parent_dir_bug4011 {
+     },
+   };
+ 
+-  my ($port, $config_user, $config_group) = config_write($config_file, $config);
++  my ($port, $config_user, $config_group) = config_write($setup->{config_file},
++    $config);
+ 
+   # Open pipes, for use between the parent and child processes.  Specifically,
+   # the child will indicate when it's done with its test by writing a message
+@@ -3708,7 +3700,7 @@ sub nlst_parent_dir_bug4011 {
+   if ($pid) {
+     eval {
+       my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
+-      $client->login($user, $passwd);
++      $client->login($setup->{user}, $setup->{passwd});
+       $client->cwd("dir1");
+       $client->cwd("dir2");
+ 
+@@ -3722,6 +3714,12 @@ sub nlst_parent_dir_bug4011 {
+       $conn->read($buf, 8192, 25);
+       eval { $conn->close() };
+ 
++      $client->quit();
++
++      if ($ENV{TEST_VERBOSE}) {
++        print STDERR "# response:\n$buf\n";
++      }
++
+       # We have to be careful of the fact that readdir returns directory
+       # entries in an unordered fashion.
+       my $res = {};
+@@ -3749,7 +3747,6 @@ sub nlst_parent_dir_bug4011 {
+         die("Unexpected name '$mismatch' appeared in NLST data")
+       }
+     };
+-
+     if ($@) {
+       $ex = $@;
+     }
+@@ -3758,7 +3755,7 @@ sub nlst_parent_dir_bug4011 {
+     $wfh->flush();
+ 
+   } else {
+-    eval { server_wait($config_file, $rfh) };
++    eval { server_wait($setup->{config_file}, $rfh) };
+     if ($@) {
+       warn($@);
+       exit 1;
+@@ -3768,18 +3765,10 @@ sub nlst_parent_dir_bug4011 {
+   }
+ 
+   # Stop server
+-  server_stop($pid_file);
+-
++  server_stop($setup->{pid_file});
+   $self->assert_child_ok($pid);
+ 
+-  if ($ex) {
+-    test_append_logfile($log_file, $ex);
+-    unlink($log_file);
+-
+-    die($ex);
+-  }
+-
+-  unlink($log_file);
++  test_cleanup($setup->{log_file}, $ex);
+ }
+ 
+ sub nlst_opt_a_root_dir_bug4069 {
+@@ -4080,4 +4069,382 @@ sub nlst_opt_1_with_chroot {
+   unlink($log_file);
+ }
+ 
++sub nlst_glob_with_rel_path_issue1325 {
++  my $self = shift;
++  my $tmpdir = $self->{tmpdir};
++  my $setup = test_setup($tmpdir, 'cmds');
++
++  my $test_path = File::Spec->rel2abs("$tmpdir/test.d");
++  mkpath($test_path);
++
++  for (my $i = 0; $i < 10; $i++) {
++    my $test_file = File::Spec->rel2abs("$test_path/TEST000$i.dat");
++    if (open(my $fh, "> $test_file")) {
++      print $fh "Hello, World!\n";
++      unless (close($fh)) {
++        die("Can't write $test_file: $!");
++      }
++
++    } else {
++      die("Can't open $test_file: $!");
++    }
++  }
++
++  my $config = {
++    PidFile => $setup->{pid_file},
++    ScoreboardFile => $setup->{scoreboard_file},
++    SystemLog => $setup->{log_file},
++
++    AuthUserFile => $setup->{auth_user_file},
++    AuthGroupFile => $setup->{auth_group_file},
++
++    IfModules => {
++      'mod_delay.c' => {
++        DelayEngine => 'off',
++      },
++    },
++  };
++
++  my ($port, $config_user, $config_group) = config_write($setup->{config_file},
++    $config);
++
++  # Open pipes, for use between the parent and child processes.  Specifically,
++  # the child will indicate when it's done with its test by writing a message
++  # to the parent.
++  my ($rfh, $wfh);
++  unless (pipe($rfh, $wfh)) {
++    die("Can't open pipe: $!");
++  }
++
++  my $ex;
++
++  # Fork child
++  $self->handle_sigchld();
++  defined(my $pid = fork()) or die("Can't fork: $!");
++  if ($pid) {
++    eval {
++      my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
++      $client->login($setup->{user}, $setup->{passwd});
++
++      my $conn = $client->nlst_raw('test.d/TEST????.dat');
++      unless ($conn) {
++        die("Failed to NLST: " . $client->response_code() . " " .
++          $client->response_msg());
++      }
++
++      my $buf;
++      $conn->read($buf, 8192, 25);
++      eval { $conn->close() };
++
++      if ($ENV{TEST_VERBOSE}) {
++        print STDERR "# response:\n$buf\n";
++      }
++
++      # We have to be careful of the fact that readdir returns directory
++      # entries in an unordered fashion.
++      my $res = {};
++      my $names = [split(/\n/, $buf)];
++      foreach my $name (@$names) {
++        $res->{$name} = 1;
++      }
++
++      $self->assert(scalar(@$names) > 0,
++        test_msg("Expected multiple names, got 0"));
++
++      my $expected = {
++        'test.d/TEST0000.dat' => 1,
++        'test.d/TEST0001.dat' => 1,
++        'test.d/TEST0002.dat' => 1,
++        'test.d/TEST0003.dat' => 1,
++        'test.d/TEST0004.dat' => 1,
++        'test.d/TEST0005.dat' => 1,
++        'test.d/TEST0006.dat' => 1,
++        'test.d/TEST0007.dat' => 1,
++        'test.d/TEST0008.dat' => 1,
++        'test.d/TEST0009.dat' => 1,
++      };
++
++      my $ok = 1;
++      my $mismatch;
++      foreach my $name (keys(%$res)) {
++        unless (defined($expected->{$name})) {
++          $mismatch = $name;
++          $ok = 0;
++          last;
++        }
++      }
++
++      unless ($ok) {
++        die("Unexpected name '$mismatch' appeared in NLST data")
++      }
++
++      # Now do it again, this time using an explicit relative path.
++
++      $conn = $client->nlst_raw('./test.d/TEST????.dat');
++      unless ($conn) {
++        die("Failed to NLST: " . $client->response_code() . " " .
++          $client->response_msg());
++      }
++
++      $buf = '';
++      $conn->read($buf, 8192, 25);
++      eval { $conn->close() };
++
++      if ($ENV{TEST_VERBOSE}) {
++        print STDERR "# response:\n$buf\n";
++      }
++
++      # We have to be careful of the fact that readdir returns directory
++      # entries in an unordered fashion.
++      $res = {};
++      $names = [split(/\n/, $buf)];
++      foreach my $name (@$names) {
++        $res->{$name} = 1;
++      }
++
++      $self->assert(scalar(@$names) > 0,
++        test_msg("Expected multiple names, got 0"));
++
++      $expected = {
++        './test.d/TEST0000.dat' => 1,
++        './test.d/TEST0001.dat' => 1,
++        './test.d/TEST0002.dat' => 1,
++        './test.d/TEST0003.dat' => 1,
++        './test.d/TEST0004.dat' => 1,
++        './test.d/TEST0005.dat' => 1,
++        './test.d/TEST0006.dat' => 1,
++        './test.d/TEST0007.dat' => 1,
++        './test.d/TEST0008.dat' => 1,
++        './test.d/TEST0009.dat' => 1,
++      };
++
++      $ok = 1;
++      $mismatch = '';
++      foreach my $name (keys(%$res)) {
++        unless (defined($expected->{$name})) {
++          $mismatch = $name;
++          $ok = 0;
++          last;
++        }
++      }
++
++      unless ($ok) {
++        die("Unexpected name '$mismatch' appeared in NLST data")
++      }
++
++      $client->quit();
++    };
++    if ($@) {
++      $ex = $@;
++    }
++
++    $wfh->print("done\n");
++    $wfh->flush();
++
++  } else {
++    eval { server_wait($setup->{config_file}, $rfh) };
++    if ($@) {
++      warn($@);
++      exit 1;
++    }
++
++    exit 0;
++  }
++
++  # Stop server
++  server_stop($setup->{pid_file});
++  $self->assert_child_ok($pid);
++
++  test_cleanup($setup->{log_file}, $ex);
++}
++
++sub nlst_glob_with_rel_path_dotdir_issue1325 {
++  my $self = shift;
++  my $tmpdir = $self->{tmpdir};
++  my $setup = test_setup($tmpdir, 'cmds');
++
++  my $test_path = File::Spec->rel2abs("$tmpdir/.test.d");
++  mkpath($test_path);
++
++  for (my $i = 0; $i < 10; $i++) {
++    my $test_file = File::Spec->rel2abs("$test_path/TEST000$i.dat");
++    if (open(my $fh, "> $test_file")) {
++      print $fh "Hello, World!\n";
++      unless (close($fh)) {
++        die("Can't write $test_file: $!");
++      }
++
++    } else {
++      die("Can't open $test_file: $!");
++    }
++  }
++
++  my $config = {
++    PidFile => $setup->{pid_file},
++    ScoreboardFile => $setup->{scoreboard_file},
++    SystemLog => $setup->{log_file},
++
++    AuthUserFile => $setup->{auth_user_file},
++    AuthGroupFile => $setup->{auth_group_file},
++
++    IfModules => {
++      'mod_delay.c' => {
++        DelayEngine => 'off',
++      },
++    },
++  };
++
++  my ($port, $config_user, $config_group) = config_write($setup->{config_file},
++    $config);
++
++  # Open pipes, for use between the parent and child processes.  Specifically,
++  # the child will indicate when it's done with its test by writing a message
++  # to the parent.
++  my ($rfh, $wfh);
++  unless (pipe($rfh, $wfh)) {
++    die("Can't open pipe: $!");
++  }
++
++  my $ex;
++
++  # Fork child
++  $self->handle_sigchld();
++  defined(my $pid = fork()) or die("Can't fork: $!");
++  if ($pid) {
++    eval {
++      my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
++      $client->login($setup->{user}, $setup->{passwd});
++
++      my $conn = $client->nlst_raw('.test.d/TEST????.dat');
++      unless ($conn) {
++        die("Failed to NLST: " . $client->response_code() . " " .
++          $client->response_msg());
++      }
++
++      my $buf;
++      $conn->read($buf, 8192, 25);
++      eval { $conn->close() };
++
++      if ($ENV{TEST_VERBOSE}) {
++        print STDERR "# response:\n$buf\n";
++      }
++
++      # We have to be careful of the fact that readdir returns directory
++      # entries in an unordered fashion.
++      my $res = {};
++      my $names = [split(/\n/, $buf)];
++      foreach my $name (@$names) {
++        $res->{$name} = 1;
++      }
++
++      $self->assert(scalar(@$names) > 0,
++        test_msg("Expected multiple names, got 0"));
++
++      my $expected = {
++        '.test.d/TEST0000.dat' => 1,
++        '.test.d/TEST0001.dat' => 1,
++        '.test.d/TEST0002.dat' => 1,
++        '.test.d/TEST0003.dat' => 1,
++        '.test.d/TEST0004.dat' => 1,
++        '.test.d/TEST0005.dat' => 1,
++        '.test.d/TEST0006.dat' => 1,
++        '.test.d/TEST0007.dat' => 1,
++        '.test.d/TEST0008.dat' => 1,
++        '.test.d/TEST0009.dat' => 1,
++      };
++
++      my $ok = 1;
++      my $mismatch;
++      foreach my $name (keys(%$res)) {
++        unless (defined($expected->{$name})) {
++          $mismatch = $name;
++          $ok = 0;
++          last;
++        }
++      }
++
++      unless ($ok) {
++        die("Unexpected name '$mismatch' appeared in NLST data")
++      }
++
++      # Now do it again, this time using an explicit relative path.
++
++      $conn = $client->nlst_raw('./.test.d/TEST????.dat');
++      unless ($conn) {
++        die("Failed to NLST: " . $client->response_code() . " " .
++          $client->response_msg());
++      }
++
++      $buf = '';
++      $conn->read($buf, 8192, 25);
++      eval { $conn->close() };
++
++      if ($ENV{TEST_VERBOSE}) {
++        print STDERR "# response:\n$buf\n";
++      }
++
++      # We have to be careful of the fact that readdir returns directory
++      # entries in an unordered fashion.
++      $res = {};
++      $names = [split(/\n/, $buf)];
++      foreach my $name (@$names) {
++        $res->{$name} = 1;
++      }
++
++      $self->assert(scalar(@$names) > 0,
++        test_msg("Expected multiple names, got 0"));
++
++      $expected = {
++        './.test.d/TEST0000.dat' => 1,
++        './.test.d/TEST0001.dat' => 1,
++        './.test.d/TEST0002.dat' => 1,
++        './.test.d/TEST0003.dat' => 1,
++        './.test.d/TEST0004.dat' => 1,
++        './.test.d/TEST0005.dat' => 1,
++        './.test.d/TEST0006.dat' => 1,
++        './.test.d/TEST0007.dat' => 1,
++        './.test.d/TEST0008.dat' => 1,
++        './.test.d/TEST0009.dat' => 1,
++      };
++
++      $ok = 1;
++      $mismatch = '';
++      foreach my $name (keys(%$res)) {
++        unless (defined($expected->{$name})) {
++          $mismatch = $name;
++          $ok = 0;
++          last;
++        }
++      }
++
++      unless ($ok) {
++        die("Unexpected name '$mismatch' appeared in NLST data")
++      }
++
++      $client->quit();
++    };
++    if ($@) {
++      $ex = $@;
++    }
++
++    $wfh->print("done\n");
++    $wfh->flush();
++
++  } else {
++    eval { server_wait($setup->{config_file}, $rfh) };
++    if ($@) {
++      warn($@);
++      exit 1;
++    }
++
++    exit 0;
++  }
++
++  # Stop server
++  server_stop($setup->{pid_file});
++  $self->assert_child_ok($pid);
++
++  test_cleanup($setup->{log_file}, $ex);
++}
++
+ 1;


=====================================
debian/patches/upstream_1346
=====================================
@@ -0,0 +1,441 @@
+From bb8116d21f7849bf36cc356de4d8cfec579eba64 Mon Sep 17 00:00:00 2001
+From: TJ Saunders <tj at castaglia.org>
+Date: Tue, 26 Oct 2021 19:10:59 -0700
+Subject: [PATCH] Issue #1346: When accept connections for passive data
+ transfers, and a class name has been configured for `AllowForeignAddress`,
+ check the connecting client against that class.
+
+---
+ src/inet.c                                    |  90 +++++--
+ .../Tests/Config/AllowForeignAddress.pm       | 255 +++++++++++++++++-
+ 2 files changed, 314 insertions(+), 31 deletions(-)
+
+diff --git a/src/inet.c b/src/inet.c
+index 33ce349aa3..81c1c99b1d 100644
+--- a/src/inet.c
++++ b/src/inet.c
+@@ -1522,9 +1522,9 @@ int pr_inet_accept_nowait(pool *p, conn_t *c) {
+  */
+ conn_t *pr_inet_accept(pool *p, conn_t *d, conn_t *c, int rfd, int wfd,
+     unsigned char resolve) {
++  config_rec *allow_foreign_addr_config = NULL;
+   conn_t *res = NULL;
+-  unsigned char *foreign_addr = NULL;
+-  int fd = -1, allow_foreign_address = FALSE;
++  int fd = -1;
+   pr_netaddr_t na;
+   socklen_t nalen;
+ 
+@@ -1540,13 +1540,10 @@ conn_t *pr_inet_accept(pool *p, conn_t *d, conn_t *c, int rfd, int wfd,
+   pr_netaddr_set_family(&na, pr_netaddr_get_family(c->remote_addr));
+   nalen = pr_netaddr_get_sockaddr_len(&na);
+ 
++  allow_foreign_addr_config = find_config(TOPLEVEL_CONF, CONF_PARAM,
++    "AllowForeignAddress", FALSE);
+   d->mode = CM_ACCEPT;
+ 
+-  foreign_addr = get_param_ptr(TOPLEVEL_CONF, "AllowForeignAddress", FALSE);
+-  if (foreign_addr != NULL) {
+-    allow_foreign_address = *foreign_addr;
+-  }
+-
+   /* A directive could enforce only IPv4 or IPv6 connections here, by
+    * actually using a sockaddr argument to accept(2), and checking the
+    * family of the connecting entity.
+@@ -1566,28 +1563,67 @@ conn_t *pr_inet_accept(pool *p, conn_t *d, conn_t *c, int rfd, int wfd,
+       break;
+     }
+ 
+-    if (allow_foreign_address == FALSE) {
+-      /* If foreign addresses (i.e. IP addresses that do not match the
+-       * control connection's remote IP address) are not allowed, we
+-       * need to see just what our remote address IS.
+-       */
+-      if (getpeername(fd, pr_netaddr_get_sockaddr(&na), &nalen) < 0) {
+-        /* If getpeername(2) fails, should we still allow this connection?
+-         * Caution (and the AllowForeignAddress setting say "no".
++    if (allow_foreign_addr_config != NULL) {
++      int allowed;
++
++      allowed = *((int *) allow_foreign_addr_config->argv[0]);
++      if (allowed != TRUE) {
++        /* If foreign addresses (i.e. IP addresses that do not match the
++         * control connection's remote IP address) are not allowed, we
++         * need to see just what our remote address IS.
+          */
+-        pr_log_pri(PR_LOG_DEBUG, "rejecting passive connection; "
+-          "failed to get address of remote peer: %s", strerror(errno));
+-        (void) close(fd);
+-        continue;
+-      }
+ 
+-      if (pr_netaddr_cmp(&na, c->remote_addr) != 0) {
+-        pr_log_pri(PR_LOG_NOTICE, "SECURITY VIOLATION: Passive connection "
+-          "from foreign IP address %s rejected (does not match client "
+-          "IP address %s).", pr_netaddr_get_ipstr(&na),
+-          pr_netaddr_get_ipstr(c->remote_addr));
+-        (void) close(fd);
+-        continue;
++        if (getpeername(fd, pr_netaddr_get_sockaddr(&na), &nalen) < 0) {
++          /* If getpeername(2) fails, should we still allow this connection?
++           * Caution (and the AllowForeignAddress setting) say "no".
++           */
++          pr_log_pri(PR_LOG_DEBUG, "rejecting passive connection; "
++            "failed to get address of remote peer: %s", strerror(errno));
++          (void) close(fd);
++          continue;
++        }
++
++        if (allowed == FALSE) {
++          if (pr_netaddr_cmp(&na, c->remote_addr) != 0) {
++            pr_log_pri(PR_LOG_NOTICE, "SECURITY VIOLATION: Passive connection "
++              "from foreign IP address %s rejected (does not match client "
++              "IP address %s).", pr_netaddr_get_ipstr(&na),
++              pr_netaddr_get_ipstr(c->remote_addr));
++
++            (void) close(fd);
++            d->mode = CM_ERROR;
++            d->xerrno = EACCES;
++
++            return NULL;
++          }
++
++        } else {
++          char *class_name;
++          const pr_class_t *cls;
++
++          class_name = allow_foreign_addr_config->argv[1];
++          cls = pr_class_find(class_name);
++          if (cls != NULL) {
++            if (pr_class_satisfied(p, cls, &na) != TRUE) {
++              pr_log_debug(DEBUG8, "<Class> '%s' not satisfied by foreign "
++                "address '%s'", class_name, pr_netaddr_get_ipstr(&na));
++
++              pr_log_pri(PR_LOG_NOTICE,
++                "SECURITY VIOLATION: Passive connection from foreign IP "
++                "address %s rejected (does not match <Class %s>).",
++                pr_netaddr_get_ipstr(&na), class_name);
++
++              (void) close(fd);
++              d->mode = CM_ERROR;
++              d->xerrno = EACCES;
++              return NULL;
++            }
++
++          } else {
++            pr_log_debug(DEBUG8, "<Class> '%s' not found for filtering "
++              "AllowForeignAddress", class_name);
++          }
++        }
+       }
+     }
+ 
+diff --git a/tests/t/lib/ProFTPD/Tests/Config/AllowForeignAddress.pm b/tests/t/lib/ProFTPD/Tests/Config/AllowForeignAddress.pm
+index cd64b5578d..0ee36cbb4e 100644
+--- a/tests/t/lib/ProFTPD/Tests/Config/AllowForeignAddress.pm
++++ b/tests/t/lib/ProFTPD/Tests/Config/AllowForeignAddress.pm
+@@ -26,11 +26,16 @@ my $TESTS = {
+     test_class => [qw(forking)],
+   },
+ 
+-  fxp_denied_by_class => {
++  fxp_port_denied_by_class => {
+     order => ++$order,
+     test_class => [qw(forking)],
+   },
+ 
++  fxp_pasv_denied_by_class_issue1346 => {
++    order => ++$order,
++    test_class => [qw(bug forking)],
++  },
++
+   fxp_allowed => {
+     order => ++$order,
+     test_class => [qw(forking)],
+@@ -41,11 +46,16 @@ my $TESTS = {
+     test_class => [qw(forking)],
+   },
+ 
+-  fxp_allowed_by_class => {
++  fxp_port_allowed_by_class => {
+     order => ++$order,
+     test_class => [qw(forking)],
+   },
+ 
++  fxp_pasv_allowed_by_class_issue1346 => {
++    order => ++$order,
++    test_class => [qw(bug forking)],
++  },
++
+   fxp_allowed_2gb => {
+     order => ++$order,
+     test_class => [qw(forking)],
+@@ -353,7 +363,7 @@ sub fxp_denied_eprt {
+   test_cleanup($setup->{log_file}, $ex);
+ }
+ 
+-sub fxp_denied_by_class {
++sub fxp_port_denied_by_class {
+   my $self = shift;
+   my $tmpdir = $self->{tmpdir};
+   my $setup = test_setup($tmpdir, 'config');
+@@ -519,6 +529,139 @@ EOC
+   test_cleanup($setup->{log_file}, $ex);
+ }
+ 
++sub fxp_pasv_denied_by_class_issue1346 {
++  my $self = shift;
++  my $tmpdir = $self->{tmpdir};
++  my $setup = test_setup($tmpdir, 'config');
++
++  my $class_name = 'allowed_fxp';
++
++  my $config = {
++    PidFile => $setup->{pid_file},
++    ScoreboardFile => $setup->{scoreboard_file},
++    SystemLog => $setup->{log_file},
++
++    AuthUserFile => $setup->{auth_user_file},
++    AuthGroupFile => $setup->{auth_group_file},
++
++    AllowForeignAddress => $class_name,
++
++    IfModules => {
++      'mod_delay.c' => {
++        DelayEngine => 'off',
++      },
++    },
++  };
++
++  my ($port, $config_user, $config_group) = config_write($setup->{config_file},
++    $config);
++
++  if (open(my $fh, ">> $setup->{config_file}")) {
++    print $fh <<EOC;
++<Class $class_name>
++  From none
++</Class>
++EOC
++    unless (close($fh)) {
++      die("Can't write $setup->{config_file}: $!");
++    }
++
++  } else {
++    die("Can't open $setup->{config_file}: $!");
++  }
++
++  # Open pipes, for use between the parent and child processes.  Specifically,
++  # the child will indicate when it's done with its test by writing a message
++  # to the parent.
++  my ($rfh, $wfh);
++  unless (pipe($rfh, $wfh)) {
++    die("Can't open pipe: $!");
++  }
++
++  my $ex;
++
++  # Fork child
++  $self->handle_sigchld();
++  defined(my $pid = fork()) or die("Can't fork: $!");
++  if ($pid) {
++    eval {
++      my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 0, 3);
++      $client->login($setup->{user}, $setup->{passwd});
++
++      # Attemping a data transfer should fail, due to the AllowForeignAddress
++      # class restriction.
++
++      my $conn = $client->list_raw();
++      if ($conn) {
++        die("LIST succeeded unexpectedly");
++      }
++
++      my $resp_code = $client->response_code();
++      my $resp_msg = $client->response_msg();
++
++      my $expected = 425;
++      $self->assert($expected == $resp_code,
++        "Expected response code $expected, got $resp_code");
++
++      $expected = 'Unable to build data connection:';
++      $self->assert(qr/$expected/, $resp_msg,
++        "Expected response message '$expected', got '$resp_msg'");
++
++      $client->quit();
++    };
++    if ($@) {
++      $ex = $@;
++    }
++
++    $wfh->print("done\n");
++    $wfh->flush();
++
++  } else {
++    eval { server_wait($setup->{config_file}, $rfh) };
++    if ($@) {
++      warn($@);
++      exit 1;
++    }
++
++    exit 0;
++  }
++
++  # Stop server
++  server_stop($setup->{pid_file});
++  $self->assert_child_ok($pid);
++
++  eval {
++    if (open(my $fh, "< $setup->{log_file}")) {
++      my $ok = 0;
++
++      while (my $line = <$fh>) {
++        chomp($line);
++
++        if ($ENV{TEST_VERBOSE}) {
++          print STDERR "$line\n";
++        }
++
++        if ($line =~ /SECURITY VIOLATION: Passive connection from foreign IP address \S+ rejected \(does not match <Class \S+>\)/) {
++          $ok = 1;
++          last;
++        }
++      }
++
++      close($fh);
++
++      $self->assert($ok, "Did not see expected log messages");
++
++    } else {
++      die("Can't read $setup->{log_file}: $!");
++    }
++  };
++  if ($@) {
++    $ex = $@;
++  }
++
++  test_cleanup($setup->{log_file}, $ex);
++}
++
+ sub fxp_allowed {
+   my $self = shift;
+   my $tmpdir = $self->{tmpdir};
+@@ -781,7 +924,7 @@ sub fxp_allowed_eprt {
+   test_cleanup($setup->{log_file}, $ex);
+ }
+ 
+-sub fxp_allowed_by_class {
++sub fxp_port_allowed_by_class {
+   my $self = shift;
+   my $tmpdir = $self->{tmpdir};
+   my $setup = test_setup($tmpdir, 'config');
+@@ -926,6 +1069,110 @@ EOC
+   test_cleanup($setup->{log_file}, $ex);
+ }
+ 
++sub fxp_pasv_allowed_by_class_issue1346 {
++  my $self = shift;
++  my $tmpdir = $self->{tmpdir};
++  my $setup = test_setup($tmpdir, 'config');
++
++  my $class_name = 'allowed_fxp';
++
++  my $config = {
++    PidFile => $setup->{pid_file},
++    ScoreboardFile => $setup->{scoreboard_file},
++    SystemLog => $setup->{log_file},
++    TraceLog => $setup->{log_file},
++    Trace => 'class:20 inet:20',
++
++    AuthUserFile => $setup->{auth_user_file},
++    AuthGroupFile => $setup->{auth_group_file},
++
++    AllowForeignAddress => $class_name,
++
++    IfModules => {
++      'mod_delay.c' => {
++        DelayEngine => 'off',
++      },
++    },
++  };
++
++  my ($port, $config_user, $config_group) = config_write($setup->{config_file},
++    $config);
++
++  if (open(my $fh, ">> $setup->{config_file}")) {
++    print $fh <<EOC;
++<Class $class_name>
++  From 127.0.0.0/8
++</Class>
++EOC
++    unless (close($fh)) {
++      die("Can't write $setup->{config_file}: $!");
++    }
++
++  } else {
++    die("Can't open $setup->{config_file}: $!");
++  }
++
++  # Open pipes, for use between the parent and child processes.  Specifically,
++  # the child will indicate when it's done with its test by writing a message
++  # to the parent.
++  my ($rfh, $wfh);
++  unless (pipe($rfh, $wfh)) {
++    die("Can't open pipe: $!");
++  }
++
++  my $ex;
++
++  # Fork child
++  $self->handle_sigchld();
++  defined(my $pid = fork()) or die("Can't fork: $!");
++  if ($pid) {
++    eval {
++      my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port, 0, 3);
++      $client->login($setup->{user}, $setup->{passwd});
++
++      # Attemping a data transfer should succeed, due to the AllowForeignAddress
++      # class restriction.
++      my $conn = $client->list_raw();
++      unless ($conn) {
++        die("Failed to LIST: " . $client->response_code() . " " .
++          $client->response_msg());
++      }
++
++      my $buf;
++      $conn->read($buf, 8192, 30);
++      eval { $conn->close() };
++
++      my ($resp_code, $resp_msg);
++      $resp_code = $client->response_code();
++      $resp_msg = $client->response_msg();
++
++      $self->assert_transfer_ok($resp_code, $resp_msg);
++      $client->quit();
++    };
++    if ($@) {
++      $ex = $@;
++    }
++
++    $wfh->print("done\n");
++    $wfh->flush();
++
++  } else {
++    eval { server_wait($setup->{config_file}, $rfh) };
++    if ($@) {
++      warn($@);
++      exit 1;
++    }
++
++    exit 0;
++  }
++
++  # Stop server
++  server_stop($setup->{pid_file});
++  $self->assert_child_ok($pid);
++
++  test_cleanup($setup->{log_file}, $ex);
++}
++
+ sub fxp_allowed_2gb {
+   my $self = shift;
+   my $tmpdir = $self->{tmpdir};


=====================================
debian/patches/upstream_long_AuthGroupFile_lines
=====================================
@@ -0,0 +1,187 @@
+From 9aff151f6810b8f0e64cc9f7e15dd21ebecd4cc3 Mon Sep 17 00:00:00 2001
+From: TJ Saunders <tj at castaglia.org>
+Date: Fri, 28 Jan 2022 08:21:44 -0800
+Subject: [PATCH] Backporting buffering fixes when parsing long `AuthGroupFile`
+ lines.
+
+---
+ modules/mod_auth_file.c | 87 ++++++++++++++++++++++++++++++++---------
+ 1 file changed, 68 insertions(+), 19 deletions(-)
+
+diff --git a/modules/mod_auth_file.c b/modules/mod_auth_file.c
+index b1ccaa771..3530905f1 100644
+--- a/modules/mod_auth_file.c
++++ b/modules/mod_auth_file.c
+@@ -1,7 +1,7 @@
+ /*
+  * ProFTPD: mod_auth_file - file-based authentication module that supports
+  *                          restrictions on the file contents
+- * Copyright (c) 2002-2021 The ProFTPD Project team
++ * Copyright (c) 2002-2022 The ProFTPD Project team
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+@@ -325,24 +325,35 @@ static struct passwd *af_getpasswd(const char *buf, unsigned int lineno) {
+ #define NGRPFIELDS      4
+ 
+ static char *grpbuf = NULL;
++static size_t grpbufsz = 0;
+ static struct group grent;
+ static char *grpfields[NGRPFIELDS];
+ static char *members[MAXMEMBERS+1];
+ 
+-static char *af_getgrentline(char **buf, int *buflen, pr_fh_t *fh,
++static char *af_getgrentline(char **buf, size_t *bufsz, pr_fh_t *fh,
+     unsigned int *lineno) {
+-  char *cp = *buf;
+-  int original_buflen;
++  char *ptr, *res;
++  size_t original_bufsz, buflen;
+ 
+-  original_buflen = *buflen;
++  original_bufsz = *bufsz;
++  buflen = *bufsz;
+ 
+-  while (pr_fsio_gets(cp, (*buflen) - (cp - *buf), fh) != NULL) {
+-    pr_signals_handle();
++  /* Try to keep our unfilled buffer zeroed out, so that strlen(3) et al
++   * work as expected.
++   */
++  memset(*buf, '\0', *bufsz);
+ 
+-    (*lineno)++;
++  ptr = *buf;
++  res = pr_fsio_gets(ptr, buflen, fh);
++  while (res != NULL) {
++    pr_signals_handle();
+ 
+     /* Is this a full line? */
+-    if (strchr(cp, '\n')) {
++    if (strchr(*buf, '\n') != NULL) {
++      pr_trace_msg(trace_channel, 25,
++        "found LF, returning line: '%s' (%lu bytes)", *buf,
++        (unsigned long) strlen(*buf));
++      (*lineno)++;
+       return *buf;
+     }
+ 
+@@ -351,26 +362,37 @@ static char *af_getgrentline(char **buf, int *buflen, pr_fh_t *fh,
+      * allocated buffer by the original buffer length each time.  So we
+      * do the same (Issue #1321).
+      */
+-    *buflen += original_buflen;
+-
+     {
++      size_t new_bufsz;
+       char *new_buf;
+ 
+-      new_buf = realloc(*buf, *buflen);
++      pr_trace_msg(trace_channel, 25, "getgrentline() buffer (%lu bytes): "
++        "'%.*s'", (unsigned long) *bufsz, (int) *bufsz, *buf);
++
++      pr_trace_msg(trace_channel, 19,
++        "no LF found in group line, increasing buffer (%lu bytes) by %lu bytes",
++        (unsigned long) *bufsz, (unsigned long) original_bufsz);
++      new_bufsz = *bufsz + original_bufsz;
++
++      new_buf = realloc(*buf, new_bufsz);
+       if (new_buf == NULL) {
+         break;
+       }
+ 
++      ptr = new_buf + *bufsz;
+       *buf = new_buf;
++      *bufsz = new_bufsz;
++      buflen = original_bufsz;
++
++      memset(ptr, '\0', buflen);
+     }
+ 
+-    cp = *buf + (cp - *buf);
+-    cp = strchr(cp, '\0');
++    res = pr_fsio_gets(ptr, buflen, fh);
+   }
+ 
+   free(*buf);
+   *buf = NULL;
+-  *buflen = 0;
++  *bufsz = 0;
+ 
+   return NULL;
+ }
+@@ -401,22 +423,29 @@ static struct group *af_getgrp(const char *buf, unsigned int lineno) {
+ 
+   i = strlen(buf) + 1;
+ 
+-  if (!grpbuf) {
++  if (grpbuf == NULL) {
++    grpbufsz = i;
+     grpbuf = malloc(i);
+ 
+-  } else {
++  } else if (grpbufsz < (size_t) i) {
+     char *new_buf;
+ 
++    pr_trace_msg(trace_channel, 19,
++      "parsing group line '%s' (%lu bytes), allocating %lu bytes via "
++      "realloc(3)", buf, (unsigned long) i, (unsigned long) i);
++
+     new_buf = realloc(grpbuf, i);
+     if (new_buf == NULL) {
+       return NULL;
+     }
+ 
+     grpbuf = new_buf;
++    grpbufsz = i;
+   }
+ 
+-  if (!grpbuf)
++  if (grpbuf == NULL) {
+     return NULL;
++  }
+ 
+   sstrncpy(grpbuf, buf, i);
+ 
+@@ -524,7 +553,16 @@ static struct group *af_getgrent(pool *p) {
+ 
+   while (TRUE) {
+     char *cp = NULL, *buf = NULL;
+-    int buflen = PR_TUNABLE_BUFFER_SIZE;
++    size_t buflen;
++
++    buflen = PR_TUNABLE_BUFFER_SIZE;
++
++    if (af_group_file->af_file_fh->fh_iosz > 0) {
++      /* This aligns our group(5) buffer with the preferred filesystem read
++       * block size.
++       */
++      buflen = af_group_file->af_file_fh->fh_iosz;
++    }
+ 
+     pr_signals_handle();
+ 
+@@ -533,6 +571,11 @@ static struct group *af_getgrent(pool *p) {
+       pr_log_pri(PR_LOG_ALERT, "Out of memory!");
+       _exit(1);
+     }
++
++    pr_trace_msg(trace_channel, 19,
++      "getgrent(3): allocated buffer %p (%lu bytes)", buf,
++      (unsigned long) buflen);
++
+     grp = NULL;
+ 
+     while (af_getgrentline(&buf, &buflen, af_group_file->af_file_fh,
+@@ -636,6 +679,12 @@ static int af_setgrent(pool *p) {
+         pbuf->remaining = pbuf->buflen;
+       }
+ 
++      if (grpbuf != NULL) {
++        free(grpbuf);
++        grpbuf = NULL;
++      }
++      grpbufsz = 0;
++
+       return 0;
+     }
+ 



View it on GitLab: https://salsa.debian.org/debian-proftpd-team/proftpd/-/commit/fbc2d5716815378eca0bf62ec472643fd2c5f6e4

-- 
View it on GitLab: https://salsa.debian.org/debian-proftpd-team/proftpd/-/commit/fbc2d5716815378eca0bf62ec472643fd2c5f6e4
You're receiving this email because of your account on salsa.debian.org.




More information about the Pkg-proftpd-maintainers mailing list