Subject: standards/2487: "" is considered a valid file name
To: None <gnats-bugs@NetBSD.ORG>
From: None <cgd@cs.cmu.edu>
List: netbsd-bugs
Date: 05/30/1996 16:11:21
>Number:         2487
>Category:       standards
>Synopsis:       "" is considered a valid file name.  POSIX disagrees.
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    gnats-admin (GNATS administrator)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu May 30 16:35:01 1996
>Last-Modified:
>Originator:     Chris G. Demetriou
>Organization:
Kernel Hackers 'r' Us
>Release:        1.2_ALPHA
>Environment:
System: NetBSD bunnahabhain.pdl.cs.cmu.edu 1.2_ALPHA NetBSD 1.2_ALPHA (BUNNY) #48: Thu May 30 12:07:36 EDT 1996 cgd@bunnahabhain.pdl.cs.cmu.edu:/usr/src/sys/arch/alpha/compile/BUNNY alpha

>Description:
	"" is considered a valid file name, e.g. stat("", &buf) works.

	POSIX (.1b-1993) explicitly states (Page 27, line 662 of Section 2):

		A null pathname is invalid.

	Now, it doesn't explicitly say what a "null pathname" is, but it does
	say that a pathname is:

		A string that is used to identify a file.

	(p. 18, line 316 of Section 2), that to determine what a "null string"
	is one should see the definition of "empty string" (p. 17, line 285 of
	Section 2), and there one finds:

		2.2.2.31 empty string [null string]: A character array whose
		first element is the null character.

	(p. 14, lines 174-175 of Section 2).

	Therefore, it would seem that "" should be disallowed as a pathname
	for stat() and other POSIX-specified system calls, if not all
	system calls that specify file names.

	Additionally, POSIX (same rev) says that ENOENT should be used
	as the error indicating a null pathname.

>How-To-Repeat:

	#include <sys/stat.h>
	#include <errno.h>

	main()
	{
		struct stat sb;

		printf("stat ret %d (%d)\n", stat("", &sb), errno);
		printf("dev = 0x%x\n", sb.st_dev);
		printf("ino = %d\n", sb.st_ino);
	}

	Note that the stat() succeeds.

>Fix:
	My fix is to namei(), and disallows empty pathnames wherever
	namei() is used.  It's not 100% clear that this is "the right
	thing" to be doing, so i'm submitting it as a PR.

	I'm really not sure how one could easily do this on a
	syscall-by-syscall basis except by adding a new namei flag,
	which feels like the wrong thing to do.

Index: vfs_lookup.c
===================================================================
RCS file: /a/cvsroot/src/sys/kern/vfs_lookup.c,v
retrieving revision 1.17
diff -c -r1.17 vfs_lookup.c
*** vfs_lookup.c	1996/02/09 19:00:59	1.17
--- vfs_lookup.c	1996/05/30 16:19:15
***************
*** 111,117 ****
  	else
  		error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf,
  			    MAXPATHLEN, &ndp->ni_pathlen);
! 	if (error) {
  		free(cnp->cn_pnbuf, M_NAMEI);
  		ndp->ni_vp = NULL;
  		return (error);
--- 111,124 ----
  	else
  		error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf,
  			    MAXPATHLEN, &ndp->ni_pathlen);
! 	/*
! 	 * If there was an error copying the file name, time to give up.
! 	 * Also, POSIX specifies that empty pathnames are invalid and
! 	 * attempts to use them should yield ENOENT.
! 	 */
! 	if (error || ndp->ni_pathlen == 1) {
! 		if (!error && ndp->ni_pathlen == 1)
! 			error = ENOENT;
  		free(cnp->cn_pnbuf, M_NAMEI);
  		ndp->ni_vp = NULL;
  		return (error);
>Audit-Trail:
>Unformatted: