Forth и другие саморасширяющиеся системы программирования Locations of visitors to this page
Текущее время: Вт июл 14, 2020 02:19

...
Google Search
Forth-FAQ Spy Grafic

Часовой пояс: UTC + 3 часа [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 9 ] 
Автор Сообщение
 Заголовок сообщения: Скрипты и плагины в Форте
СообщениеДобавлено: Чт ноя 27, 2008 01:28 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 5012
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 21 раз.
Поблагодарили: 58 раз.
Автор: mOleg
Дата публикации: 2008-11-26
публикуется впервые

Скрипты и плагины в Форте

Аннотация

В статье предлагается размышление о том, как можно реализовать в форт-программах скрипты<sup>1</sup> и плагины<sup>2</sup>, то есть куски исходного текста и бинарного кода, создаваемые не разработчиком программы, а ее пользователем для получения дополнительной функциональности уже готовой программы. Так как обычно программы, написанные на форте, уже содержат в себе компилятор<sup>3</sup>, а так же, обычно, обращаются к функциям по их именам, такая идея кажется очень удобной и перспективной, даже присущей Форту. Часто создатель программы не может предусмотреть всех возможных направлений использования программы, а так же ряда удобств, которые реализовать очень просто пользователю, не отвлекая программиста. Однако, при реализации такого подхода, если не забывать об устойчивости программы (то есть скрипты и плагины не должны «ронять» работающую программу), а так же о безопасности (чтобы кто-то не написал деструктивный код в виде скрипта), возникают довольно серьезные проблемы.

Введение
Форт устроен очень удобно с точки зрения встраивания новой функциональности в уже существующие программы, то есть на первый взгляд очень легко и естественно можно реализовать скрипты. В реальности же все не так гладко, потому что некорректное использование ряда слов<sup>4</sup> гарантированно приводит к критическому завершению работы программы. В ряде случаев форт слишком открыт для вмешательств, что одновременно является и его сильной стороной и его большой слабостью.
На данный момент времени все Форты (виденные мною) устроены по уязвимой схеме, в которой данные, код, различные критические внутренние структуры доступны вмешательству, поэтому могут быть «исправлены» или запорчены случайно в результате ошибки или преднамеренно, в том числе злонамеренно. Это одновременно и хорошо, если управляемо, и плохо, так как невозможно обезопасить скрипты. Из-за стремления к быстродействию, нежелания реализовывать сложные схемы работы с памятью, а так же, зачастую, неизбежного наследования модели памяти, предлагаемой операционной системой, под которой работает форт-программа, делать скрипты в форте не так просто, как может показаться на первый взгляд. Существуют методики создания безопасных интерфейсов, но все они имеют свои ограничения и проблемы.

Анализ

Наиболее опасными словами в Форт-системе, а значит и в программе, в первую очередь являются слова для работы с памятью: @ ! CMOVE и подобные им; после них, конечно же, идут системные переменные и слова для работы с ними, например: S0 R0 SP! RP! DP LAST и им подобные; слова, работающие со стеком возвратов: >R R> RDROP R@ и т.п.; а так же слова или конструкции слов, передающие управление на указанный адрес (а не на фиксированную метку): EXECUTE CATCH и подобные, либо пары слов: >R EXIT и т.п., а так же RECURSE. Соответственно, за ними идут слова, работающие с файлами. Не стоит забывать о потенциальной опасности переполнения стеков, утечек памяти (что критично в программах, которые должны работать непрерывно на протяжении длительного времени), а так же потенциальной опасности несовместимости некоторых слов (то есть такая последовательность «безопасных» слов, которая приводит к исключению, например, деление на нуль).
Стоит отметить, что плагины в форте удобно представлять их исходными текстами (то есть скриптами), так как скорость компиляции кода очень высока, а плагины редко бывают очень большими. В то же время бинарные плагины лучше оформлять как пару: dll-библиотека + инициализирующий исходный текст, который подключит dll, импортирует нужные функции, произведет необходимые инициализирующие действия и передаст управление на необходимый код. Однако же, контролировать dll мы не в состоянии, поэтому этот вариант дальше в тексте рассматриваться не будет. Реализация же поддержки бинарного кода внутри форт-системы вещь редкая и достаточно нетривиальная (я знаю только одну такую форт систему SMAL32) поэтому дальше будут рассматриваться только скрипты.

