Jak mogę załadować plik tabel i zmiennych Lua bez zanieczyszczania środowiska globalnego? Od robienia pliku load i uruchamiania go ładuję wszystko w przestrzeni globalnej i mogę nadpisać coś innego, czego nie chcę.Plik ładowania bez zanieczyszczania środowiska globalnego
Odpowiedz
w Lua 5.1 i bez większego błędu obsługi można to zrobić:
-- 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
Pierwsza linia tworzy pustą tablicę środowiska, które można zobaczyć wszystkie istniejące globalnych, ale których nie można trywialnie zmienić je, ponieważ są one widoczne tylko przez proxy za pośrednictwem metametodu __index
. Wszystkie globale utworzone przez skrypt zostaną zapisane w postaci env
, która zostanie zwrócona. To zadziała dobrze w przypadku prostych skryptów, które po prostu ustawiają kilka parametrów konfiguracyjnych, i które mogą wymagać wywoływania prostych bezpiecznych funkcji, aby ustawić je na podstawie warunków w czasie wykonywania.
Należy pamiętać, że tworzenie globali widocznych w skrypcie jest wygodą. Mimo że globalnych nie można w sposób oczywisty zmodyfikować ze skryptu, _G
jest zmienną globalną zawierającą odniesienie do środowiska globalnego (zawierającą _G._G
, _G._G._G
, itp.) I _G
można zmodyfikować ze skryptu, który może prowadzić do dalsze problemy.
Dlatego zamiast używać indeksu, należy znacznie lepiej skonstruować tabelę zawierającą tylko funkcje znane jako bezpieczne i znane autorowi skryptu.
Kompletnym rozwiązaniem byłoby uruchomienie skryptu w piaskownicy i ewentualnie dalsze zabezpieczenie przed przypadkową (lub celową) odmową usługi lub gorzej. Sandboxes są omówione bardziej szczegółowo na Wiki użytkownika Lua. Temat jest głębszy, niż się wydaje na pierwszy rzut oka, ale dopóki twoi użytkownicy są zaufani, aby nie byli złośliwi, praktyczne rozwiązania są proste.
Lua 5.2 zmienia trochę rzeczy, eliminując setfenv()
na korzyść nowego parametru do load()
. Szczegóły znajdują się również na stronie wiki.
Jednym ze sposobów obejścia modyfikacji '_G' jest ustawienie' _G' na coś innego w środowisku: 'local env = setmetatable ({_ G = false}, {__index = _G})' –
W rzeczywistości zdałem sobie sprawę, że bardzo łatwo jest przerwać skrypt: '_G = nil; _G.print = nil'.Potrzebne by było coś takiego: 'local env = setmetatable ({}, {__index = funkcja (t, k), jeśli k == '_ G', a następnie zwraca zero, to zwraca _G [k] koniec})' –
Jedna kluczowa idea wyrażone na stronie wiki, której nie poruszałem w mojej odpowiedzi, to użycie białej listy funkcji, które są starannie wybrane jako bezpieczne i potrzebne * raczej * niż dopuszczenie _G lub innej globalnie znanej tabeli modułów do wycieku do środowiska skryptu. O wiele bezpieczniej jest umieścić 'string.find' w środowisku niż na przykład' string'. To powiedziawszy, odpowiedź, którą podałem, jest całkiem praktyczna w przypadku plików konfiguracyjnych małych niezabezpieczonych narzędzi. – RBerteig
Oto dofile() wersja RBerteig za odpowiedź gdzie dostarczyć środowiska oraz wynik, jeśli w ogóle, jest zwracana (próbowałem zrobić to jako komentarz, ale nie mogliśmy zorientować się, do formatu it):
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
Chciałem móc załadować wiele plików do tego samego środowiska, a niektóre z tych plików miały "coś w sobie". Dzięki RBerteig, twoja odpowiedź była pomocna i pouczająca!
- 1. Utrzymywanie globalnego odniesienia do środowiska JNIEnv
- 2. Jak mogę się zalogować bez metody zanieczyszczania?
- 3. Jak mogę załadować wartości z pamięci bez zanieczyszczania pamięci podręcznej?
- 4. Ustawianie `axes.linewidth` bez zmiany` rcParams` globalnego dict
- 5. Jak znaleźć tylko deklarowane metody podczas ładowania zestawu środowiska wykonawczego?
- 6. Dodaj nagłówek do CSV bez ładowania CSV
- 7. Przeciążenie globalnego operatora typograficznego?
- 8. Wstaw wiersz bez ponownego ładowania tabeli
- 9. Modyfikowanie ciągu zapytania bez ponownego ładowania strony
- 10. Prześlij formularz bez ponownego ładowania strony
- 11. Jak zbudować link bez wstępnego ładowania modelu?
- 12. Jak uzyskać wersję zespołu bez jej ładowania?
- 13. jQuery parse html bez ładowania obrazów
- 14. Jak eksponować obiekty javascript do testowania jednostkowego bez zanieczyszczania globalnej przestrzeni nazw
- 15. Uruchom cygwin zbudowany exe w oknach bez środowiska cygwin
- 16. Moduł globalnego modułu NVM
- 17. MyBatis - definiowanie globalnego parametru
- 18. upuszczenie globalnego tabeli tymczasowej
- 19. Dołącz lista słowników Python pliku bez ładowania to
- 20. Obsługa globalnego wyjątku Xamarin | Droid | iOS
- 21. Uruchamianie plików binarnych C++ bez redystrybucji środowiska wykonawczego (Server2k3, XPSP3)
- 22. Specyficzny dla środowiska plik application.properties w aplikacji Spring Boot
- 23. Środowiska Sitecore
- 24. Usługa globalnego sondowania usługi AngularJS
- 25. popd stos katalogu globalnego popd?
- 26. Wykrywanie środowiska: node.js lub przeglądarka
- 27. Jak stworzyć aplikację DirectFB bez opuszczania środowiska X.11
- 28. Uruchom program Matlab w systemie Linux bez środowiska graficznego?
- 29. Używanie globalnego słownika z wątkami w Pythonie
- 30. Jak pobrać plik bez formularza
Czy używasz lua 5.2 lub 5.1? – kikito
Znaleziono go: 'x = loadFile ("myfile.lua")' 'setfenv (x ENV)' ' x() - wszystkie globalne dostępy pójdzie ENV a następnie _G' – Milind
Dokładnie. Wyglądasz na 5.1. Powinieneś odpowiedzieć sobie i zaznaczyć swoją odpowiedź jako poprawną, więc nie wydaje się "bez odpowiedzi", ale nie masz za to przedstawiciela. :/ – kikito