Некоторые мысли по первой части вашего вопроса:
Итак, мой вопрос, насколько случайными являются эти числа, возвращаемые realrandom
на самом деле?
Ваша функцияпытается найти адрес таблицы, используя причину ее реализации по умолчанию tostring()
.Я не верю, что строка, возвращаемая tostring{}
, имеет указанный формат или что значение, включенное в эту строку, имеет какое-либо задокументированное значение.На практике это происходит от адреса что-то , связанного с конкретной таблицей, и поэтому разные таблицы преобразуются в разные строки.Тем не менее, следующая версия Lua может изменить это на что угодно.Хуже того, формат, который он принимает, будет сильно зависеть от платформы, поскольку он использует спецификатор формата %p
для sprintf()
, который указывается только как разумное представление указателя.
Существует также гораздо большийвопрос.Хотя адрес n-й таблицы, созданной в процессе, может показаться случайным на вашей платформе, tt может не быть случайным вообще.Или это может варьироваться всего в несколько бит.Например, на моем win7-боксе меняется только несколько битов, причем не очень случайно:
C:...>for /L %i in (1,1,20) do @ lua -e "print{}"
table: 0042E5D8
table: 0061E5D8
table: 0024E5D8
table: 0049E5D8
table: 0042E5D8
table: 0042E5D8
table: 0042E5D8
table: 0064E5D8
table: 0042E5D8
table: 002FE5D8
table: 0042E5D8
table: 0049E5D8
table: 0042E5D8
table: 0042E5D8
table: 0042E5D8
table: 0024E5D8
table: 0042E5D8
table: 0042E5D8
table: 0061E5D8
table: 0042E5D8
Другие платформы, конечно, будут отличаться.Я бы даже ожидал, что будут платформы, где адрес первой выделенной таблицы будет полностью детерминированным и, следовательно, будет идентичным при каждом запуске программы.
Короче говоря, адрес произвольного объекта в образе вашего процессане очень хороший источник случайности.
Редактировать: Для полноты картины я хотел бы добавить пару других мыслей, которые пришли в голову за ночь.
Функция stock tostring()
предоставляется базовой библиотекой и реализуется функцией luaB_tostring()
.Соответствующим битом является этот фрагмент:
switch (lua_type(L, 1)) {
...
default:
lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1));
break;
Если вы действительно вызываете эту функцию, то конец строки будет адресом, представленным стандартным форматом C sprintf()
%p
, тесно связанным сконкретная таблица.Одно наблюдение состоит в том, что я видел несколько различных реализаций для %p
.Windows MSVCR80.DLL (версия библиотеки C, используемая в текущем выпуске Lua для Windows) делает ее эквивалентной %08X
.Моя коробка Ubuntu Karmic Koala, кажется, делает ее эквивалентной %#x
, что заметно сбрасывает ведущие нули.Если вы собираетесь разобрать эту часть строки, то вы должны сделать это более гибким способом с учетом изменения значения %p
.
Также обратите внимание, что выполнениечто-нибудь подобное в библиотечном коде может преподнести вам пару сюрпризов.
Во-первых, если таблица, переданная в tostring()
, имеет метатаблицу, обеспечивающую функцию __tostring()
, то эта функция будет вызвана, а приведенный выше фрагмент никогда не будет выполнен вообще.В вашем случае эта проблема не может возникнуть из-за того, что таблицы имеют отдельные метатаблицы, и вы случайно не применили метатаблицу к вашей локальной таблице.
Во-вторых, к моменту загрузки вашего модуля какой-то другой модуль или предоставленный пользователемкод мог заменить акции tostring()
чем-то другим.Если замена безвредна (например, оболочка memoization ), то, вероятно, это не имеет значения для написанного кода.Тем не менее, это может быть источником атаки и полностью находится вне контроля вашего модуля.Это не очень хорошая идея, если целью является улучшение безопасности вашего случайного начального материала.
В-третьих, вы можете вообще не загружаться в стандартный интерпретатор Lua, а в более крупное приложение.(Lightroom, WoW, Wireshark, ...) могут заменить функции базовой библиотеки своими собственными реализациями.Это гораздо менее вероятная проблема для tostring()
, но обратите внимание, что базовая библиотека print()
является частой целью для замены или удаления в альтернативных реализациях, и существуют модули ( Lua Lanes , для одного), которыеbreak, если print
не является реализацией в базовой библиотеке.