Итак, первый вывод: при необходимости обеспечения надежной работы программы, поддерживающей механизм скриптов, необходимо изолировать опасные функции, имеющиеся в словарях программы от скриптов.
Второе: при работе с файлами необходимо контролировать действия плагина, например, не давать открывать dll и исполнимые файлы, не давать возможности выходить за пределы определенных каталогов, не давать открывать самостоятельно файловые потоки и тому подобное.
Третье: так как обойтись при решении более-менее серьезной задачи без переменных и массивов в памяти (в том числе динамических) невозможно, необходим некий набор слов для работы с памятью, не позволяющий залазить в системные области программы.
Четвертое: все интерфейсные слова необходимо стараться делать таким образом, чтобы они поглощали и возвращали значения, а не ссылки на них. То есть, надо учиться обходиться без реальных адресов.
Пятое: не желательно предоставление возможности подключения внешних динамических библиотек, потому что их невозможно контролировать. То есть скрипты должны рассчитывать только на возможности, предоставляемые базовой программой.

Изоляция опасных слов
Изолировать опасные функции от плагина можно в отдельный словарь, который при сборке и работе плагина только и будет доступен. Для SPF это может выглядеть так:
<pre>
\ создаем словарь, в котором будут находиться общие для всех плагинов слова
VOCABULARY Interface
\ создаем словарь, в котором будут находиться все плагины
VOCABULARY Plugins

