Hi all,

I'm using the nssqlite3 driver for my latest experiment and found a serious limitation in it: you cannot execute a select statement that returns no rows. (at least not with select or 0or1row; you could probably hack it with exec but that would be annoying and is supposed to be unnecessary)

The problem is straightforward - the driver checks how many rows are returned after executing a statement; 0 returns NS_DML and >0 returns NS_ROWS. 'ns_db select' and '0or1row' expect NS_ROWS results, even if there are no rows to be read (which is a perfectly valid result).

So how to fix it? There's no direct way to tell what kind of statement was parsed in the sqlite api (unlike say, OCI) and checking how many rows were changed will give bad results for an update affecting no rows. The dumb thing to do would be to compare the start of the passed sql with "select" to determine if it is a select or dml statement. But there may be a cleverer way!

sqlite allows you to set up an authorization callback that is called when parsing the sql. Among other things this callback can allow or deny operations like select, insert, delete, drop, and so forth. That makes it easy, just create an authorizer to allow select (and read) and deny everything else, and use that for select operations only, and for dml or exec leave the authorizer null to allow everything. The nsdb driver allows for a different selectProc and execProc, so this should be straightforward.

Fortunately I read the code before implementing this, for had I not I would surely have slammed my head into the wall several times trying to figure out what was going wrong. nsdb does allow you to register a different selectProc and execProc, and one would think that a select operation would use the more specific function if it was available, and fall back to the generic one if not. One would be mistaken; if an execProc is registered it will be used and the selectProc is only used when there is no execProc. Not only is this backward IMHO, it thwarts a potentially useful protection against sql-injection attacks - if the select method really only let the database execute select statements then adding in a drop table or other nastiness would be ineffectual.

However, even if this protection wasn't thwarted at the nsdb level, the database-specific drivers that exist are no help. As far as I can tell, even when a separate selectProc is provided is it just a wrapper around execProc, meaning they all execute whatever sql is passed in and only use the different initial call to check what is returned and raise an error if it is wrong. I gather that these different interfaces were not intended as a security measure, but as a programmer convenience.

So after all this I guess I'll shortly be writing a patch for this driver which checks if the statement begins with "select" and forces it to return NS_ROWS for that case. To whom should I send it? (Or Dossy could grant me cvs access.)

And then there's nsdb - I think the more specific selectProc should be tried first for select operations, but since it's been this way for a while, would changing this break some other drivers (where the selectProc has never been called, or tested)? The postgres driver is at least aware of this judging by a comment that the select function is never called by the server, but how would the other drivers fare?

-J


--
AOLserver - http://www.aolserver.com/

To Remove yourself from this list, simply send an email to <[EMAIL PROTECTED]> 
with the
body of "SIGNOFF AOLSERVER" in the email message. You can leave the Subject: 
field of your email blank.

Reply via email to