Subject: lib/24604: libform 'enum match' performs wrong matches
To: None <gnats-bugs@gnats.NetBSD.org>
From: Peter Postma <peter@pointless.nl>
List: netbsd-bugs
Date: 02/29/2004 16:20:28
>Number:         24604
>Category:       lib
>Synopsis:       libform 'enum match' performs wrong matches
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Feb 29 15:21:01 UTC 2004
>Closed-Date:
>Last-Modified:
>Originator:     Peter Postma
>Release:        NetBSD 1.6ZK
>Organization:
>Environment:
System: NetBSD mercury.pointless.nl 1.6ZK NetBSD 1.6ZK (mercury) #25: Mon Feb 23 15:42:28 CET 2004 root@mercury.pointless.nl:/usr/obj/sys/arch/sparc64/compile/mercury sparc64
Architecture: sparc64
Machine: sparc64
>Description:
There is a problem in libform's match_enum().
The function performs matches with wrong length.
Best to explain this is by showing libform debug output:

> next_enum: attempt to match 'maildrop'
> match_enum: start 0, blen 8

We are trying to match the string 'maildrop', it's length is 8.
The debug output for each check is as follows:

> match_enum: checking choice 'users'
> match_enum: enum_start 0, elen 5
> match_enum: curmatch is FALSE

We are checking 'users' against 'maildrop'.
The following code does the match check:

> strncasecmp(&choices[i][enum_start], &this[start], elen)

It is using 'elen' to indicate which length should be checked.
This is wrong, look what happens when we check 'mail' against 'maildrop':

> match_enum: checking choice 'mail'
> match_enum: enum_start 0, elen 4
> match_enum: curmatch is TRUE

The match is valid because only the first four characters are being
checked.

>How-To-Repeat:
Problem was noticed with sushi(8).
Start sushi, System Maintenance -> Edit usermgmt.conf.
The list group should be selected.
Press <tab> for a few times.
The list selection will change but after the group 'maildrop' it falls back
to 'bin', this is the first group after 'mail'.
So it is obvious that match_enum() also matches 'mail' when only 'maildrop'
should be matched.

>Fix:
We should use strcmp/strcasecmp to perform exact matches.

Index: type_enum.c
===================================================================
RCS file: /cvsroot/src/lib/libform/type_enum.c,v
retrieving revision 1.7
diff -u -r1.7 type_enum.c
--- type_enum.c 9 Mar 2003 00:57:19 -0000       1.7
+++ type_enum.c 29 Feb 2004 14:59:52 -0000
@@ -157,12 +157,12 @@
                        continue;

                if (ignore_case)
-                       cur_match = (strncasecmp(&choices[i][enum_start],
-                                                &this[start], elen) == 0) ?
+                       cur_match = (strcasecmp(&choices[i][enum_start],
+                                               &this[start]) == 0) ?
                                TRUE : FALSE;
                else
-                       cur_match = (strncmp(&choices[i][enum_start],
-                                            &this[start], elen) == 0) ?
+                       cur_match = (strcmp(&choices[i][enum_start],
+                                           &this[start]) == 0) ?
                                TRUE : FALSE;

 #ifdef DEBUG

>Release-Note:
>Audit-Trail:
>Unformatted: