All of lore.kernel.org
 help / color / mirror / Atom feed
From: kernel test robot <lkp@intel.com>
To: kbuild@lists.01.org
Subject: [bcache:nvdimm-meta 11/12] drivers/md/bcache/journal.c:123:27: warning: Access to field 'keys' results in a dereference of an undefined pointer value (loaded from variable 'j') [clang-analyzer-core.NullDereference]
Date: Sat, 14 Aug 2021 16:21:39 +0800	[thread overview]
Message-ID: <202108141631.73CzyCqx-lkp@intel.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 21776 bytes --]

CC: clang-built-linux(a)googlegroups.com
CC: kbuild-all(a)lists.01.org
CC: linux-kernel(a)vger.kernel.org
TO: Coly Li <colyli@suse.de>

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/colyli/linux-bcache.git nvdimm-meta
head:   8479d552442398498ffcf15d551ff22a63b799e3
commit: f2800a148cb8ca81162d7c898f058df2e230b1e2 [11/12] bcache: read jset from NVDIMM pages for journal replay
:::::: branch date: 3 days ago
:::::: commit date: 3 days ago
config: x86_64-randconfig-c001-20210811 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project d39ebdae674c8efc84ebe8dc32716ec353220530)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install x86_64 cross compiling tool for clang build
        # apt-get install binutils-x86-64-linux-gnu
        # https://git.kernel.org/pub/scm/linux/kernel/git/colyli/linux-bcache.git/commit/?id=f2800a148cb8ca81162d7c898f058df2e230b1e2
        git remote add bcache https://git.kernel.org/pub/scm/linux/kernel/git/colyli/linux-bcache.git
        git fetch --no-tags bcache nvdimm-meta
        git checkout f2800a148cb8ca81162d7c898f058df2e230b1e2
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 clang-analyzer 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


