[Date Prev][Date Next][Thread Prev][Thread Next]
- Subject: Re: "*toclose" vs. sandboxes / embedded environments
- From: Andrew Gierth <andrew@...>
- Date: Tue, 18 Dec 2018 23:27:21 +0000
>>>>> "Roberto" == Roberto Ierusalimschy <email@example.com> writes:
>> Right now, if spi.execute gets an error generated by PG, what happens is
>> that it stores the relevant details in a userdata, throws that as a Lua
>> error, lets it propagate out to the lua_pcall that was used to call the
>> function, and then raises it as a PG error again. There could be several
>> levels of this - for example, the SQL query might contain a call to
>> another Lua function. (It doesn't matter if the error gets replaced with
>> a different error along the way, for example if we get an out-of-memory
>> when trying to copy error data, as long as it continues to propagate as
>> an error and as long as we're not executing arbitrary Lua code.)
>> I can be sure this is safe because the Lua code can't interfere with the
>> error process except by calling pcall()/xpcall(), which I already
>> replaced with my own versions.
Roberto> In your current implementation, what happens if there is a PG
Roberto> error inside a coroutine? The error handler in that case is
Roberto> not pcall/xpcall, but resume.
I intercept that too.
Roberto> I must say that this whole process of changing pcall/xcall
Roberto> seems somewhat smelly.
Maybe so, but the primary reason I took on the project at all was that
the previous version had half a dozen unfixable crash bugs caused by
playing fast and loose with the interaction between Lua and PG.
Accordingly, in my version I have tried to be as strict as possible
about the correctness of all interactions with the PG code.
(There actually is a simpler way to do the whole business of embedding a
new language into Postgres: it's the method that's used for perl, tcl
and python. That approach is to force every database interaction to be
wrapped in a subtransaction whether the caller wants to or not, so that
all errors can be cleaned up before returning to the user code. The
overhead involved is noticable, and it also means that all data values
must be converted into strings or other data types of the embedded
language. I wanted to try for better integration - exposing things like
PG's "numeric" arithmetic and json serialization/deserialization to Lua
code, not converting PG records and arrays to Lua tables and back except
when needed, and so on. The fact that Lua code couldn't catch errors
except via functions which the environment could control seemed to make
this approach possible.)