Tuesday, January 17, 2006

Scripting: VBScript and function calls

I noticed some weirdness with some of the data being placed in SQL Server for the mass mailing list. If data entered through a web form contained an apostrophe (such as O'Brien) then the records in the database would duplicate the number of apostrophes on each insert after the initial one (O''Brien, O''''Brien, etc.).

Immediately I supsected that this had to do with the SQLEncode() function provided by Microsoft in the iasutil.asp file. I was correct, and the problem was beginning to look supsiciously familiar (I'm pretty sure I've seen it before, though I'm not sure I actually took the time to resolve the problem). I took a quick glance at the function to see if I could determine the source of the problem.

Basically the problem boils down to the way that VBScript handles the passing of variables to functions. Some languages allow passing of variables by value (byval) or by reference (byref). VBScript has this functionality, but by default passes variable byref. In effect this means that any modification of the function variable will also modify the original one passed to the function.

For example, take the following code:
Dim intGlobalVar
intGlobalVar = 1
Function addOneToNum (intFuncArg)
intFuncArg = intFuncArg + 1
addOneToNum = intFuncArg
End Function
Response.Write(intGlobalVar)
Response.Write(addOneToNum(intGlobalVar))
Response.Write(intGlobalVar)

The first Response.Write() prints out "1". The second Response.Write() prints out "2". While you might expect the third Response.Write() to print out "1" it in fact prints out "2" because intGlobalVar was passed byref to the function and then modified.

There are two methods of solving this particular problem
  1. Specify byval in the function argument list
  2. Reassign function arguments to variables local to the function
I updated the SQLEncode() function so that the arguments are passed byval. I also updated the variables so that they have more uniqueness (to avoid possible confusion).

(Note: In JavaScript simple types are passed by value while complex types are passed by reference. There is no way to modify this behavior ... though I have seen indications that a future version will have this capability.)

References: