Come posso caricare un file di tavoli LUA e le variabili senza inquinare l'ambiente globale? Dal momento che eseguire un file di caricamento e eseguirlo carica tutto nello spazio globale e potrebbe sovrascrivere qualcos'altro che non desidero.LoadFile senza inquinare l'ambiente globale
risposta
In Lua 5.1 e senza molto la gestione degli errori si potrebbe fare questo:
-- load and run a script in the provided environment
-- returns the modified environment table
function run(scriptfile)
local env = setmetatable({}, {__index=_G})
assert(pcall(setfenv(assert(loadfile(scriptfile)), env)))
setmetatable(env, nil)
return env
end
La prima riga crea una tabella ambiente vuoto che può vedere tutte le variabili globali esistenti, ma che non può banalmente cambiarli dal momento che sono visibili solo per procura attraverso il metametodo __index
. Eventuali globals creati dallo script verranno archiviati in env
, che viene restituito. Ciò funzionerà bene per gli script semplici che impostano solo una serie di parametri di configurazione e che potrebbero dover chiamare semplici funzioni sicure per impostarli in base alle condizioni in fase di esecuzione.
Nota che, per rendere le variabili globali visibili allo script è una convenienza. Sebbene le variabili globali non possono essere modificati dallo script in modo ovvio, _G
è una variabile globale che contiene un riferimento per l'ambiente globale (contenente _G._G
, _G._G._G
, ecc ...) e _G
può essere modificato dallo script che potrebbe portare a ulteriori problemi.
Quindi piuttosto che utilizzare _G
per l'indice, sarebbe molto meglio costruire una tabella che contenga solo le funzioni note per essere sicure e note per essere necessarie all'autore del proprio script.
Una soluzione completa potrebbe essere quella di eseguire lo script in una sandbox, ed eventualmente con un'ulteriore protezione per evitare accidentale (o intenzionale) negazione del servizio o peggio. Sandboxes sono trattati in modo più dettagliato nella Wiki dell'utente Lua. L'argomento è più profondo di quanto sembri a prima vista, ma finché gli utenti sono considerati non dannosi, le soluzioni pratiche sono semplici.
Lua 5.2 modifica leggermente le cose eliminando setfenv()
in favore di un nuovo parametro su load()
. I dettagli sono anche nella pagina wiki.
Un modo per aggirare la modifica '_G' è quello di impostare' _G' a qualcos'altro per l'ambiente: 'ENV locale = SetMetaTable ({_ G = false}, {__index = _G})' –
In realtà, ho capito che è davvero facile spezzare lo script: '_G = nil; _G.print = quelle negative.Quindi qualcosa del genere sarebbe necessario: 'env locale = setmetatable ({}, {__index = funzione (t, k) se k == '_ G' quindi restituisce nil else return _G [k] end})' –
Un'idea chiave espresso nella pagina wiki che non ho sollevato nella mia risposta è di usare una whitelist di funzioni che sono accuratamente selezionate come sicure e necessarie * piuttosto * che permettere a _G o qualsiasi altra tabella di moduli globalmente nota di filtrare nell'ambiente dello script. È molto più sicuro lasciare 'stringa.find' nell'ambiente che' stringa' stessa, per esempio. Detto questo, la risposta che ho dato è abbastanza pratica per i file di configurazione di piccole utilità non sicure. – RBerteig
Ecco un dofile() versione di risposta di RBerteig in cui si fornisce l'ambiente e il risultato, se presente, viene restituito (ho provato a fare questo come un commento, ma non riuscivo a capire in formato esso):
local function DofileIntoEnv(filename, env)
setmetatable (env, { __index = _G })
local status, result = assert(pcall(setfenv(assert(loadfile(filename)), env)))
setmetatable(env, nil)
return result
end
ho voluto essere in grado di caricare più file in uno stesso ambiente, e alcuni di questi file ha avuto un 'restituire qualcosa' in loro. Grazie RBerteig, la tua risposta è stata utile e istruttiva!
- 1. Come esporre oggetti javascript per il test delle unità senza inquinare lo spazio dei nomi globale
- 2. Passare un oggetto modello a RedirectToAction senza inquinare l'URL?
- 3. window.onload senza variabile globale
- 4. Differenza tra LoadFile e LoadFrom con .NET Assembly?
- 5. Impostazione `axes.linewidth` senza cambiare il dict globale` rcParams`
- 6. la ricorsione non funziona senza dichiarare la variabile globale
- 7. Usa requirejs e jquery, senza jolly globale che sta rovesciando?
- 8. Uso di gulp senza gulp globale // modifica: e senza collegamento al file bin js
- 9. variabile globale non ha portata globale
- 10. C/C++ globale vs statico globale
- 11. Un altro hook globale riguarda il mio hook globale
- 12. Sovraccarico globale dell'operatore typecast?
- 13. apache globale
- 14. Come si carica un file in una variabile usando il task 'loadfile'?
- 15. Qual è il modo corretto di esporre un modulo requireJS allo spazio dei nomi globale?
- 16. Eliminazione "posizionamento" globale []
- 17. Impostazione Server.ScriptTimeout globale nell'ambito?
- 18. ADBannerView globale nell'app per iPhone
- 19. Emacs configurazione globale di schede
- 20. Dimensione carattere WPF globale
- 21. Statico vs globale
- 22. array globale in php
- 23. WPF - Stile globale?
- 24. PHP globale o $ GLOBALS
- 25. Variabile globale Angular2 osservabile
- 26. Java globale namespace accesso
- 27. variabile globale ampia applicazione
- 28. Ricerca globale in Android
- 29. ReferenceError e l'oggetto globale
- 30. Nome globale in Python
Si sta utilizzando lua 5.2 o 5.1? – kikito
trovato: 'x = loadfile ("myfile.lua")' ' setfenv (x, ENV)' ' x() - tutti gli accessi a livello mondiale sarebbe andato a env piuttosto che _G' – Milind
Esattamente. Sembra che tu sia in 5.1. Dovresti risponderti e contrassegnare la tua risposta come corretta, in modo che non appaia "senza risposta", ma per questo non hai il rappresentante. :/ – kikito