\ создается словарь, определяемый именем плагина
\ (вероятно это будет имя файла, содержащего исходный текст плагина,
\ но в данном случае имя плагина будет идти за определяющим словом Plugin:
: Plugin: ( / name --> )
ALSO Plugins DEFINITIONS \ в словаре Plugins
VOCABULARY \ создается словарь с именем name
ONLY Interface \ оставляется в контексте только интерфейсный словарь
ALSO \ поверх интерфейсного словаря
VOC-LIST @ CELL + CONTEXT ! \ кладется созданный словарь name
DEFINITIONS \ и делается текущим
;

\ добавляем слова, доступные любому плагину, то есть: создаем интерфейс
ALSO Interface DEFINITIONS

: WORDS WORDS ; \ в данном случае создается заголовок в словаре Interface
: BYE TERMINATE ; \ для уже существующих в словаре FORTH слов.
: ORDER ORDER ;
: : : ;
: ; [COMPILE] ; ; IMMEDIATE
\ …и другие слова, доступные плагину…

PREVIOUS DEFINITIONS

\ Теперь можно попробовать посмотреть что получилось:
Plugin: test
ORDER \ enter –
\ должен показать в контексте два словаря: Interface test и
\ test текущим словарем, то есть словарем, в который будет в дальнейшем вестись
\ компиляция
BYE
\ позволит нам завершить процесс плагина
</pre>
Впрочем, каждый скрипт должен работать в собственном потоке, что удобно уже потому, что завершение потока не приведет к завершению программы. Так же удобно автоматическое освобождение блоков памяти, занятых в хипе при завершении процесса. Поэтому так же необходимо предусмотреть некий механизм, инициализирующий контекст таким образом, чтобы в нем были только необходимые для работы словари, и, соответственно, слова. Кроме того, если предполагать, что скрипт может быть завершен принудительно, либо в результате ошибки, либо после выполнения предназначенных действий самостоятельно, стоит позаботиться об удалении кода скрипта, словаря, в котором этот скрипт находится. Перечисленные действия реализовать, например, в SPF не так уж и просто, поэтому в рамках данной статьи они рассматриваться не будут. Компилирующие структуры должны использовать изолированный стек, не давая перехватить и подменить адреса переходов.

Изоляция адресного пространства
Изолировать пространство данных процесса тоже достаточно просто на первый взгляд: надо выделить память в хипе, необходимого размера (этот размер может задавать сам скрипт), и работать с этой памятью, как с именованным массивом, при этом обязательно контролировать выход за пределы массива (либо просто ограничивать адресуемую область). Например, если базовый адрес памяти хранится в переменной Memory , а размер этой памяти в переменной Limit , можно переписать слова @ ! следующим образом:
<pre>
: ! ( n addr --> )
Limit OVER > THROW \ если хочется контролировать выход за диапазон, либо:
\ Limit UMIN \ если хочется ограничить выход за предел диапазона
Memory + \ получить реальный адрес переменной
! \ сохранить значение
;
</pre>
Кстати, переменная Limit должна быть на один CELL меньше, реально выделенной памяти. Точнее, реально выделенная память должна быть на один CELL больше запрашиваемой, которая будет храниться в Limit, либо придется учитывать размерность данных, записываемых в массив, чтобы не выйти за его границы при работе с крайними адресами.

Аналогично будет выглядеть слово @ :
<pre>
: @ ( addr --> n )
Limit UMIN \ обязательно беззнаковый, чтобы не нарваться на отрицательные адреса.
Memory +
@ ;
</pre>
Пересылки будут выглядеть чуточку сложнее, но для иллюстрации идеи достаточно рассмотрения слов @ и ! . Проблема только в том, что постоянная проверка выхода за адресуемый диапазон отнимает время, но с потерей производительности в любом случае придется мириться.
В принципе, похожий механизм уже используется в системе при работе с USER переменными, однако,
USER переменные возвращают реальные адреса, с которыми работает классический @ и ! , что нас никоим образом не устраивает, хотя можно ограничиться только USER-VALUE переменными. К тому же USER область по умолчанию не очень велика, и содержит много не нужных и даже опасных данных, например, переменные S0 R0 .
Кроме того, как уже отмечалось, код самого скрипта необходимо компилировать не в базовую область программы, а в какое-то отдельное адресное пространство (в SPF для этого можно использовать TEMP-WORDLIST). Так же не стоит забывать о том, что одновременное компилирование нескольких слов в память форт может не поддерживать, по крайней мере, в SPF этого делать нельзя даже во временные словари.

Другие варианты
Перечисленные методики обладают неприятным качеством – они ограничивают возможности скрипта, методики работы в рамках форт-системы, то есть требуют создания некоего специфичного проблемно-ориентированного языка с ограниченной функциональностью, что не всегда приемлемо. То есть получившийся язык не будет обладать гибкостью классического форта и будет иметь другой, пусть и близкий, набор слов (наследование традиционных имен может привести к путанице). Возможным выходом из данного положения видится создание защищенной виртуальной машины и форта на ее основе, который бы просто не давал возможности выходить на системный уровень и не давал непредвиденным заранее образом влиять на базовую программу, либо такая машина должна подключаться к готовой программе. Однако же, вся гибкость, мощьность, свобода форта не обязательно необходимы при создании интерфейсов для скриптов (или плагинов), поэтому без специфичных ВМ все-таки можно обойтись в большом количестве случаев.

1. исходные тексты, подключаемые средствами программы, позволяющие автоматизировать некую задачу, которую без сценария пользователь делал бы вручную, используя интерфейс программы.
2. независимые бинарные модули, подключаемые к программе через специализированный интерфейс
3. очень редко форт содержит в себе только код, относящийся к программе, обычно форт-программа наследует компилятор, на котором она создана
4. в современном программировании принято программу разделять на небольшие куски, так называемые подпрограммы или функции – в форте такие куски принято называть определениями или словами


Последний раз редактировалось mOleg Пн апр 27, 2009 03:26, всего редактировалось 3 раз(а).

Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Пн дек 08, 2008 04:17 
Не в сети

Зарегистрирован: Сб май 06, 2006 12:01
Сообщения: 959
Откуда: Украина, Харьков
Благодарил (а): 2 раз.
Поблагодарили: 7 раз.
(с 27 ноя не мог залить :( )

Так почему не хочешь красные числа в качестве ссылок?
А то получается несоответствие - сначала были звездочки, а потом - числа.
mOleg писал(а):
не позволяющий залазить в системные области программы
обращаться к системным областям. "Залазить" - разговорное и неприменимо в строгом научном тексте.
mOleg писал(а):
Четвертое: все интерфейсные слова необходимо стараться делать таким образом, чтобы они поглощали и возвращали значения, а не ссылки на них. То есть, надо учиться обходиться без реальных адресов.
не понял смысла. Можешь сказать более подробно?
"стараться делать" подразумевает необязательность действия, что не подходит в контексте твоего предложения.
mOleg писал(а):
Пятое: не желательно предоставление возможности подключения внешних динамических библиотек, потому что их невозможно контролировать. То есть скрипты должны рассчитывать только на возможности, предоставляемые базовой программой.
Вроде это (или аналогичное) сказал в п.1. Может, предложить вообще запретить?
Но применение DLL в скриптах очень удобное расширение. Обсуждаемо.
mOleg писал(а):
мощьность
мощность

_________________
With best wishes, in4.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Пн дек 08, 2008 08:36 
Не в сети
Administrator
Administrator
Аватара пользователя

Зарегистрирован: Вт май 02, 2006 13:19
Сообщения: 3565
Откуда: St.Petersburg
Благодарил (а): 4 раз.
Поблагодарили: 72 раз.
Кстати, для ссылок можно пользоваться
Код:
<sup>[color=red]1[/color]<sup>


получится - <sup>1</sup>

<sup>1</sup>- ссылка в верхнем индексе

_________________
С уважением, WingLion
Forth-CPU . RuF09WE
Мой Форт
Отсутствие бана это не заслуга юзера, а недоработка модератора (с)


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Пн дек 08, 2008 09:05 
Не в сети
Administrator
Administrator
Аватара пользователя

Зарегистрирован: Вт май 02, 2006 13:19
Сообщения: 3565
Откуда: St.Petersburg
Благодарил (а): 4 раз.
Поблагодарили: 72 раз.
Кстати, если Limit = 2<sup>n</sup>-1, то ограничение выхода за пределы делается простым AND с Limit, а старшие биты адреса могут быть использованы для неких иных целей, например, для указания типа адреса или переменной, хранящейся по этому адресу.

_________________
С уважением, WingLion
Forth-CPU . RuF09WE
Мой Форт
Отсутствие бана это не заслуга юзера, а недоработка модератора (с)


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Пн дек 08, 2008 09:11 
Не в сети

Зарегистрирован: Вт май 09, 2006 12:31
Сообщения: 3438
Благодарил (а): 5 раз.
Поблагодарили: 16 раз.
Цитата:
Изолировать опасные функции от плагина можно в отдельный словарь, который при сборке и работе плагина только и будет доступен. ... Изолировать пространство данных процесса тоже достаточно просто на первый взгляд: надо выделить память в хипе, необходимого размера (этот размер может задавать сам скрипт), и работать с этой памятью, как с именованным массивом, при этом обязательно контролировать выход за пределы массива (либо просто ограничивать адресуемую область).
вопрос безопасности прочно занял своё место в обсуждении 8) :)

