Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ DIALECT_NEUTRAL_TESTS = tests/case-00-hello.bash \
tests/case-20-repeat-count.bash \
tests/case-21-exit-Q-status.bash \
tests/case-22-empty-process-name.bash \
tests/case-23-multi-address-hostname.bash \
tests/case-30-json-output.bash \
tests/case-31-jsonl-output.bash
TESTS = $(DIALECT_NEUTRAL_TESTS)
Expand Down
41 changes: 29 additions & 12 deletions src/arg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1604,6 +1604,8 @@ int enter_network_address(struct lsof_context *ctx, /* context */
}
if (sn)
(void)free((FREE_P *)sn);
if (n.proto)
(void)free((FREE_P *)n.proto);
if (hn)
(void)free((FREE_P *)hn);
return (0);
Expand All @@ -1627,18 +1629,6 @@ static int enter_nwad(struct lsof_context *ctx, /* context */
static int na = 0;
struct nwad nc;
struct nwad *np;
/*
* Allocate space for the argument specification.
*/
if (strlen(s)) {
if (!(n->arg = mkstrcpy(s, (MALLOC_S *)NULL))) {
(void)fprintf(stderr, "%s: no space for Internet argument: -i ",
Pn);
safestrprt(s, stderr, 1);
Error(ctx);
}
} else
n->arg = (char *)NULL;
/*
* Loop through all hostent addresses.
*/
Expand Down Expand Up @@ -1687,8 +1677,35 @@ static int enter_nwad(struct lsof_context *ctx, /* context */
}
/*
* Construct and link the address specification.
*
* Each nwad owns copies of its argument and protocol strings. A
* hostent may contain several addresses, so sharing the strings
* between the resulting nwad entries would make lsof_destroy() free
* the same allocation more than once.
*/
*np = nc;
np->arg = (char *)NULL;
if (strlen(s)) {
if (!(np->arg = mkstrcpy(s, (MALLOC_S *)NULL))) {
(void)fprintf(stderr,
"%s: no space for Internet argument: -i ", Pn);
safestrprt(s, stderr, 1);
(void)free((FREE_P *)np);
Error(ctx);
}
}
if (n->proto) {
if (!(np->proto = mkstrcpy(n->proto, (MALLOC_S *)NULL))) {
(void)fprintf(stderr, "%s: no space for protocol name: -i ",
Pn);
safestrprt(s, stderr, 1);
if (np->arg)
(void)free((FREE_P *)np->arg);
(void)free((FREE_P *)np);
Error(ctx);
}
} else
np->proto = (char *)NULL;
np->sport = sp;
np->eport = ep;
np->f = 0;
Expand Down
51 changes: 51 additions & 0 deletions tests/case-23-multi-address-hostname.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env bash
# Regression test for https://github.com/lsof-org/lsof/issues/370
#
# A host name can resolve to several addresses. lsof creates one nwad entry
# for each address, and lsof_destroy() frees the argument and protocol strings
# of every entry. If those strings are shared between entries, lsof frees the
# same allocation more than once and aborts before it can flush its output.
source tests/common.bash

if ! command -v python3 >/dev/null 2>&1; then
echo "SKIP: python3 not available" >> "$report"
exit 77
fi

host=$(hostname)
naddr=$(python3 - "$host" <<'PY'
import socket
import sys

host = sys.argv[1]
count = 0
for family in (socket.AF_INET, socket.AF_INET6):
try:
infos = socket.getaddrinfo(host, None, family, socket.SOCK_STREAM)
except OSError:
continue
count = max(count, len({info[4][0] for info in infos}))
print(count)
PY
)

if [ "${naddr:-0}" -lt 2 ]; then
echo "SKIP: $host resolves to fewer than two addresses in one family" \
>> "$report"
exit 77
fi

{
echo "host name: $host ($naddr addresses in one address family)"
$lsof -a -i@"$host" -p $$ >/dev/null 2>&1
status=$?
case $status in
0|1)
echo "PASS: lsof -a -i@$host -p $$ exited with status $status"
;;
*)
echo "FAIL: lsof -a -i@$host -p $$ exited with status $status"
exit 1
;;
esac
} >> "$report" 2>&1
Loading