microsoft / ODBC-Specification

Microsoft ODBC Specification
Other
121 stars 40 forks source link

Caching nested statement state optional? #84

Closed matthew-wozniczka closed 7 years ago

matthew-wozniczka commented 7 years ago

I see a possible security concern with the fact that (unless explicitly closed), nested statement handles maintain their descriptors across parent statement rows.

Consider an application doing a recursive traversal of a document. If it's written such that it keeps no state between rows, then, to be safe, it would need to explicitly unbind/rebind the columns (as the old bindings are probably just waiting to corrupt your heap), and re-set all deferred pointer attributes (like SQL_ATTR_ROWS_FETCHED_PTR) since they are probably not pointing anywhere useful.

If it misses something, undefined behaviour.

I think it would make sense for there to be a statement property which controlled whether the driver kept state information for nested handles across calls to SQLGetNestedHandle (At the very least, it would set all those pointer attributes to their defaults). A 'naive' application could keep it disabled (IMO the default), and not worry about it. A more advanced application that wanted to optimize retrieval could enable it so that it could avoid rebinding (but it would pay a cost in complexity).

mikepizzo commented 7 years ago

I would rather not add too many different "behaviors" as I think it makes things more confusing for everyone.

I would think the common case (except for variants) would be that the same child handle would be used across parents. We have addressed the variant case in #85 by creating a new handle each time for variants. Equivalent "safe" code would be for the application would be to simply allocate and set a fresh descriptor each time it called GetNestedHandle. We could also add a "ResetDescriptor" (statement attribute?) to explicitly reset it to this state.

This is certainly something we can revisit as we start writing applications against real implementations and see what patterns work best. For an entirely random NoSQL document not copying the descriptor probably makes sense, but for any structured result (which is most of them) copying is probably usually the right behavior (although I get that you might want to put child values in different locations for each parent, I would expect that either to be a matter simply of changing the offset pointer or rebinding each row).

mikepizzo commented 7 years ago

Note: we do say that the statement handle is not re-used if it is explicitly freed by the application.

So, in the above scenario, if the application explicitly frees the statement then it should be fine.