NetBSD Problem Report #48881

From woods@once.weird.com  Sun Jun  8 04:10:57 2014
Return-Path: <woods@once.weird.com>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
	(using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits))
	(Client CN "mail.netbsd.org", Issuer "Postmaster NetBSD.org" (verified OK))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 40F04A6521
	for <gnats-bugs@gnats.NetBSD.org>; Sun,  8 Jun 2014 04:10:57 +0000 (UTC)
Message-Id: <m1WtURX-001ECZC@once.weird.com>
Date: Sat, 7 Jun 2014 21:10:51 -0700 (PDT)
From: "Greg A. Woods" <woods@planix.com>
Sender: "Greg A. Woods" <woods@once.weird.com>
To: gnats-bugs@gnats.NetBSD.org
Subject: /etc/hosts file parsing broken (since Aug 2013)
X-Send-Pr-Version: 3.95

>Number:         48881
>Category:       lib
>Synopsis:       /etc/hosts file parsing broken (since Aug 2013)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Jun 08 04:15:00 +0000 2014
>Last-Modified:  Wed Jun 18 03:15:00 +0000 2014
>Originator:     Greg A. Woods
>Release:        NetBSD current 2014/06/06
>Organization:
Planix, Inc.; Kelowna, BC; Canada
>Environment:


System: NetBSD
>Description:

	some massive changes to the gethost*() functions introduced a
	bug in the parsing of the /etc/hosts file due to unsafe use of
	fgetln():

	http://mail-index.netbsd.org/source-changes/2013/08/16/msg046780.html

>How-To-Repeat:

	try running a LAN server with /etc/hosts alone

>Fix:

	This is most definitely _NOT_ the best or safest fix, but it
	does work for me for now.

	I don't think fgetln() ensures an extra byte at the end of
	buffer is always available to be clobbered with a NUL.

	A proper fix that also deals with the missing-last-newline issue
	will probably require copying the line (up to the first newline
	or llen, whichever comes first) to a new buffer anyway (as per
	the example in fgetln(3)) so maybe that should be done for every
	line just to be safe.

	The final fix will need to be pulled up to netbsd-5 and netbsd-6 too.

Index: gethnamaddr.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/lib/libc/net/gethnamaddr.c,v
retrieving revision 1.90
diff -u -u -r1.90 gethnamaddr.c
--- gethnamaddr.c	24 Jan 2014 17:26:18 -0000	1.90
+++ gethnamaddr.c	8 Jun 2014 03:56:37 -0000
@@ -740,6 +740,7 @@
 {
 	char *p, *name;
 	char *cp, **q;
+	char nxt;
 	int af, len;
 	size_t llen, anum;
 	char **aliases;
@@ -762,12 +763,17 @@
 		goto again;
 	if (*p == '#')
 		goto again;
-	p[llen] = '\0';
-	if (!(cp = strpbrk(p, "#\n")))
+	nxt = p[llen];			/* xxx this may not be safe... */
+	p[llen] = '\0';			/* xxx this may not be safe... */
+	if (!(cp = strpbrk(p, "#\n"))) {	/* xxx this ignores the last line if it does not end in a newline!!! */
+		p[llen] = nxt;
 		goto again;
+	}
 	*cp = '\0';
-	if (!(cp = strpbrk(p, " \t")))
+	if (!(cp = strpbrk(p, " \t"))) {
+		p[llen] = nxt;
 		goto again;
+	}
 	*cp++ = '\0';
 	if (inet_pton(AF_INET6, p, &host_addr) > 0) {
 		af = AF_INET6;
@@ -786,14 +792,18 @@
 		}
 		__res_put_state(res);
 	} else {
+		p[llen] = nxt;
 		goto again;
 	}
 	/* if this is not something we're looking for, skip it. */
-	if (hent->h_addrtype != 0 && hent->h_addrtype != af)
+	if (hent->h_addrtype != 0 && hent->h_addrtype != af) {
+		p[llen] = nxt;
 		goto again;
-	if (hent->h_length != 0 && hent->h_length != len)
+	}
+	if (hent->h_length != 0 && hent->h_length != len) {
+		p[llen] = nxt;
 		goto again;
-
+	}
 	while (*cp == ' ' || *cp == '\t')
 		cp++;
 	if ((cp = strpbrk(name = cp, " \t")) != NULL)

