[SOLVED] Is it possible to have a config file next to executable?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
ivan
Party member
Posts: 1915
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: [SOLVED] Is it possible to have a config file next to executable?

Post by ivan »

A malicious user could place some kind of DoS code in there though. Like, an endless loop or some kind of memory exhausting code, but other than that, it's pretty secure.
Lua has a built-in memory limit so theoretically there is no risk to the user's machine.
But yes, to prevent your game from ever crashing you could monitor the memory and timeout the untrusted script.
Not really a concern unless people are actively trying to hack your save files.
KayleMaster
Party member
Posts: 234
Joined: Mon Aug 29, 2016 8:51 am

Re: [SOLVED] Is it possible to have a config file next to executable?

Post by KayleMaster »

Will that set config.option1 = 42 ?
Or the global option1 to 42?
grump
Party member
Posts: 947
Joined: Sat Jul 22, 2017 7:43 pm

Re: [SOLVED] Is it possible to have a config file next to executable?

Post by grump »

KayleMaster wrote: Fri Jun 22, 2018 11:20 am Will that set config.option1 = 42 ?
Or the global option1 to 42?
It will set config.option1 = 42.

setfenv sets the global enviroment of the given function to the table you provide. This is what makes this approach secure:

1. Anything you have defined in your game is hidden from the code in the configuration file. That prevents it from altering anything in your main code.
2. There are no functions available in the config file, you can only use basic language features. No require, loadlib, setmetatable, etc. possible. You can selectively put functions/tables in the config table if you want to allow use for configuration.
3. All globals defined in the configuration file will end up in the config table the calling code provided.
KayleMaster
Party member
Posts: 234
Joined: Mon Aug 29, 2016 8:51 am

Re: [SOLVED] Is it possible to have a config file next to executable?

Post by KayleMaster »

That's cool, thanks!
User avatar
pgimeno
Party member
Posts: 3656
Joined: Sun Oct 18, 2015 2:58 pm

Re: [SOLVED] Is it possible to have a config file next to executable?

Post by pgimeno »

grump wrote: Fri Jun 22, 2018 5:50 am
pgimeno wrote: Thu Jun 21, 2018 10:31 pmJSON is also good.
https://arp242.net/weblog/json_as_confi ... lease_dont
Fair enough for configuration files, which is the subject of the thread. I agree, simple INI files are probably the best choice.

When a line in a configuration file has an out of range value (e.g. when value can only be 1, 2 or 3 but the user enters a 4), doing it right (according to my standards) involves informing the user about the line number where that happens. That basically discards about every parsing library out there, including Lua. A custom INI-like key-value parser is easy to write and it can handle values on the fly, which makes it easy to report the faulty line number.

Edit: After more thought, I think Lua is actually a viable alternative. The main problem is that it's difficult to secure. I don't know if I've secured it against most possible attacks, I think I've left out a possible memory overflow problem, but here's a possible approach:

(edit 2: edited to take care of errors during love.filesystem.load)

Edit 3: Edited to remove the __index field of the metatable of strings, to prevent patterns being used as DoS via things like ("a"):rep(40):match(("a*"):rep(40).."b")

Code: Select all

-- Limit number of debug.sethook events in the config file.
-- Ideally, this should grow proportionally to the number of elements in valid_config_keys.
local max_config_events = 2000

-- Allowed configuration keys
local valid_config_keys = {param=true, value=true}

local function check_set(t, idx, val)
  if not valid_config_keys[idx] then
    error('Unknown configuration parameter:' .. tostring(idx), 2)
  end
  if idx == 'value' then
    if type(val) ~= 'number' then
      error("Invalid type for value: " .. type(val), 2)
    end
    if val ~= val or val < 1 or val > 3 then
      error("Value out of range: " .. tostring(val), 2)
    end
  end
end

local function timeout()
  error("Timeout reading config file", 2)
end

local function read_config_file(name)
  local config = setmetatable({}, {__newindex=check_set, __metatable=false})
  local ok, err = pcall(love.filesystem.load, name)
  if not ok then return false, "Error loading " .. name .. ": " .. err end
  local config_fn = setfenv(err, config)
  if jit then jit.off(config_fn) end
  debug.sethook(timeout, "", max_config_events)
  local str_idx = getmetatable("").__index
  getmetatable("").__index = nil
  ok, err = pcall(config_fn)
  getmetatable("").__index = str_idx
  debug.sethook()
  if not ok then return false, err end
  return config
end

local ok, err = read_config_file('config.lua')
print("So far so good...")
if not ok then print(err) end

-- this is an example, so we exit immediately:
love.event.quit()
Example config.lua:

Code: Select all

param = 5
value = 4
Output:

Code: Select all

config.lua:2: Value out of range: 4
Another example config.lua:

Code: Select all

param = 5

repeat until false

value = 4
Output:

Code: Select all

config.lua:3: Timeout reading config file
Last edited by pgimeno on Sun Sep 16, 2018 11:06 pm, edited 1 time in total.
Master Thief
Prole
Posts: 8
Joined: Wed Jun 13, 2018 3:39 pm

Re: [SOLVED] Is it possible to have a config file next to executable?

Post by Master Thief »

I always make it so it reverts to a default value if anything goes wrong, unless I want it to complain about some error during development. Not that I have that much implemented in my code as of now, but that's the goal anyway. Ideally you could fill it with gibberish or delete the file and the game would still run fine (and create a new ini file if you delete it).

But I'm not really worried about this type of stuff. Not as long as I'm not making any games where I can expect players to share their files with each other. And even then, I'm not averse to trolls either. :) But an ini file is something you more easily share in a forum post, anyway.
"You can't find LÖVE in the dictionary." -- Daniel Dennett
Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests