lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


> Say you have defined: function func(userid, publicdata, privatedata).
> And you call: func(userid, getpublicdata(userid), getprivatedata(userid))
> There is NO warranty at all that fun() will process publicdata containing ONLY the return value(s) of getpublicdata().
> It could happen that publicdata used by fun() will return what was returned by getprivatedata(), and that privatedata would be nil in that case.
> This would happen if getpublicdata() for example checks if userid is declared visible in some database, and if not (concealed user), it would return nothing (assuming it is equivalent to returning nil). But that userid would still have privatedata, that would suddenly be made accessible inside fun() as if it was public.

I don't think this is the case, as the second parameter will always be
`nil` if the function returns `nil` or doesn't return anything. Here
is my test:

function getpublicdata() end
function getprivatedata() return "private" end
function func(...) print(...) end
func(123, getpublicdata(userid), getprivatedata(userid))

This prints: "123 nil private" for me in Lua 5.1-5.4

> So instead of calling:  func(userid, getpublicdata(userid), getprivatedata(userid))
> You need to call:  func(userid, (getpublicdata(userid)), (getprivatedata(userid)))

No, this only makes a difference for the last parameter, so you can do
it for the last call to avoid sending *more* parameters than necessary
(for example, when string.gsub is used, but you only need the first
value returned). You *may* need it for the last parameter if you want
to guarantee that the function will see 3 parameters instead of 2
(when `getprivatedata()` doesn't return anything), but if you assign
those values to local variables, you won't see any difference.

Paul.

On Mon, Sep 6, 2021 at 12:18 PM Philippe Verdy <verdyp@gmail.com> wrote:
>
> I think that this is a problem of Lua not clearly handling list of return values, but it could be even worse and seen as a security issue.
>
> Say you have defined: function func(userid, publicdata, privatedata).
> And you call: func(userid, getpublicdata(userid), getprivatedata(userid))
> There is NO warranty at all that fun() will process publicdata containing ONLY the return value(s) of getpublicdata().
>
> It could happen that publicdata used by fun() will return what was returned by getprivatedata(), and that privatedata would be nil in that case.
> This would happen if getpublicdata() for example checks if userid is declared visible in some database, and if not (concealed user), it would return nothing (assuming it is equivalent to returning nil). But that userid would still have privatedata, that would suddenly be made accessible inside fun() as if it was public.
>
> So instead of calling:  func(userid, getpublicdata(userid), getprivatedata(userid))
> You need to call:  func(userid, (getpublicdata(userid)), (getprivatedata(userid)))
> So that there's an isolation provided by the extra parentheses, apparently superfluous:
> Having to use these extra parentheses everywhere is really a very bad trick that programs should never depend on!
>
> And anyway I still do not see any reason for the type(value) builtin function to generate an error instead of returning "nil" when its argument list is empty, given that it just has to process the single argument arg[1] and ignores arg[2] or everything else, independantly of the effective length of the argument list computed and passed by the caller.
>
> Checking if parameters are properly bound is something impossible to check if you have declared the function with named parameters (which are in fact declaring local variables initialized with arg[1], arg[2], etc. in the order of the declaration, where "arg" is the implicitly declared local variable added in every function and pointing to its argument list (accessible like a table indexed by integers, but still not necessarily a sequence).
>
>
>
>
>
>
>
>
>
>
>
> Le lun. 6 sept. 2021 à 19:53, Paul K <paul@zerobrane.com> a écrit :
>>
>> > The problem is that `('A':byte(2)` actually does not return `nil` in its list of upvalues, it just returns an empty list:
>>
>> You can wrap it into parentheses to force `nil` if that's what's
>> needed in this case:
>>
>> print(type( ( ('A'):byte(2) ) ))
>>
>> This prints "nil" for me in all Lua versions 5.1+
>>
>> Paul.
>>
>> On Mon, Sep 6, 2021 at 9:19 AM Philippe Verdy <verdyp@gmail.com> wrote:
>> >
>> > The Lua builtin function "type(value)" unexpectedly signals an error (sometimes but not always) when the argument value is nil.
>> >
>> > This occurs when the value nil is the result of a function call, and not a simple variable containing nil or the constant nil. This is incoherent !
>> >
>> > That error is wrong. `type(nil)` or `type()` or `type(f())` (where `f()` returns nil or nothing), or `type(nil, 'dummy')` or `type(...)` (called from inside a function called without parameters or with a nil parameter in first position of the varaible argument list) should return 'nil' in all cases.
>> >
>> > E.g. run in a Lua console:
>> >
>> > val = ('A'):byte(1); typ = type(val); print typ ..'=' ..  tostring(val); print type(('A'):byte(1))
>> > --> number=65
>> > --> number
>> > val = ('A'):byte(2); typ = type(val); print typ .. '=' .. tostring(val); print type(('A'):byte(2))
>> > --> nil=nil
>> > --> Error: bad argument #1 to 'type' (value expected).
>> >
>> > The problem is that `('A':byte(2)` actually does not return `nil` in its list of upvalues, it just returns an empty list:
>> > * when assigning an empty list to a variable, that variables get `nil` (with the correct type).
>> > * when passing the empty list returned by a function to `type()`, this function gets no parameter and incorrectly signals an "error".
>> >
>> > Yes the builtin `type(value)` function "requires" at least one argument, but that argument in first position CAN be `nil`. So it may not be passed at all and the first argument should be initialized with the `nil` value, and the builtin `type(value)` function SHOULD return the string `"nil"`, without any error (which I think is a very legacy behavior of very old versions of Lua before major changes in how lists of values were passed and returned through function calls).
>> >
>> > And the builtin `string.byte(index)` function SHOULD also be fixed to return a true `nil` for a given index past the end of string, and not an empty list (or this should not make any difference for calling type()).
>> >
>> >