Перейти к содержимому
  • 0
swg2you

Баг или фича? или реализация load в Lua@OpenComuters

Вопрос

пример кода:

a=1
local e={print=print, load=load, a='2'}
e._G=e
load(
[[
  print(a) 
  load("print(a)")()
]]
, '', '', e)() 

ожидается вывод:
2
2


а в реальности:
2
1

 
Проверял и под OpenOS и в чистой среде.
 
Это баг или фича?

Изменено пользователем swg2you

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Рекомендуемые сообщения

Такое происходит из-за биндинга, есть разница между статичным и динамичным.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Такое происходит из-за биндинга, есть разница между статичным и динамичным.

Не понял.

 

load("print(a)") вызванный с параметрами "по умолчанию", должен компилировать блок "print(a)" в среде _G

Поскольку для load("print(a)") глобальной средой является e, то ожидается что именно e будет средой для "print(a)"

 

Но, почему-то, load берет среду из места в которое не должен иметь доступа.

Изменено пользователем swg2you

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

а в реальности:

2

1

Да, действительно, выдает не то, что подразумевается. Но не 2,1 а 2, nil. Почему так происходит не в курсе, нужно видимо у самого Сангара спрашивать, либо копаться в реализации этого load() на гитхабе.

 

 

 

Такое происходит из-за биндинга
Какой еще биндинг, Рид? Мониторов что ли? =))

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 

Да, действительно, выдает не то, что подразумевается. Но не 2,1 а 2, nil. Почему так происходит не в курсе, нужно видимо у самого Сангара спрашивать, либо копаться в реализации этого load() на гитхабе.

nil - это я первую строчку в примере потерял.

поправил пример.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Это баг или фича?

 

В для первого load() ты указываешь переменную окружения, насколько я понял.

Для второго - нет (используется "глобальное окружение").

Поэтому, у них разные переменные а.

 

Строка из документации:

 

When loading a chunk, the top-level function gets a new _ENV upvalue, and any nested functions inside it can see it. You can pretend that when loading works something like this:

  local _ENV = _G

return function (...) -- this function is what's returned from load

-- code you passed to load goes here, with all global variable names replaced with _ENV lookups

-- so, for example "a = b" becomes "_ENV.a = _ENV.b" if neither a nor b were declared local

end

 

Т.е. загруженный чанк получает новую переменную окружения, и при этом LVM выдает ей "внешний" _G.

Изменено пользователем Totoro

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В для первого load() ты указываешь переменную окружения, насколько я понял.

Для второго - нет (используется "глобальное окружение").

Поэтому, у них разные переменные а.

Да, но блок

 

[[

print(a)

load("print(a)")()

]]

 

скомпилирован в среде e.

 

Для этого блока глобальной средой является содержимое таблицы e. Т.е. все что находится в этом блоке не может видеть ничего кроме переданных функций print, load, заданной a и замыкающей _G.

 

Получается что load() игнорируя принципы Lua и собственную среду выполнения - получает доступ к рутовому глобалу, мало того, дает этот доступ компилируемому блоку.

 

На мой взгляд, это серьезный баг реализации, нарушающий общую концепцию изоляции сред в Lua. Либо я неверно понимаю эту концепцию.

 

upd:

если у кого-то установлен чистый Lua без майнкрафтов и прочих крафтов, прошу проверить, проявляется ли такой эффект там.

Изменено пользователем swg2you

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Я давно подозревал, что функция serialization.unserialize  -  дыра для хакера

Хотя, нет. Что бы дыра стала дырой в окружении должна быть разрешена функция load. А в serialization.unserialize - только math.huge

Изменено пользователем Zer0Galaxy

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
если у кого-то установлен чистый Lua без майнкрафтов и прочих крафтов, прошу проверить, проявляется ли такой эффект там.
a=1 load(" print(a) load('print(a)')()",nil,nil,{print=print, load=load, a=2})()  

Результат:

2

1

Вывод: не хочешь давать доступ к руту - не разрешай в среде функцию load

Изменено пользователем Zer0Galaxy

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
a=1 load(" print(a) load('print(a)')()",nil,nil,{print=print, load=load, a=2})()  

Результат:

2

1

Вывод: не хочешь давать доступ к руту - не разрешай в среде функцию load

 

Если это результат выполнения на одной из чистых реализаций, то этот баг вполне можно считать фичей.

 

Убрать load - не вариант. Придется учитывать эту особенность и исправлять поведение кода на более каноничное. 

 

upd:

задал тот-же вопрос на стаковерфлоу, отвечают что если не указать среду лоад берет, цитирую: "very global environment" )

будем глушить. OpenOs то надо в окошке запустить.

Изменено пользователем swg2you

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Да, это выполнялось в самом чистом Луа, который мне удалось найти.

А что если сделать как-то так:

a=1
e={print=print, a=2}
e.load=function(str) return load(str,nil,nil,e) end
load(" print(a) load('print(a)')()",nil,nil,e)() 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 

Да, это выполнялось в самом чистом Луа, который мне удалось найти.

А что если сделать как-то так:

a=1
e={print=print, a=2}
e.load=function(str) return load(str,nil,nil,e) end
load(" print(a) load('print(a)')()",nil,nil,e)() 

именно так. но чуть менее грубо.

e.load=function(c,s,m,g)
  return load(c,s,m,g or e)
end

чтобы все параметры обрабатывались, а среда по умолчанию бралась из среды выполнения.

 

там еще вроде с _ENV можно сыграть, но я в нем пока не разобрался.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


×
×
  • Создать...