88 posts
Location
UK
Posted 30 December 2012 - 11:15 PM
At the moment, in bios.lua, the string metatable is hidden like this:
local nativegetmetatable = getmetatable
local nativetype = type
local nativeerror = error
function getmetatable( _t )
if nativetype( _t ) == "string" then
nativeerror( "Attempt to access string metatable", 2 )
return nil
end
return nativegetmetatable( _t )
end
This is a bad way to approach the problem - in normal lua, the contract of `getmetatable` is to never error. For instance, I might want to check if a value has a metatable, without wanting to do anything to it.
Lua provides a builtin way to protect metatables -
the `__metatable` metafield:
getmetatable("").__metatable = "The string metatable is protected"
print(getmetatable("")) -- The string metatable is protected
302 posts
Posted 30 December 2012 - 11:24 PM
They know about the __metatable field in general, beats me why the __metatable field isn't used for protecting the string metatable.
88 posts
Location
UK
Posted 31 December 2012 - 12:34 AM
Thinking some more, it would be more useful to actually expose the string metatable in a readonly manner, by:
- Making a copy of the metatable. This has the advantage of being iterable, but the disadvantage of silently failing when the metatable is modified.
local stringmt = getmetatable("")
local clonedmt = {}
stringmt.__metatable = clonedmt
for k, v in pairs(stringmt) do
clonedmt[k] = v
end
Proxying access, firing an error on modification. Yes, rawset can be used, but that won't actually modify the real metatable. This has the disadvantage of making the table non-iterable, but the advantage of failing loudly.
local stringmt = getmetatable("")
stringmt.__metatable = setmetatable({}, {
-- the `__index = stringmt` shorthand is unsuitable here
__index = function(_, k)
return stringmt[k]
end,
__newindex = function(_, k, v)
nativeerror("The string metatable cannot be changed")
end
})
997 posts
Location
Wellington, New Zealand
Posted 31 December 2012 - 02:25 AM
The string metatable is shared between computers. I can't see your code on my phone, so I don't know if that affects it.
88 posts
Location
UK
Posted 02 January 2013 - 03:52 AM
The string metatable is shared between computers.
Wait, really? Is that the only thing shared between computers/
997 posts
Location
Wellington, New Zealand
Posted 02 January 2013 - 01:57 PM
The string metatable is shared between computers.
Wait, really? Is that the only thing shared between computers/
I think so. It's a static field in LuaJ so there's no easy way for CC to unshare it.
108 posts
Posted 07 January 2013 - 09:48 PM
I don't see a reason to prevent getting the string metatable, it's not like the value can be changed outside of java
2447 posts
Posted 08 January 2013 - 12:25 AM
Except it can.
997 posts
Location
Wellington, New Zealand
Posted 08 January 2013 - 12:48 AM
I don't see a reason to prevent getting the string metatable, it's not like the value can be changed outside of java
getmetatable("").__index.sub = os.reboot
That would reboot something whenever someone does aStringVariable:sub(…)
Not sure if it'll reboot the computer that put it in the metatable or the one running the sub command.
88 posts
Location
UK
Posted 08 January 2013 - 07:45 AM
Except it can.
Not if you get it in a readonly way, like the two ways I suggested.
getmetatable("").__index.sub = os.reboot
That would reboot something whenever someone does aStringVariable:sub(…)
Not sure if it'll reboot the computer that put it in the metatable or the one running the sub command.
That particular example is no worse than `string.sub = os.reboot`, which is currently allowed - worse yet, all the bios code uses `string.func(s, …)` not `s:func(…)`, so this breaks things at a deeper level.
The case which would really break things is `getmetatable("").__concat = os.reboot`
Again, none of these are problems if the metatable is readonly (instead of inaccesible)
2447 posts
Posted 08 January 2013 - 08:17 AM
Why is that example no worse? One propagates to all computers - the other stays on one computer.
88 posts
Location
UK
Posted 08 January 2013 - 08:22 AM
Why is that example no worse? One propagates to all computers - the other stays on one computer.
Whoops, forgot about the "The string metatable is shared between computers." bit
108 posts
Posted 08 January 2013 - 02:47 PM
Ok, so I was being stupid and assumed that sense there was no setmetatable method, the metatable couldn't be changed
997 posts
Location
Wellington, New Zealand
Posted 08 January 2013 - 08:51 PM
The case which would really break things is `getmetatable("").__concat = os.reboot`
IIRC all string operations are built-in except for indexing, and don't go through the metatable.