_________________
понимаю некоторую бестолковость некоторых вопросов


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Пн дек 08, 2008 09:13 
Не в сети

Зарегистрирован: Вт май 09, 2006 12:31
Сообщения: 3438
Благодарил (а): 5 раз.
Поблагодарили: 16 раз.
WingLion писал(а):
Кстати, если Limit = 2<sup>n</sup>-1, то ограничение выхода за пределы делается простым AND с Limit, а старшие биты адреса могут быть использованы для неких иных целей, например, для указания типа адреса или переменной, хранящейся по этому адресу.

где-то я эту идею уже видел ...

_________________
понимаю некоторую бестолковость некоторых вопросов


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Пн дек 08, 2008 15:49 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 5012
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 21 раз.
Поблагодарили: 58 раз.
in4 писал(а):
mOleg писал(а):Четвертое: все интерфейсные слова необходимо стараться делать таким образом, чтобы они поглощали и возвращали значения, а не ссылки на них. То есть, надо учиться обходиться без реальных адресов.
не понял смысла. Можешь сказать более подробно?
"стараться делать" подразумевает необязательность действия, что не подходит в контексте твоего предложения.

смысл в отказе от реальных адресов и указателей. В простых случаях это возможно - то есть имена и метки можно, а адреса и ссылки нельзя.

in4 писал(а):
mOleg писал(а):Пятое: не желательно предоставление возможности подключения внешних динамических библиотек, потому что их невозможно контролировать. То есть скрипты должны рассчитывать только на возможности, предоставляемые базовой программой.Вроде это (или аналогичное) сказал в п.1. Может, предложить вообще запретить?
Но применение DLL в скриптах очень удобное расширение. Обсуждаемо.

да, не спорю, удобное. Но опасное. То есть, если ты хочешь, чтобы скрипты были безопасны, надо заранее предусмотреть все возможные DLL, и сделать для каждой функции обертку. Причем, всегда есть шанс, что кто-то сделает DLL с тем же именем и с теми же именами функций и сламает защиту. Так что dll в любом случае опасны.

WingLion писал(а):
Кстати, для ссылок можно пользоваться

спасибо, уже исправил.

WingLion писал(а):
Кстати, если Limit = 2n-1, то ограничение выхода за пределы делается простым AND с Limit, а старшие биты адреса могут быть использованы для неких иных целей, например, для указания типа адреса или переменной, хранящейся по этому адресу.

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

_________________
Мне бы только мой крошечный вклад внести,
За короткую жизнь сплести
Хотя бы ниточку шёлка.
fleur


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Скрипты и плагины в Форте
СообщениеДобавлено: Чт июл 09, 2009 19:33 
Не в сети

Зарегистрирован: Пт июн 23, 2006 14:05
Сообщения: 126
Благодарил (а): 1 раз.
Поблагодарили: 16 раз.
mOleg писал(а):
Так же не стоит забывать о том, что одновременное компилирование нескольких слов в память форт может не поддерживать, по крайней мере, в SPF этого делать нельзя даже во временные словари.

С рувимовым расширением storage.f - можно, уже несколько лет это используется на практике (в Eserv и др.).


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Чт июл 09, 2009 21:50 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 5012
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 21 раз.
Поблагодарили: 58 раз.
ac писал(а):
С рувимовым расширением storage.f - можно, уже несколько лет это используется на практике (в Eserv и др.).

это не является свойством ядра. когда будет в ядре расширение storage.f - можно будет говорить, что СПФ поддерживает многопоточную компиляцию.
(по крайней мере для меня такой критерий)

_________________
Мне бы только мой крошечный вклад внести,
За короткую жизнь сплести
Хотя бы ниточку шёлка.
fleur


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 9 ] 

Часовой пояс: UTC + 3 часа [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6


Вы не можете начинать темы
Вы можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
phpBB сборка от FladeX // Русская поддержка phpBB