Pitfalls of F$LOCATE and other Functions

Code that is almost correct is pernicious, and I often encounter it in the course of my consulting practice. While working on a client problem the other day, I encountered just such an example, an almost correct use of F$LOCATE to determine if a process holds a particular privilege or identifier. The fault is not in F$LOCATE, it is in the way that F$LOCATE (or any other index function) is used.

In this case, I found the error in the released version of a major non-HP product used on OpenVMS. This same product contained both this coding error and an interoperabilty problem with its management of the LNM$FILE_DEV logical name (I will cover the LNM$FILE_DEV problem in a future column).

This column will talk about the first of the two errors, the frequent incorrect coding of the F$LOCATE lexical function. This error falls into the species of “code that often works most of the time”. As such, its failures seem unpredictable and irregular. The consequences of the failures also seem erratic and unpredictable. The supreme irony is that the difference between the correct and incorrect code is less than ten (10) characters.

Consider the following test case:

$ X = "USER_PAY"
$ Y = "REMOTE,DIALUP,KUMQUAT,USER_PAYROLL"
$ IF F$LOCATE(X, Y) .NE. F$LENGTH(Y) THEN -
        WRITE SYS$OUTPUT "User has USER_PAYROLL permission"

Running the above sample clearly shows something is wrong. The user does not have the USER_PAY identifier, yet the code “found” it. What is the pathology of the failure?

The pathology of the failure is the matching of a partial element, not a complete element. The code author omitted wrapping the two strings in delimiter characters (in this case “,”). The correction consists of wrapping the strings in delimiter characters to anchor the F$LOCATE at beginning and end, ensuring that if and when a match occurs, it is to a complete element.

The correct code for the preceding would be:

$ X = "USER_PAY"
$ Y = "REMOTE,DIALUP,KUMQUAT,USER_PAYROLL"
$ IF F$LOCATE(",''X',", ",''Y',") .NE. F$LENGTH(",''Y',") THEN -
        WRITE SYS$OUTPUT "User has USER_PAYROLL permission"

If one carefully analyzes the cases, the failures occur in at least two different situations:

Often, these problems appear in code which checks the rights or privilege lists returned by the F$GETJPI lexical function. However, the coding error can manifest itself in a wide range of situations, particularly when validating inputs.

In general, this is an example of what can happen when implementation and design are not as thorough as they can be. The size of your organization is irrelevant; in the end analysis, code is written by humans, and will contain errors. It is our responsibility as IT professionals to keep a watchful eye for errors, whether they affect us immediately or in the future. Today's minor error could be a show-stopper tomorrow.

URLs for referencing this entry

Picture of Robert Gezelter, CDP
RSS Feed Icon RSS Feed Icon
Add to Technorati Favorites
Follow us on Twitter
Bringing Details into Focus, Focused Innovation, Focused Solutions
Robert Gezelter Software Consultant Logo
http://www.rlgsc.com
+1 (718) 463 1079