I pretty much remember that we had to modify bind_params() and use, within the loop, $params[$key] everywhere instead of $value, because of some similar reason (a copy happens there). And that was enough under PHP5, the returned array was a different one (by value), but the array elements/values were ok (same instance, by reference).
Maybe it was a PHP5 bug (or maybe it's a bug/new feature in PHP7, if you ask me that's my personal opinion), but it was enough in the past, who knows why it's not now..
Anyway, really good catch, that way for sure we ensure both params and descriptors are always by ref and done. Same for the missing descriptor->close() call, that must be called always after writeTemporary(). Luckily, all the uses of descriptors we have in the driver are for such calls.
About the NULL/empty string I'm not 100% sure which was the problem, maybe it's https://bugs.php.net/bug.php?id=72524 (only affects PHP7), in fact, I'm not 100% sold to this change as far as this changes data in a way it would not survive calling oracle_dirty_hack() twice and this may happen: NULL => 'empty string' => '1-whitespace string'. Surely I'd perform the conversion within bind_params() instead, I mean, as later as possible, and possibly with a call to that php issue so we can restitute NULLs once it's fixed (or at least have a reference to it).
About ADOdb's changes, they look ok. My only comment is that, at some point, I think we should kill ADOdb completely, or at very least, provide the possibility of using our own drivers there in auth and enrol database plugins.
Said that, I'm really a bit worried because some of the changes above are needed because a sudden change / ongoing bugs in php/oci behavior and that makes me feel that we'll be finding more (still hidden) obstacles in the road.
I'm going to propose a extra commit with some of the points commented above, mainly clarifications, and let's discuss about them.