OberonCore
https://forum.oberoncore.ru/

Доступ через Meta к полям неэкспортированных объектов
https://forum.oberoncore.ru/viewtopic.php?f=2&t=227
Страница 1 из 1

Автор:  Илья Ермаков [ Суббота, 03 Июнь, 2006 00:26 ]
Заголовок сообщения:  Доступ через Meta к полям неэкспортированных объектов

Обнаружил нюанас в метапрограммировании в ББ.
Предыстория: технически в ББ можно добраться до любого поля любой переменной/типа, будь он экспортированный, неэскпортированный либо локально объявленный - для этого нужно обращаться к Kernel, чего, естественно, из прикладных модулей делать не следует. А контроль на доступность объекта по его метке экспорта проверяется уже на уровне модуля Meta - если объект неэкспортированный, то возвращается пустой Item.

Однако синтаксически компилятор КП (по крайней мере, в BlackBox) допускает постановку метки экспорта для поля неэкспортированного типа. Я раньше думал, что просто для удобства программиста - чтобы для скрытия/открытия типа не приходилось перемечать все его поля. Однако обнаружилась интересная вещь - поля неэспортированных объектов, помеченные *, становятся доступны через Meta.

Можно провести эксперимент:
Код:
MODULE TempMetaTarget;

   IMPORT Meta;

   VAR
      rec: POINTER TO RECORD
         a: INTEGER
      END;
   
   PROCEDURE Do* ;
      VAR item, field: Meta.Item;
   BEGIN
      NEW(rec);
      Meta.GetItem(rec, item);
      ASSERT(item.Valid(), 20);
      item.Lookup("a", field);
      ASSERT(field.Valid(), 21)   
   END Do;

END TempMetaTarget.

Запустим процедуру Do - получим TRAP 21. Все правильно. Item по указателю получить можно, работать с неэкспортированными полями нельзя. Поставим после a звездочку - код будет работать, доступ к полю получен.

В принципе, такое поведение ничего плохого не несет и даже логично. Это позволяет, например, не открывать на полное обозрение какие-либо типы, но в то же время работать с ними через SqlDB и т.п.

Однако возникает вопрос: Ominc сделали это намеренно или случайно? Как это согласуется со стандартом языка? Таким образом, при развитии BlackBox следует ли это а) сохранить и задокументировать б) сохранить, но не документировать и использование не поощрять в) посчитать ошибкой, "нарушением безопасности" и исправить Meta ?
Я лично склоняюсь к варианту а). Прошу высказывать мнения и предложения...

Автор:  Сергей Оборотов [ Суббота, 03 Июнь, 2006 06:46 ]
Заголовок сообщения: 

Только если править то не Meta, а то место где видимость устанавливается в компиляторе. Что предпочтительнее, по-моему. Если поля всё-таки нужны - то можно пользоваться экспортированными типами или Kernel напрямую. Какие с ними проблемы?

Автор:  Илья Ермаков [ Суббота, 03 Июнь, 2006 15:42 ]
Заголовок сообщения: 

Цитата:
а то место где видимость устанавливается в компиляторе.

Править компилятор - последнее дело... Как я уже сказал, "отрезания" доступа к закрытым полям ЦЕЛИКОМ делается на уровне Meta.
Цитата:
Если поля всё-таки нужны - то можно пользоваться экспортированными типами или Kernel напрямую. Какие с ними проблемы?

В том-то и дело, что Kernel использовать нежелательно, если можно обойтись без него.

Автор:  Сергей Оборотов [ Воскресенье, 04 Июнь, 2006 06:31 ]
Заголовок сообщения: 

Илья Ермаков писал(а):
Цитата:
а то место где видимость устанавливается в компиляторе.

Править компилятор - последнее дело... Как я уже сказал, "отрезания" доступа к закрытым полям ЦЕЛИКОМ делается на уровне Meta.
В том-то и дело, что Kernel использовать нежелательно, если можно обойтись без него.
В том-то и дело, что обсуждаемые поля компилятором не закрываются. Что противоречит способу использования этих полей. А почему экспортированный тип не использовать? Илья, Вы так и не сказали. Тогда можно и без Meta обойтись, насколько я понимаю.
P.S. В крайнем случае компромисный вариант б вполне устроит тех, кто ничего об этом не знал.