clang-analyzer warnings: (new ones prefixed by >>)
   drivers/nvme/host/fc.c:3794:11: note: Loop condition is false.  Exiting loop
                   rport = list_first_entry(&local_disc_list,
                           ^
   include/linux/list.h:522:2: note: expanded from macro 'list_first_entry'
           list_entry((ptr)->next, type, member)
           ^
   include/linux/list.h:511:2: note: expanded from macro 'list_entry'
           container_of(ptr, type, member)
           ^
   include/linux/kernel.h:495:2: note: expanded from macro 'container_of'
           BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) &&   \
           ^
   note: (skipping 1 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
   include/linux/compiler_types.h:328:2: note: expanded from macro 'compiletime_assert'
           _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
           ^
   include/linux/compiler_types.h:316:2: note: expanded from macro '_compiletime_assert'
           __compiletime_assert(condition, msg, prefix, suffix)
           ^
   include/linux/compiler_types.h:306:2: note: expanded from macro '__compiletime_assert'
           do {                                                            \
           ^
   drivers/nvme/host/fc.c:3796:3: note: Calling 'list_del_init'
                   list_del_init(&rport->disc_list);
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/list.h:204:2: note: Calling '__list_del_entry'
           __list_del_entry(entry);
           ^~~~~~~~~~~~~~~~~~~~~~~
   include/linux/list.h:132:6: note: Assuming the condition is false
           if (!__list_del_entry_valid(entry))
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/list.h:132:2: note: Taking false branch
           if (!__list_del_entry_valid(entry))
           ^
   include/linux/list.h:135:13: note: Use of memory after it is freed
           __list_del(entry->prev, entry->next);
                      ^~~~~~~~~~~
   Suppressed 4 warnings (4 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   3 warnings generated.
   Suppressed 3 warnings (3 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   2 warnings generated.
   Suppressed 2 warnings (2 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   6 warnings generated.
>> drivers/md/bcache/journal.c:123:27: warning: Access to field 'keys' results in a dereference of an undefined pointer value (loaded from variable 'j') [clang-analyzer-core.NullDereference]
                           size_t blocks, bytes = set_bytes(j);
                                                  ^
   drivers/md/bcache/bset.h:262:23: note: expanded from macro 'set_bytes'
   #define set_bytes(i)            __set_bytes(i, i->keys)
                                   ^
   drivers/md/bcache/bset.h:261:43: note: expanded from macro '__set_bytes'
   #define __set_bytes(i, k)       (sizeof(*(i)) + (k) * sizeof(uint64_t))
                                                   ^
   drivers/md/bcache/journal.c:240:2: note: Taking false branch
           if (bch_has_feature_nvdimm_meta(&ca->sb)) {
           ^
   drivers/md/bcache/journal.c:246:2: note: Taking false branch
           pr_debug("%u journal buckets\n", ca->sb.njournal_buckets);
           ^
   include/linux/printk.h:471:2: note: expanded from macro 'pr_debug'
           dynamic_pr_debug(fmt, ##__VA_ARGS__)
           ^
   include/linux/dynamic_debug.h:162:2: note: expanded from macro 'dynamic_pr_debug'
           _dynamic_func_call(fmt, __dynamic_pr_debug,             \
           ^
   include/linux/dynamic_debug.h:152:2: note: expanded from macro '_dynamic_func_call'
           __dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
           ^
   include/linux/dynamic_debug.h:133:2: note: expanded from macro '__dynamic_func_call'
           if (DYNAMIC_DEBUG_BRANCH(id))                   \
           ^
   drivers/md/bcache/journal.c:246:2: note: Loop condition is false.  Exiting loop
           pr_debug("%u journal buckets\n", ca->sb.njournal_buckets);
           ^
   include/linux/printk.h:471:2: note: expanded from macro 'pr_debug'
           dynamic_pr_debug(fmt, ##__VA_ARGS__)
           ^
   include/linux/dynamic_debug.h:162:2: note: expanded from macro 'dynamic_pr_debug'
           _dynamic_func_call(fmt, __dynamic_pr_debug,             \
           ^
   include/linux/dynamic_debug.h:152:2: note: expanded from macro '_dynamic_func_call'
           __dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
           ^
   include/linux/dynamic_debug.h:131:49: note: expanded from macro '__dynamic_func_call'
   #define __dynamic_func_call(id, fmt, func, ...) do {    \
                                                   ^
   drivers/md/bcache/journal.c:252:14: note: Assuming 'i' is < field 'njournal_buckets'
           for (i = 0; i < ca->sb.njournal_buckets; i++) {
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/md/bcache/journal.c:252:2: note: Loop condition is true.  Entering loop body
           for (i = 0; i < ca->sb.njournal_buckets; i++) {
           ^
   drivers/md/bcache/journal.c:260:7: note: Assuming the condition is false
                   if (test_bit(l, bitmap))
                       ^~~~~~~~~~~~~~~~~~~
   drivers/md/bcache/journal.c:260:3: note: Taking false branch
                   if (test_bit(l, bitmap))
                   ^
   drivers/md/bcache/journal.c:263:7: note: 'ret' is >= 0
                   if (read_bucket(l))
                       ^
   drivers/md/bcache/journal.c:224:7: note: expanded from macro 'read_bucket'
                   if (ret < 0)                                            \
                       ^~~
   drivers/md/bcache/journal.c:263:7: note: Taking false branch
                   if (read_bucket(l))
                       ^
   drivers/md/bcache/journal.c:224:3: note: expanded from macro 'read_bucket'
                   if (ret < 0)                                            \
                   ^
   drivers/md/bcache/journal.c:263:3: note: Taking false branch
                   if (read_bucket(l))
                   ^
   drivers/md/bcache/journal.c:252:14: note: Assuming 'i' is < field 'njournal_buckets'
           for (i = 0; i < ca->sb.njournal_buckets; i++) {
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/md/bcache/journal.c:252:2: note: Loop condition is true.  Entering loop body
           for (i = 0; i < ca->sb.njournal_buckets; i++) {
           ^
   drivers/md/bcache/journal.c:260:7: note: Assuming the condition is false
                   if (test_bit(l, bitmap))
                       ^~~~~~~~~~~~~~~~~~~
   drivers/md/bcache/journal.c:260:3: note: Taking false branch
                   if (test_bit(l, bitmap))
                   ^
   drivers/md/bcache/journal.c:263:7: note: Calling 'journal_read_bucket'
                   if (read_bucket(l))
                       ^
   drivers/md/bcache/journal.c:222:9: note: expanded from macro 'read_bucket'
                   ret = journal_read_bucket(ca, list, b);                 \
                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/md/bcache/journal.c:87:2: note: 'j' declared without an initial value
           struct jset *j;
           ^~~~~~~~~~~~~~
   drivers/md/bcache/journal.c:94:2: note: Taking false branch
           pr_debug("reading %u\n", bucket_index);
           ^
   include/linux/printk.h:471:2: note: expanded from macro 'pr_debug'
           dynamic_pr_debug(fmt, ##__VA_ARGS__)
           ^
   include/linux/dynamic_debug.h:162:2: note: expanded from macro 'dynamic_pr_debug'
           _dynamic_func_call(fmt, __dynamic_pr_debug,             \
           ^
   include/linux/dynamic_debug.h:152:2: note: expanded from macro '_dynamic_func_call'
           __dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)

vim +123 drivers/md/bcache/journal.c

cafe563591446c Kent Overstreet   2013-03-23  115  
cafe563591446c Kent Overstreet   2013-03-23  116  		/* This function could be simpler now since we no longer write
cafe563591446c Kent Overstreet   2013-03-23  117  		 * journal entries that overlap bucket boundaries; this means
cafe563591446c Kent Overstreet   2013-03-23  118  		 * the start of a bucket will always have a valid journal entry
cafe563591446c Kent Overstreet   2013-03-23  119  		 * if it has any journal entries at all.
cafe563591446c Kent Overstreet   2013-03-23  120  		 */
cafe563591446c Kent Overstreet   2013-03-23  121  		while (len) {
cafe563591446c Kent Overstreet   2013-03-23  122  			struct list_head *where;
cafe563591446c Kent Overstreet   2013-03-23 @123  			size_t blocks, bytes = set_bytes(j);
cafe563591446c Kent Overstreet   2013-03-23  124  
b3fa7e77e67e64 Kent Overstreet   2013-08-05  125  			if (j->magic != jset_magic(&ca->sb)) {
46f5aa8806e34f Joe Perches       2020-05-27  126  				pr_debug("%u: bad magic\n", bucket_index);
cafe563591446c Kent Overstreet   2013-03-23  127  				return ret;
b3fa7e77e67e64 Kent Overstreet   2013-08-05  128  			}
cafe563591446c Kent Overstreet   2013-03-23  129  
b3fa7e77e67e64 Kent Overstreet   2013-08-05  130  			if (bytes > left << 9 ||
b3fa7e77e67e64 Kent Overstreet   2013-08-05  131  			    bytes > PAGE_SIZE << JSET_BITS) {
46f5aa8806e34f Joe Perches       2020-05-27  132  				pr_info("%u: too big, %zu bytes, offset %u\n",
b3fa7e77e67e64 Kent Overstreet   2013-08-05  133  					bucket_index, bytes, offset);
cafe563591446c Kent Overstreet   2013-03-23  134  				return ret;
b3fa7e77e67e64 Kent Overstreet   2013-08-05  135  			}
cafe563591446c Kent Overstreet   2013-03-23  136  
cafe563591446c Kent Overstreet   2013-03-23  137  			if (bytes > len << 9)
cafe563591446c Kent Overstreet   2013-03-23  138  				goto reread;
cafe563591446c Kent Overstreet   2013-03-23  139  
b3fa7e77e67e64 Kent Overstreet   2013-08-05  140  			if (j->csum != csum_set(j)) {
46f5aa8806e34f Joe Perches       2020-05-27  141  				pr_info("%u: bad csum, %zu bytes, offset %u\n",
b3fa7e77e67e64 Kent Overstreet   2013-08-05  142  					bucket_index, bytes, offset);
cafe563591446c Kent Overstreet   2013-03-23  143  				return ret;
b3fa7e77e67e64 Kent Overstreet   2013-08-05  144  			}
cafe563591446c Kent Overstreet   2013-03-23  145  
4e1ebae3ee4e0c Coly Li           2020-10-01  146  			blocks = set_blocks(j, block_bytes(ca));
cafe563591446c Kent Overstreet   2013-03-23  147  
2464b693148e5d Coly Li           2019-06-28  148  			/*
2464b693148e5d Coly Li           2019-06-28  149  			 * Nodes in 'list' are in linear increasing order of
2464b693148e5d Coly Li           2019-06-28  150  			 * i->j.seq, the node on head has the smallest (oldest)
2464b693148e5d Coly Li           2019-06-28  151  			 * journal seq, the node on tail has the biggest
2464b693148e5d Coly Li           2019-06-28  152  			 * (latest) journal seq.
2464b693148e5d Coly Li           2019-06-28  153  			 */
2464b693148e5d Coly Li           2019-06-28  154  
2464b693148e5d Coly Li           2019-06-28  155  			/*
2464b693148e5d Coly Li           2019-06-28  156  			 * Check from the oldest jset for last_seq. If
2464b693148e5d Coly Li           2019-06-28  157  			 * i->j.seq < j->last_seq, it means the oldest jset
2464b693148e5d Coly Li           2019-06-28  158  			 * in list is expired and useless, remove it from
9c9b81c45619e7 Bhaskar Chowdhury 2021-04-11  159  			 * this list. Otherwise, j is a candidate jset for
2464b693148e5d Coly Li           2019-06-28  160  			 * further following checks.
2464b693148e5d Coly Li           2019-06-28  161  			 */
cafe563591446c Kent Overstreet   2013-03-23  162  			while (!list_empty(list)) {
cafe563591446c Kent Overstreet   2013-03-23  163  				i = list_first_entry(list,
cafe563591446c Kent Overstreet   2013-03-23  164  					struct journal_replay, list);
cafe563591446c Kent Overstreet   2013-03-23  165  				if (i->j.seq >= j->last_seq)
cafe563591446c Kent Overstreet   2013-03-23  166  					break;
cafe563591446c Kent Overstreet   2013-03-23  167  				list_del(&i->list);
cafe563591446c Kent Overstreet   2013-03-23  168  				kfree(i);
cafe563591446c Kent Overstreet   2013-03-23  169  			}
cafe563591446c Kent Overstreet   2013-03-23  170  
2464b693148e5d Coly Li           2019-06-28  171  			/* iterate list in reverse order (from latest jset) */
cafe563591446c Kent Overstreet   2013-03-23  172  			list_for_each_entry_reverse(i, list, list) {
cafe563591446c Kent Overstreet   2013-03-23  173  				if (j->seq == i->j.seq)
cafe563591446c Kent Overstreet   2013-03-23  174  					goto next_set;
cafe563591446c Kent Overstreet   2013-03-23  175  
2464b693148e5d Coly Li           2019-06-28  176  				/*
2464b693148e5d Coly Li           2019-06-28  177  				 * if j->seq is less than any i->j.last_seq
2464b693148e5d Coly Li           2019-06-28  178  				 * in list, j is an expired and useless jset.
2464b693148e5d Coly Li           2019-06-28  179  				 */
cafe563591446c Kent Overstreet   2013-03-23  180  				if (j->seq < i->j.last_seq)
cafe563591446c Kent Overstreet   2013-03-23  181  					goto next_set;
cafe563591446c Kent Overstreet   2013-03-23  182  
2464b693148e5d Coly Li           2019-06-28  183  				/*
2464b693148e5d Coly Li           2019-06-28  184  				 * 'where' points to first jset in list which
2464b693148e5d Coly Li           2019-06-28  185  				 * is elder then j.
2464b693148e5d Coly Li           2019-06-28  186  				 */
cafe563591446c Kent Overstreet   2013-03-23  187  				if (j->seq > i->j.seq) {
cafe563591446c Kent Overstreet   2013-03-23  188  					where = &i->list;
cafe563591446c Kent Overstreet   2013-03-23  189  					goto add;
cafe563591446c Kent Overstreet   2013-03-23  190  				}
cafe563591446c Kent Overstreet   2013-03-23  191  			}
cafe563591446c Kent Overstreet   2013-03-23  192  
cafe563591446c Kent Overstreet   2013-03-23  193  			where = list;
cafe563591446c Kent Overstreet   2013-03-23  194  add:
cafe563591446c Kent Overstreet   2013-03-23  195  			i = kmalloc(offsetof(struct journal_replay, j) +
cafe563591446c Kent Overstreet   2013-03-23  196  				    bytes, GFP_KERNEL);
cafe563591446c Kent Overstreet   2013-03-23  197  			if (!i)
cafe563591446c Kent Overstreet   2013-03-23  198  				return -ENOMEM;
cafe563591446c Kent Overstreet   2013-03-23  199  			memcpy(&i->j, j, bytes);
2464b693148e5d Coly Li           2019-06-28  200  			/* Add to the location after 'where' points to */
cafe563591446c Kent Overstreet   2013-03-23  201  			list_add(&i->list, where);
cafe563591446c Kent Overstreet   2013-03-23  202  			ret = 1;
cafe563591446c Kent Overstreet   2013-03-23  203  
a231f07a5fe30a Coly Li           2019-06-28  204  			if (j->seq > ja->seq[bucket_index])
cafe563591446c Kent Overstreet   2013-03-23  205  				ja->seq[bucket_index] = j->seq;
cafe563591446c Kent Overstreet   2013-03-23  206  next_set:
cafe563591446c Kent Overstreet   2013-03-23  207  			offset	+= blocks * ca->sb.block_size;
cafe563591446c Kent Overstreet   2013-03-23  208  			len	-= blocks * ca->sb.block_size;
cafe563591446c Kent Overstreet   2013-03-23  209  			j = ((void *) j) + blocks * block_bytes(ca);
cafe563591446c Kent Overstreet   2013-03-23  210  		}
cafe563591446c Kent Overstreet   2013-03-23  211  	}
cafe563591446c Kent Overstreet   2013-03-23  212  
cafe563591446c Kent Overstreet   2013-03-23  213  	return ret;
cafe563591446c Kent Overstreet   2013-03-23  214  }
cafe563591446c Kent Overstreet   2013-03-23  215  

:::::: The code at line 123 was first introduced by commit
:::::: cafe563591446cf80bfbc2fe3bc72a2e36cf1060 bcache: A block layer cache

:::::: TO: Kent Overstreet <koverstreet@google.com>
:::::: CC: Kent Overstreet <koverstreet@google.com>

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 35881 bytes --]

             reply	other threads:[~2021-08-14  8:21 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-14  8:21 kernel test robot [this message]
  -- strict thread matches above, loose matches on Subject: below --
2021-08-26  6:34 [bcache:nvdimm-meta 11/12] drivers/md/bcache/journal.c:123:27: warning: Access to field 'keys' results in a dereference of an undefined pointer value (loaded from variable 'j') [clang-analyzer-core.NullDereference] kernel test robot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=202108141631.73CzyCqx-lkp@intel.com \
    --to=lkp@intel.com \
    --cc=kbuild@lists.01.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.