Làm cách nào để tải một tệp bảng và biến mà không gây ô nhiễm môi trường toàn cầu? Kể từ khi làm một loadfile và chạy nó chỉ cần tải tất cả mọi thứ trong không gian toàn cầu và có thể ghi đè lên một cái gì đó khác mà tôi không muốn.Loadfile mà không gây ô nhiễm môi trường toàn cầu
Trả lời
Trong Lua 5.1 và không có nhiều lỗi xử lý bạn có thể làm điều này:
-- 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
Dòng đầu tiên tạo ra một bảng môi trường có sản phẩm nào có thể xem tất cả globals hiện có, nhưng mà không thể trivially thay đổi chúng vì chúng là chỉ hiển thị bằng proxy thông qua phương thức metamethod __index
. Bất kỳ hình cầu nào mà tập lệnh tạo sẽ được lưu trữ trong env
, được trả lại. Điều này sẽ làm việc tốt cho các script đơn giản chỉ cần thiết lập một loạt các tham số cấu hình và có thể cần gọi các hàm an toàn đơn giản để đặt chúng dựa trên các điều kiện trong thời gian chạy.
Lưu ý rằng việc hiển thị hình ảnh chung cho tập lệnh là một sự tiện lợi. Mặc dù các globals không thể sửa đổi từ script theo cách rõ ràng, _G
là một biến toàn cầu chứa tham chiếu đến môi trường toàn cục (có chứa _G._G
, _G._G._G
, v.v.) và _G
có thể được sửa đổi từ tập lệnh. các vấn đề khác. Vì vậy, thay vì sử dụng _G
cho chỉ mục, sẽ tốt hơn nếu bạn xây dựng một bảng chỉ chứa các hàm được biết là an toàn và được tác giả kịch bản của bạn cần.
Giải pháp hoàn chỉnh sẽ là chạy tập lệnh trong hộp cát và có thể được bảo vệ hơn nữa để ngăn chặn việc từ chối dịch vụ vô tình (hoặc cố tình) hoặc tệ hơn. Sandboxes được trình bày chi tiết hơn tại Wiki của người dùng Lua. Chủ đề sâu hơn so với cái nhìn đầu tiên, nhưng miễn là người dùng của bạn được tin cậy là không độc hại thì các giải pháp thực tế rất đơn giản.
Lua 5.2 thay đổi mọi thứ một chút bằng cách xóa setfenv()
có lợi cho thông số mới thành load()
. Chi tiết cũng nằm trong trang wiki.
Một cách để sửa đổi '_G' là đặt' _G' thành một cái gì đó khác trong môi trường: 'local env = setmetatable ({_ G = false}, {__index = _G})' –
Thực ra, tôi nhận ra rằng nó thực sự dễ dàng để phá vỡ trong kịch bản: '_G = nil; _G.print = nil'.Vì vậy, một cái gì đó như thế này sẽ là cần thiết: 'local env = setmetatable ({}, {__index = function (t, k) nếu k == '_ G' sau đó trả về nil khác return _G [k] end})' –
Một ý tưởng chính thể hiện trong trang wiki mà tôi không đưa ra trong câu trả lời là sử dụng danh sách trắng các hàm được chọn cẩn thận là an toàn và cần thiết * thay vì * cho phép _G hoặc bất kỳ bảng mô-đun được biết đến khác trên toàn cầu rò rỉ vào môi trường tập lệnh. Ví dụ, để cho 'string.find' trở thành môi trường an toàn hơn là' string'. Điều đó nói rằng, câu trả lời như tôi đã cho nó là khá thiết thực để cấu hình các tập tin của các tiện ích không an toàn nhỏ. – RBerteig
Đây là một dofile() phiên bản của câu trả lời RBerteig của nơi bạn cung cấp môi trường và kết quả, nếu có, sẽ được trả về (tôi đã cố gắng để làm điều này như một bình luận, nhưng không thể tìm ra sang định dạng nó):
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
Tôi muốn có thể tải nhiều tệp vào cùng một môi trường và một số tệp trong số đó có 'trả lại nội dung' trong đó. Cảm ơn RBerteig, câu trả lời của bạn rất hữu ích và có tính hướng dẫn!
- 1. Chuyển đối tượng mô hình sang RedirectToAction mà không gây ô nhiễm URL?
- 2. scala đối tượng trường hợp ô nhiễm
- 3. Cách hiển thị đối tượng javascript để kiểm tra đơn vị mà không gây ô nhiễm không gian tên chung
- 4. Điều này có gây ra ô nhiễm heap với varargs?
- 5. Không gian tên toàn cầu có nghĩa là gì sẽ bị ô nhiễm?
- 6. Có cách nào để cảnh báo tôi về các ô nhiễm không gian tên toàn cầu không?
- 7. make_pair ô nhiễm không gian tên
- 8. parSapply không tìm thấy các đối tượng trong môi trường toàn cầu
- 9. Làm cách nào để tải các giá trị từ bộ nhớ mà không làm ô nhiễm bộ đệm ẩn?
- 10. Môi trường nguyên văn bên trong ô LaTeX?
- 11. Virtualenv: gói trang web toàn cầu so với gói trang web trong môi trường ảo
- 12. Thiết 'axes.linewidth` mà không thay đổi' rcParams` dict toàn cầu
- 13. hằng số toàn cầu mà không sử dụng #define
- 14. Virtualenv không tạo môi trường
- 15. Ruby: GC có thể :: Profiler.enable trong môi trường sản xuất gây ra vấn đề hiệu suất?
- 16. Ví dụ về yêu cầu truyền trực tuyến không hoạt động trong môi trường của tôi
- 17. có môi trường ảo cho node.js không?
- 18. làm thế nào để sử dụng movntdqa để tránh ô nhiễm bộ nhớ cache?
- 19. Trong môi trường mạng xã hội, cách nào là cách dễ nhất để kiểm tra tình bạn trên toàn cầu?
- 20. biến toàn cầu không có phạm vi toàn cầu
- 21. .htaccess trong nhiều môi trường
- 22. Trả về các phần tử của danh sách dưới dạng các đối tượng độc lập trong môi trường toàn cầu
- 23. Capistrano: Tôi có thể đặt biến môi trường cho toàn bộ phiên làm việc không?
- 24. Biến môi trường CMAKE_INSTALL_PREFIX - không hoạt động?
- 25. Sự cố khi tạo môi trường lstnewen môi trường bắt đầu/kết thúc một môi trường khác
- 26. Biến môi trường không được chuyển từ .htaccess sang PHP
- 27. Nhiều môi trường Magento
- 28. Biến môi trường Javascript
- 29. GHCi môi trường bãi
- 30. Biến môi trường Ruby
Bạn đang sử dụng lua 5.2 hoặc 5.1? – kikito
Tìm thấy nó: 'x = loadfile ("myfile.lua") ' ' setfenv (x, env)' 'x() - tất cả các truy cập toàn cầu sẽ đi đến ENV thay vì sau đó _G' – Milind
Chính xác. Dường như bạn đang ở trong 5.1. Bạn nên tự trả lời và đánh dấu câu trả lời là chính xác, vì vậy nó không xuất hiện "chưa được trả lời", nhưng bạn không có đại diện cho điều đó. :/ – kikito