Автор:  Илья Ермаков [ Воскресенье, 04 Июнь, 2006 10:48 ]
Заголовок сообщения: 

Цитата:
А почему экспортированный тип не использовать? Илья, Вы так и не сказали. Тогда можно и без Meta обойтись, насколько я понимаю.


Я уже привел пример. У меня есть модуль, работающий с базой данных. Я не знал про обсуждаемый нюанс и был вынужден открывать все типы, которые я читаю/пишу из базы через SqlDB, т.к. SqlDB работает именно через Meta (и правильно сделано, это не системный модуль. Если Stores "позволительно" работать через Kernel, то прикладным подсистемам уже нежелательно к нему привязываться). Мне нравится вариант не открывать целиком типы, а открыть только некоторые поля, которые должны считываться из базы. В принципе, такое поведение Meta/компилятора логично - каждый элемент имеет свою метку доступа. Если поле имеет метку доступа, а тип в целом не имеет, то служебные операции могут быть выполнены на полях, но не могут - на типе в целом. Брешей в безопасности это не создает.
Я сделаю проще - спишусь с Ominc и проясню ситуацию - было ли это сделано случайно или намеренно.

Автор:  Сергей Оборотов [ Понедельник, 05 Июнь, 2006 05:19 ]
Заголовок сообщения: 

Хорошо, а какие бреши в безопасности создает открытый тип? Если мне это будет понятно - то я, пожалуй, и соглашусь, что не стоит его открывать.

Автор:  Илья Ермаков [ Понедельник, 05 Июнь, 2006 11:39 ]
Заголовок сообщения: 

Проблема не в безопасности, а в том, что нет необходимости засорять интерфейс модуля типами, которые используются только внутри самого модуля.

Автор:  Сергей Оборотов [ Понедельник, 05 Июнь, 2006 16:02 ]
Заголовок сообщения: 

А почему не используется? Хотелось бы именно его и использовать. Тогда не придется Meta импортировать. Быстрее будет работать.

Автор:  Илья Ермаков [ Понедельник, 05 Июнь, 2006 17:26 ]
Заголовок сообщения: 

Вы, видимо, слабо понимаете механизм метапрограммирования. Meta предназначен для того, чтобы ваш код мог работать с теми типами, о которых он вообще ничего не знает на этапе выполнения.
SqlDB.Table.Read(row: INTEGER; rec: ANYREC) ничего не знает и знать не может про ваши конкретные типы. Через Meta происходит разбор структуры записи и заполнение ее данными из таблицы. Только в данный момент для того, чтобы работать со своим типом через SqlDB и аналогичные сервисы, приходится обязательно его экспортировать. Иначе SqlDB не найдет в нем ни одного поля и данные туда не занесет по понятным причинам. У меня, например, в библиотеке есть процедура ZeroRec, которая инициализирует нулями и "" любую запись, но она также работает только с экспортированными записями. Я могу, конечно, переписать через Kernel, но пока мне это не нужно. Модулю Stores как сердцу Framework'a, позволительно привязываться к Kernel, пользовательским модулям - нежелательно.
В любом случае ждем ответа от Ominc - если текущее поведение Meta является не ошибкой, а сознательным решением, то тут и обсуждать нечего...

Автор:  Сергей Оборотов [ Понедельник, 05 Июнь, 2006 21:32 ]
Заголовок сообщения: 

Я лишь высказал пожелание использовать открытые типы там, где Meta не нужен, не сужая тему противоположным случаем. Я себе представлял, что и Вы не только метапрограммирование имели в виду. Извините, если это было не так.
Если речь вести о вещах не связанных с метапрограммированием, считаете ли Вы полезным иметь возможность доступа к полям не экспортируемого объекта?

Автор:  Илья Ермаков [ Понедельник, 05 Июнь, 2006 22:02 ]
Заголовок сообщения: 

GUEST писал(а):
Если речь вести о вещах не связанных с метапрограммированием, считаете ли Вы полезным иметь возможность доступа к полям не экспортируемого объекта?

Так такой доступ и есть только через метапрограммирование... На этапе компиляции сам тип недоступен, никакие действия с ним недоступны.

Автор:  Сергей Оборотов [ Вторник, 06 Июнь, 2006 04:21 ]
Заголовок сообщения: 

Хотя вопрос предполагал два ответа, Вы, Илья, нашли третий.

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/