This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
tenshae's profile picture

Read-Only Tables?

Started by tenshae, 16 September 2014 - 02:05 AM
tenshae #1
Posted 16 September 2014 - 04:05 AM
I've seen a few examples of this that are either dated or just completely untested and absolutely none that I've seen even work a bit (at least with this version of CC). I was wondering, and yes I have searched on google, how you would do read-only tables in Lua.
I want to guard the OS and FS apis from userspace code, so that they can't modify it and break some things/break out of the sandbox. Could anyone help?
KingofGamesYami #2
Posted 16 September 2014 - 04:21 AM
You'll want to look at metatables for this. Here's a tutorial on how to use metatables.
natedogith1 #3
Posted 16 September 2014 - 04:22 AM

function readOnly(tbl)
  return setmetatable({}, __index = tbl, __newindex =
	function(self,key,value)
	  error("not modifyable")
	end,__metatable={})
end
'__index' defines where/how to look up values
'__newindex' defines where/how to set values
'__metatable' prevents me from using getmetatable and modifying it that way
if you're interested in more about metatables, you might like to look at http://www.lua.org/m...manual.html#2.8

There are a few issues with this though, like the fact that 'pairs' doesn't work, though it does do a better job of read-only than the CC's OS
tenshae #4
Posted 16 September 2014 - 04:34 AM
–snippeth–
I guess I should try to override setmetatable so that people can't "unreadonly-ize" the tables, right?
Is there anything else I should watch out for?
natedogith1 #5
Posted 16 September 2014 - 04:46 AM
–snippeth–
I guess I should try to override setmetatable so that people can't "unreadonly-ize" the tables, right?
Is there anything else I should watch out for?
Actually, since the metatable has a '__metatable' field, setmetatable will throw an error; however you should maybe watch out for 'rawset'.
TsarN #6
Posted 24 January 2015 - 08:55 PM
If you want to also block rawset here the code to put into "startup" (I'm using this in UberOS):

local absoluteReadOnly = {}
function applyreadonly(table)
  local tmp = {}
  setmetatable(tmp, {
	__index = table,
	__newindex = function(table, key, value)
	  error("Attempt to modify read-only table")
	end,
	__metatable = false
  })
  absoluteReadOnly[#absoluteReadOnly + 1] = tmp
  return tmp
end
local oldrawset = rawset
rawset = function(table, index, value)
  for i = 1, #absoluteReadOnly do
	if (table == absoluteReadOnly[i]) or (index == absoluteReadOnly[i]) then
	  error("Attempt to modify read-only table")
	  return
	end
  end
  oldrawset(table, index, value)
end

Then, to make table "a" read-only, do the following:
a = applyreadonly(a)
Edited on 26 January 2015 - 04:35 AM