Subject: bin/32799: Apparent off-by-one error in locate(1) causes incorrect behaviour when entries with the maximum path length are encountered
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: None <dhgutteridge@sympatico.ca>
List: netbsd-bugs
Date: 02/12/2006 00:15:00
>Number:         32799
>Category:       bin
>Synopsis:       Apparent off-by-one error in locate(1) causes incorrect behaviour when entries with the maximum path length are encountered
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Feb 12 00:15:00 +0000 2006
>Originator:     David H. Gutteridge
>Release:        3.0 mostly
>Organization:
>Environment:
>Description:
When locate(1) encounters a path entry in the database that has the maximum number of characters allowed, it terminates with a spurious error message: "invalid data in database file".  This is because some error-checking code in locate.c has an off-by-one error in it.  (It's necessary to leave one byte available in the string for the NUL terminator after the block in question exits, but not two.)
>How-To-Repeat:
Here's my (trival) test script to create such a path in the file system:

#!/bin/sh

mkdir -p /home/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/disciple/dis
 ciple/disciple/disciple/disciple/disciple1

>Fix:
--- locate.c~	2006-02-11 16:31:54.000000000 +0000
+++ locate.c	2006-02-11 18:23:46.000000000 +0000
@@ -206,7 +206,7 @@
 		/* overlay old path */
 		for (p = path + count; (c = getc(fp)) > SWITCH;) {
 			/* sanity check */
-			if (p < path || p >= path + sizeof(path) - 2)
+			if (p < path || p >= path + sizeof(path) - 1)
 				return -1;	/* invalid database file */
 			if (c < PARITY)
 				*p++ = c;