>Audit-Trail:
From: "Greg A. Woods" <woods@planix.ca>
To: NetBSD GNATS <gnats-bugs@NetBSD.org>
Cc: 
Subject: Re: lib/48881: /etc/hosts file parsing broken (since Aug 2013)
Date: Fri, 13 Jun 2014 15:03:49 -0700

 Appended is a new improved patch that would fully fix the bug for
 netbsd-5 (but the patch is against -current, and fixes the missing final
 newline ase for -current), and it includes some new test cases for
 -current.

 I was of course unable to reproduce the original bug in in -current.

 The bug is only really nasty in the netbsd-5 branch (since NetBSD-5.2).

 It disappears (in an un-documented way) in -current because of changes
 in the implementation fgetln().

 In netbsd-5 writing the NUL byte past the length returned by fgetln()
 tromps on the first character of the next line and so that line is
 treated as empty (the next strpbrk() can't find any newline or '#').
 Only a blank or comment line in the input will "accidentally" reset the
 bug and allow the code to see the full next line and confuse the heck
 out of the person trying to figure out the problem.

 The code could probably use getdelim() or getline() instead of fgetln()
 if it really wants to assume the result is a C string.  Otherwise it
 should follow the rules for portable use of fgetln().  Better to be
 clearly safe than sorry.

 However the code still doesn't work correctly for the missing final
 newline case (i.e. the last entry in a hosts file with no final newline
 on that last entry cannot be found by name or by address).

 The extra mallocs could be avoided in all but the missing final newline
 case I suppose (while still using fgetln()), but at the expense of more
 complex code.  However now that the aliases array is also malloced there
 doesn't seem to be any point to trying to avoid using malloc in this
 code, and it's not likely anyone will have huge numbers of entries in
 /etc/hosts (and thus huge numbers of mallocs) anyway.

 --=20
 						Greg A. Woods
 						Planix, Inc.

 <woods@planix.com>       +1 250 762-7675        http://www.planix.com/

 Index: tests/lib/libc/net/t_hostent.sh
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: /cvs/master/m-NetBSD/main/src/tests/lib/libc/net/t_hostent.sh,v
 retrieving revision 1.10
 diff -u -r1.10 t_hostent.sh
 --- tests/lib/libc/net/t_hostent.sh	13 Jan 2014 11:08:14 -0000	1.10
 +++ tests/lib/libc/net/t_hostent.sh	13 Jun 2014 20:49:05 -0000
 @@ -41,6 +41,30 @@
  al4=3D"127.0.0.1"
  loc4=3D"name=3D$l4, length=3D4, addrtype=3D2, aliases=3D[localhost. localh=
 ost.localdomain.] addr_list=3D[$al4]\n"
 =20
 +# Many more combinations should be provided in hosts and tried here,
 +# but this should scratch most major features and edge cases, though
 +# just one at a time....
 +
 +f4=3D"oldfoohost.local"
 +af4=3D"10.0.1.1"
 +resf4=3D"name=3Dfoohost.local, length=3D4, addrtype=3D2, aliases=3D[$f4] a=
 ddr_list=3D[$af4]\n"
 +
 +cm4=3D"commented.local"
 +acm4=3D"10.0.2.2"
 +rescm4=3D"name=3Dcommented, length=3D4, addrtype=3D2, aliases=3D[$cm4] add=
 r_list=3D[$acm4]\n"
 +
 +sp4=3D"spaced.local"
 +asp4=3D"10.0.3.3"
 +ressp4=3D"name=3D$sp4, length=3D4, addrtype=3D2, aliases=3D[] addr_list=3D=
 [$asp4]\n"
 +
 +msp4=3D"multispaced.local"
 +amsp4=3D"10.0.4.4"
 +resmsp4=3D"name=3D$msp4, length=3D4, addrtype=3D2, aliases=3D[] addr_list=
 =3D[$amsp4]\n"
 +
 +nnl4=3D"nonewline.local"
 +annl4=3D"10.10.10.10"
 +resnnl4=3D"name=3Dnonewline, length=3D4, addrtype=3D2, aliases=3D[$nnl4] a=
 ddr_list=3D[$annl4]\n"
 +
  dir=3D"$(atf_get_srcdir)"
  res=3D"-r ${dir}/resolv.conf"
 =20
 @@ -131,6 +155,56 @@
  	atf_check -o inline:"$loc4" -x "${dir}/h_hostent -f ${dir}/hosts -t file =
 -4 $l4"
  }
 =20
 +atf_test_case hostsbynamelookup4a
 +hostsbynamelookup4a_head()
 +{
 +	atf_set "descr" "Checks /etc/hosts name lookup by alias for AF_INET"
 +}
 +hostsbynamelookup4a_body()
 +{
 +	atf_check -o inline:"$resf4" -x "${dir}/h_hostent -f ${dir}/hosts -t file=
  -4 $f4"
 +}
 +
 +atf_test_case hostsbynamelookup4b
 +hostsbynamelookup4b_head()
 +{
 +	atf_set "descr" "Checks /etc/hosts name lookup with comment for AF_INET"
 +}
 +hostsbynamelookup4b_body()
 +{
 +	atf_check -o inline:"$rescm4" -x "${dir}/h_hostent -f ${dir}/hosts -t fil=
 e -4 $cm4"
 +}
 +
 +atf_test_case hostsbynamelookup4c
 +hostsbynamelookup4c_head()
 +{
 +	atf_set "descr" "Checks /etc/hosts name lookup with space for AF_INET"
 +}
 +hostsbynamelookup4c_body()
 +{
 +	atf_check -o inline:"$ressp4" -x "${dir}/h_hostent -f ${dir}/hosts -t fil=
 e -4 $sp4"
 +}
 +
 +atf_test_case hostsbynamelookup4d
 +hostsbynamelookup4d_head()
 +{
 +	atf_set "descr" "Checks /etc/hosts name lookup with multiple spaces for A=
 F_INET"
 +}
 +hostsbynamelookup4d_body()
 +{
 +	atf_check -o inline:"$resmsp4" -x "${dir}/h_hostent -f ${dir}/hosts -t fi=
 le -4 $msp4"
 +}
 +
 +atf_test_case hostsbynamelookup4e
 +hostsbynamelookup4e_head()
 +{
 +	atf_set "descr" "Checks /etc/hosts name lookup with no newline for AF_INE=
 T"
 +}
 +hostsbynamelookup4e_body()
 +{
 +	atf_check -o inline:"$resnnl4" -x "${dir}/h_hostent -f ${dir}/hosts -t fi=
 le -4 $nnl4"
 +}
 +
  atf_test_case hostsbynamelookup6
  hostsbynamelookup6_head()
  {
 @@ -151,6 +225,56 @@
  	atf_check -o inline:"$loc4" -x "${dir}/h_hostent -f ${dir}/hosts -t file =
 -4 -a $al4"
  }
 =20
 +atf_test_case hostsbyaddrlookup4a
 +hostsbyaddrlookup4a_head()
 +{
 +	atf_set "descr" "Checks /etc/hosts address lookup again for AF_INET"
 +}
 +hostsbyaddrlookup4a_body()
 +{
 +	atf_check -o inline:"$resf4" -x "${dir}/h_hostent -f ${dir}/hosts -t file=
  -4 -a $af4"
 +}
 +
 +atf_test_case hostsbyaddrlookup4b
 +hostsbyaddrlookup4b_head()
 +{
 +	atf_set "descr" "Checks /etc/hosts address lookup with comment for AF_INE=
 T"
 +}
 +hostsbyaddrlookup4b_body()
 +{
 +	atf_check -o inline:"$rescm4" -x "${dir}/h_hostent -f ${dir}/hosts -t fil=
 e -4 -a $acm4"
 +}
 +
 +atf_test_case hostsbyaddrlookup4c
 +hostsbyaddrlookup4c_head()
 +{
 +	atf_set "descr" "Checks /etc/hosts address lookup with space for AF_INET"
 +}
 +hostsbyaddrlookup4c_body()
 +{
 +	atf_check -o inline:"$ressp4" -x "${dir}/h_hostent -f ${dir}/hosts -t fil=
 e -4 -a $asp4"
 +}
 +
 +atf_test_case hostsbyaddrlookup4d
 +hostsbyaddrlookup4d_head()
 +{
 +	atf_set "descr" "Checks /etc/hosts address lookup with multiple spaces fo=
 r AF_INET"
 +}
 +hostsbyaddrlookup4d_body()
 +{
 +	atf_check -o inline:"$resmsp4" -x "${dir}/h_hostent -f ${dir}/hosts -t fi=
 le -4 -a $amsp4"
 +}
 +
 +atf_test_case hostsbyaddrlookup4e
 +hostsbyaddrlookup4e_head()
 +{
 +	atf_set "descr" "Checks /etc/hosts address lookup with no newline for AF_=
 INET"
 +}
 +hostsbyaddrlookup4e_body()
 +{
 +	atf_check -o inline:"$resnnl4" -x "${dir}/h_hostent -f ${dir}/hosts -t fi=
 le -4 -a $annl4"
 +}
 +
  atf_test_case hostsbyaddrlookup6
  hostsbyaddrlookup6_head()
  {
 @@ -229,8 +353,18 @@
  	atf_add_test_case gethostbyaddr6
 =20
  	atf_add_test_case hostsbynamelookup4
 +	atf_add_test_case hostsbynamelookup4a
 +	atf_add_test_case hostsbynamelookup4b
 +	atf_add_test_case hostsbynamelookup4c
 +	atf_add_test_case hostsbynamelookup4d
 +	atf_add_test_case hostsbynamelookup4e
  	atf_add_test_case hostsbynamelookup6
  	atf_add_test_case hostsbyaddrlookup4
 +	atf_add_test_case hostsbyaddrlookup4a
 +	atf_add_test_case hostsbyaddrlookup4b
 +	atf_add_test_case hostsbyaddrlookup4c
 +	atf_add_test_case hostsbyaddrlookup4d
 +	atf_add_test_case hostsbyaddrlookup4e
  	atf_add_test_case hostsbyaddrlookup6
 =20
  	atf_add_test_case dnsbynamelookup4
 Index: tests/lib/libc/net/hosts
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: /cvs/master/m-NetBSD/main/src/tests/lib/libc/net/hosts,v
 retrieving revision 1.1
 diff -u -r1.1 hosts
 --- tests/lib/libc/net/hosts	16 Aug 2013 15:29:45 -0000	1.1
 +++ tests/lib/libc/net/hosts	13 Jun 2014 20:55:14 -0000
 @@ -1,3 +1,5 @@
 +# -*- eval (setq require-final-newline nil) -*-
 +#
  #	$NetBSD: hosts,v 1.1 2013/08/16 15:29:45 christos Exp $
  #
  # Host Database
 @@ -9,3 +11,19 @@
  #
  ::1			localhost localhost. localhost.localdomain.
  127.0.0.1		localhost localhost. localhost.localdomain.
 +
 +# some test hosts...
 +
 +10.0.0.0		network network.localdomain
 +
 +10.0.1.1	foohost.local oldfoohost.local
 +10.0.2.2	commented commented.local		# trailing comment
 +10.0.3.3 spaced.local
 +10.0.4.4  multispaced.local
 +
 +10.255.255.255		broadcast broadcast.localdomain
 +
 +# N.B.: no trailing newline!!!
 +# (non-emacs users do this:  printf %s "$(< hosts)" > t && mv t hosts)
 +# xxx or maybe the test setup should do it....
 +10.10.10.10		nonewline nonewline.local
 \ No newline at end of file
 Index: lib/libc/net/gethnamaddr.c
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: /cvs/master/m-NetBSD/main/src/lib/libc/net/gethnamaddr.c,v
 retrieving revision 1.90
 diff -u -r1.90 gethnamaddr.c
 --- lib/libc/net/gethnamaddr.c	24 Jan 2014 17:26:18 -0000	1.90
 +++ lib/libc/net/gethnamaddr.c	13 Jun 2014 20:28:45 -0000
 @@ -83,8 +83,6 @@
  # define LOG_AUTH 0
  #endif
 =20
 -#define MULTI_PTRS_ARE_ALIASES 1	/* XXX - experimental */
 -
  #include <nsswitch.h>
  #include <stdlib.h>
  #include <string.h>
 @@ -378,7 +376,6 @@
  				had_error++;
  				break;
  			}
 -#if MULTI_PTRS_ARE_ALIASES
  			cp +=3D n;
  			if (cp !=3D erdata)
  				goto no_recovery;
 @@ -395,19 +392,6 @@
  				bp +=3D n;
  			}
  			break;
 -#else
 -			hent->h_name =3D bp;
 -			if (res->options & RES_USE_INET6) {
 -				n =3D strlen(bp) + 1;	/* for the \0 */
 -				if (n >=3D MAXHOSTNAMELEN) {
 -					had_error++;
 -					break;
 -				}
 -				bp +=3D n;
 -				map_v4v6_hostent(hent, &bp, ep);
 -			}
 -			goto success;
 -#endif
  		case T_A:
  		case T_AAAA:
  			if (strcasecmp(hent->h_name, bp) !=3D 0) {
 @@ -738,7 +722,7 @@
  struct hostent *
  gethostent_r(FILE *hf, struct hostent *hent, char *buf, size_t buflen, int=
  *he)
  {
 -	char *p, *name;
 +	char *ln, *p, *name;
  	char *cp, **q;
  	int af, len;
  	size_t llen, anum;
 @@ -753,21 +737,30 @@
  	}
  	setup(aliases, maxaliases);
   again:
 -	if ((p =3D fgetln(hf, &llen)) =3D=3D NULL) {
 +	if ((ln =3D fgetln(hf, &llen)) =3D=3D NULL) {
  		free(aliases);
  		*he =3D HOST_NOT_FOUND;
  		return NULL;
  	}
  	if (llen < 1)
  		goto again;
 -	if (*p =3D=3D '#')
 +	if (*ln =3D=3D '#')
  		goto again;
 +	/* xxx we only really need to alloc and copy IFF no newline */
 +	if (! (p =3D malloc(llen + 1))) {
 +		goto nospc;
 +	}
 +	memcpy(p, ln, llen);
  	p[llen] =3D '\0';
 -	if (!(cp =3D strpbrk(p, "#\n")))
 -		goto again;
 -	*cp =3D '\0';
 -	if (!(cp =3D strpbrk(p, " \t")))
 +	if ((cp =3D strpbrk(p, "#\n")) !=3D NULL) {
 +		/* trim any comment to EOL, or the newline */
 +		*cp =3D '\0';
 +	}
 +	if (!(cp =3D strpbrk(p, " \t"))) {
 +		/* there must be at least two words on a line */
 +		free(p);
  		goto again;
 +	}
  	*cp++ =3D '\0';
  	if (inet_pton(AF_INET6, p, &host_addr) > 0) {
  		af =3D AF_INET6;
 @@ -786,14 +779,18 @@
  		}
  		__res_put_state(res);
  	} else {
 +		free(p);
  		goto again;
  	}
  	/* if this is not something we're looking for, skip it. */
 -	if (hent->h_addrtype !=3D 0 && hent->h_addrtype !=3D af)
 +	if (hent->h_addrtype !=3D 0 && hent->h_addrtype !=3D af) {
 +		free(p);
  		goto again;
 -	if (hent->h_length !=3D 0 && hent->h_length !=3D len)
 +	}
 +	if (hent->h_length !=3D 0 && hent->h_length !=3D len) {
 +		free(p);
  		goto again;
 -
 +	}
  	while (*cp =3D=3D ' ' || *cp =3D=3D '\t')
  		cp++;
  	if ((cp =3D strpbrk(name =3D cp, " \t")) !=3D NULL)
 @@ -823,6 +820,7 @@
  	hent->h_aliases[anum] =3D NULL;
 =20
  	*he =3D NETDB_SUCCESS;
 +	free(p);
  	free(aliases);
  	return hent;
  nospc:

From: Robert Elz <kre@munnari.OZ.AU>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: lib/48881: /etc/hosts file parsing broken (since Aug 2013)
Date: Sat, 14 Jun 2014 06:07:19 +0700

     Date:        Fri, 13 Jun 2014 22:05:00 +0000 (UTC)
     From:        "Greg A. Woods" <woods@planix.ca>
     Message-ID:  <20140613220500.E37EAA6550@mollari.NetBSD.org>

 Apart from your QP encoded patch being totally mangled by gnats,
 the fgetln fixes are probably needed but ...

   |  However the code still doesn't work correctly for the missing final
   |  newline case (i.e. the last entry in a hosts file with no final newline
   |  on that last entry cannot be found by name or by address).

 That should not be "fixed" - unix lines are terminated by newlines, a "line"
 that has no terminating newline is not a line at all, and should be
 ignored in places like that - in particular, one way (aside from using
 brain dead editors) to get such a state, is to write the file back to
 a full filesystem, the file will be truncated at the end of the last free
 available block, almost certainly in the middle of a line - using that broken
 line as if it were valid data would be a mistake.


 kre

From: "Greg A. Woods" <woods@planix.ca>
To: NetBSD GNATS <gnats-bugs@NetBSD.org>
Cc: 
Subject: Re: lib/48881: /etc/hosts file parsing broken (since Aug 2013)
Date: Fri, 13 Jun 2014 20:05:16 -0700

 At Fri, 13 Jun 2014 23:10:01 +0000 (UTC), Robert Elz <kre@munnari.OZ.AU> wr=
 ote:
 Subject: Re: lib/48881: /etc/hosts file parsing broken (since Aug 2013)
 >=20
 >  Apart from your QP encoded patch being totally mangled by gnats,

 Yes, gnats should probably given a helping hand to get it to try to
 catch up with the now decades-old use of MIME.

 >  That should not be "fixed" - unix lines are terminated by newlines, a "l=
 ine"
 >  that has no terminating newline is not a line at all, and should be
 >  ignored in places like that - in particular, one way (aside from using
 >  brain dead editors) to get such a state, is to write the file back to
 >  a full filesystem, the file will be truncated at the end of the last free
 >  available block, almost certainly in the middle of a line - using that b=
 roken
 >  line as if it were valid data would be a mistake.

 I understand what you are saying, and for the most part I agree with
 you, but I think there are worse problems caused by not parsing the text
 after the last newline in files that don't end in a newline.

 ed and vi will both quietly open such files and show that last "line"
 and also happily quit without asking to save the file (though they will
 also both silently add a final newline if any part of the file is
 changed and it is saved).  (I think maybe they should both warn that the
 file was read without a final newline and ask to save the file on quit
 even if no changes were made by the user.)

 less, more, grep, awk, and probably most other tools one might use to
 examine text files will all happily read the text after the final
 newline and parse or show it as a true "line" of text in the file.

 About the only way a more naive admin will discover a problem with a
 missing final newline is to hexdump the file, or maybe they might cat or
 tail the file and notice the next shell prompt doesn't appear at the
 beginning of the line after the end of the file's contents.

 --=20
 						Greg A. Woods
 						Planix, Inc.

 <woods@planix.com>       +1 250 762-7675        http://www.planix.com/

From: David Holland <dholland-bugs@netbsd.org>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: lib/48881: /etc/hosts file parsing broken (since Aug 2013)
Date: Wed, 18 Jun 2014 03:13:16 +0000

 On Sat, Jun 14, 2014 at 03:10:05AM +0000, Greg A. Woods wrote:
  >>  That should not be "fixed" - unix lines are terminated by
  >>  newlines, a "line" that has no terminating newline is not a line
  >>  at all, and should be ignored in places like that - in
  >>  particular, one way (aside from using brain dead editors) to get
  >>  such a state, is to write the file back to a full filesystem, the
  >>  file will be truncated at the end of the last free available
  >>  block, almost certainly in the middle of a line - using that
  >>  broken line as if it were valid data would be a mistake.
  >  
  >  I understand what you are saying, and for the most part I agree with
  >  you, but I think there are worse problems caused by not parsing the text
  >  after the last newline in files that don't end in a newline.
  > [...]

 I mostly don't agree: a partial line should either be a line or a
 syntax error, and in either case ignoring it silently is wrong :-)

 -- 
 David A. Holland
 dholland@netbsd.org

>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.