Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Страница 1 из 2 1 2 ПоследняяПоследняя
Показано с 1 по 10 из 11

Тема: Pawn 3.2 (+)

  1. #1
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±

    Pawn 3.2 (+)

    Основная цель данного проекта - создание улучшенной версии Pawn 3.2 с исправлениями и нововведениями как для компилятора, так и для библиотеки времени выполнения.

    Кодовая база проекта базируется на форке Zeex'а (Pawn 3.10), направленном на исправление багов и улучшение компилятора для SA-MP.
    Данный проект, напротив, сфокусирован на улучшении интерпретатора и модулей расширения AMX - часть изменений перенесена из более поздних версий Pawn (такие как, например, добавление функций frename(), fstat() и strcopy()), другая часть является оригинальной разработкой (верификация байткода при загрузке скрипта, модернизированное ядро интерпретатора).

    Список изменений:
    • Бэкпортированы изменения из Pawn 3.3 и дальнейших предрелизных версий, вплоть до 4.0.
      Среди перенесённых изменений можно отметить добавление новых нативных функций в модулях amxfile (frename, fstat, fattrib и filecrc), amxtime (settimestamp() и cvttimestamp()) и amxstring (strcopy).
      Кроме новых функций есть исправления для уже существующих - valstr (устранён уход в бесконечный цикл при больших числах), printf (исправлена неправильная обработка комбинации "%%").
      Перенести изменений из 4.0 и более поздних версий не представляется возможным, т.к. это повлечёт нарушение авторских прав - начиная с 4-й версии, основная часть кода Pawn была переведена под новую лицензию.

    • В корневой папке репозитория добавлен проект для CMake, служащий для построения и компилятора, и интерпретатора.
      Также в скрипт для построения рантайма (в папке "source/amx") добавлены опции для построения с 32/64-битными ячейками, компиляции модулей расширения в виде статический библиотек (может пригодиться для встраивания модулей в исполняемый файл пользовательского приложения, как в сервере SA-MP), и включения/исключения отдельных модулей из билда.

    • Добавлено новое ядро интерпретатора (amx_Exec), основанное на двух других стандартных ядрах: обычном (ANSI C) и GCC-специфичном.
      Этот шаг должен значительно упростить поддержку кода - сопровождать одну версию ядра куда проще, чем две и более.
      Также в новое ядро добавлены новые проверки времени выполнения, исключающие множество недочётов и уязвимостей, присутствующих в оригинальном коде.
      Например, в оригинале во многих опкодах, совершающих чтение или запись в секцию данных или стек, отсутствует проверка адреса доступа, благодаря чему атакующий может читать и записывать данные за пределами памяти скрипта.
      Кроме того, у всех опкодов, изменяющих состояние стека, кроме опкода STACK, отсутствует проверка значение в регистре STK (указателе вершины стека) - можно с помощью SCTRL 4 заставить STK указывать за пределы памяти скрипта и выполнять чтение/запись данных с помощью опкодов PUSH*/POP*.
      В новом ядре эти и многие другие виды уязвимостей устранены. Тем не менее, для совместимости оставлена возможность использования старых ядер, для этого следует отключить опцию PAWN_USE_NEW_AMXEXEC в проекте для CMake.

      Кроме того, в новом ядре изменён принцип считывания аргументов в опкодах, интерпретатор избавлен от последовательного чтения. В оригинале чтобы считать 2-й аргумент, нужно сначала прочитать 1-й, а чтобы перейти к следующему опкоду, нужно считать все аргументы текущего опкода. Теперь же интерпретатор может считывать аргументы не по порядку и при возможности вообще пропускать их. Например, в инструкциях jump и j** интерпретатор не будет считывать адрес перехода, если условие перехода не выполняется. Кроме того, интерпретатор теперь может считывать два аргумента не друг за другом, а одновременно (при условии, что операции чтения из памяти распараллеливаются на целевом процессоре).
      Сам процесс считывания аргумента теперь не модифицирует значение в регистре cip, поэтому в случае возникновения ошибки интерпретатор сможет выдать адрес именно инструкции, на которой возникла ошибка, а не адрес одного из аргументов инструкции (или даже следующей инструкции, если у текущей аргументов нет), как в оригинале.

      Несмотря на добавление новых проверок времени выполнения, новое ядро обладает большей производительностью, чем у стандартных ядер.
      Достигнуто это благодаря упрощению кода (см. пример выше с устранением последовательности чтения) и использованию нестандартных возможностей компиляторов C/C++ для статического предсказания переходов (__assume(0) в MSVC++, а также __builtin_unreachable() и __builtin_expect() в GCC и Clang).
      На моём ПК прирост производительности при построении в VS 2010 составил 23%, VS 2017 - 75%, MinGW - 90%. Я также пробовал провести измерения на своём планшете (ARMv8) - на нём разница оказалась не сильно заметна: +10% при компиляции с GCC и -15% с Clang.
      Если вы хотите проверить факт прироста производительности самостоятельно, постройте два экземпляра интерпретатора, с включенной и выключенной опцией PAWN_USE_NEW_AMXEXEC соответственно, затем скомпилируйте скрипт fib_bench.p (находится в папке "examples") и запустите его на каждом из них.

    • Помимо проверок времени выполнения добавлена верификация байткода при загрузке скрипта (в amx_Init).

    • Устранена зависимость размера ячейки Pawn от размера указателя на целевой платформе.
      Теперь можно использовать интерпретатор с 32-битными ячейками под управлением 64-разрядной ОС.
      В оригинальной версии Pawn при такой конфигурации работа интерпретатора невозможна, т.к. физические адреса нативных функций и хендлов модулей расширения AMX хранятся в ячейках, а размера ячейки (32 бита) с большой долей вероятности может не хватить для хранения 64-битного указателя.
      В данном форке если размер указателя больше размера ячейки, то под физические адреса (указатели) выделяется отдельный блок памяти, в котором они помещаются полностью.

    • Файловые функции теперь оперируют над ID файлов (например, 1, 2, 3, ...) вместо указателей FILE *, приведённых к типу ячейки.
      Это означает, что файловые функции не обрушат целое хост-приложение из-за нечаянного использования неправильного ID файла (привет, SA-MP) (например, при вызове функции fwrite() после закрытия файла с помощью fclose()), т.к. ID легко проверить на валидность.

    • В инструкциях доступа к секциям данных, в которых адрес доступа указывается в виде константы (LOAD.pri/alt, LREF.pri/alt, STOR.pri/alt и т.д.), реализована релокация адресов.
      Теперь при загрузке скрипта виртуальные адреса в вышеупомянутых инструкциях заменяются физическими адресами для прямого доступа к данным, что должно повысить общую производительность. Релокация осуществляется только при использовании нового ядра интерпретатора (см. выше) и только если ячейка Pawn способна вместить физический адрес.



    Исходный код: https://github.com/Daniel-Cortez/pawn-3.2-plus
    Статью подготовил: Daniel_Cortez

    Специально для Pro-Pawn.ru
    Запрещается копирование содержимого данной статьи на других ресурсах без разрешения автора.
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  2. 13 пользователя(ей) сказали cпасибо:
    $continue$ (28.07.2017) 0x452 (02.04.2018) DeimoS (28.10.2017) Desulaid (29.07.2017) Nurick (06.08.2017) Osetin (29.07.2017) Outsider (02.11.2017) Seregamil (31.07.2017) SooBad (03.04.2018) Sp1ke (28.07.2017) vovandolg (06.11.2017) VVWVV (28.07.2017) Web (29.07.2017)
  3. #2
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Обновление от 05.08.2017:
    • Удалена лишняя проверка времени выполнения в обработчике инструкции PUSH (адрес для чтения данных является постоянным и проверяется при загрузке скрипта).
    • В инструкциях доступа к секциям данных, в которых адрес доступа указывается в виде константы (LOAD.pri/alt, LREF.pri/alt, STOR.pri/alt и т.д.), реализована релокация адресов. Теперь при загрузке скрипта виртуальные адреса в вышеупомянутых инструкциях заменяются физическими адресами для прямого доступа к данным, что должно повысить общую производительность.
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  4. #3
    Аватар для OLDBOY
    Пользователь

    Статус
    Оффлайн
    Регистрация
    18.06.2017
    Сообщений
    11
    Репутация:
    0 ±
    А не подскажете как пользоваться вашим компилятором. Я что-то понять не могу, перешёл на github что мне надо скачать оттуда, как заменить стандартный компилятор на ваШ?

  5. #4
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Цитата Сообщение от OLDBOY Посмотреть сообщение
    А не подскажете как пользоваться вашим компилятором. Я что-то понять не могу, перешёл на github что мне надо скачать оттуда, как заменить стандартный компилятор на ваШ?
    *facepalm*
    Цитата Сообщение от Daniel_Cortez Посмотреть сообщение
    Данный проект, напротив, сфокусирован на улучшении интерпретатора и модулей расширения AMX
    TL;DR: Это не "компилятор".
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  6. #5
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Обновление от 27.10.2017:
    • Кодовая база синхронизирована с компилятором от Zeex версии 3.10.3.
    • Убрана генерация архива с компилятором с помощью CPack, т.к. данный форк сфокусирован на развитии не только компилятора, но и рантайма.
    • Серия правок в реализации оператора emit/__emit (чистка кода, исправлена неправильная установка старшего бита на числах типа Float при 64-битном размере ячейки).
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  7. 2 пользователя(ей) сказали cпасибо:
    koberman (28.10.2017) Web (28.10.2017)
  8. #6
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Обновление от 31.10.2017:
    • Кодовая база синхронизирована с форком Zeex.
      • Приняты изменения, направленные на улучшение скорости работы компилятора.
      • Исправлена проблема с исчезновением пробелов, возникавшая при переносе строк с помощью обратного слеша.


    • Серия изменений для оператора emit/__emit.
      • Исправлена неправильная генерация отрицательных чисел типа Float при размере ячейки в 64 бита (установка старшего бита работала правильно только при 32-битном размере ячейки).
      • Убрано излишнее копирование названия инструкции AMX (функция emit_findopcode()).
      • Использован чувствительный к регистру поиск имени инструкции (emit_findopcode()).


    • Исправлена сборка под Visual Studio 2010.

    • Также принята ещё одна порция изменений, направленных на повышение скорости записи файла *.amx.
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  9. #7
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Состояние на 04.03.2018:
    • В модуль amxFloat добавлена функция floatint() из Pawn 4. Также добавлена перегрузка оператора "=" для автоматического преобразования вещественных чисел в целые, которой в Pawn 4 нет.
      1. native Float:floatint(Float:value);
      2. native operator=(Float:oper) = floatint;

      Что интересно, на самом деле аналогичная перегрузка "=" задумывалась к добавлению и в 4-й версии (судя по комментарию в коде), но по какой-то причине этого сделано не было. Кроме того, сама функция floatint() реализована в amxfloat.c, но в float.inc нет заголовка этой функции (т.е. в Pawn 4.0 она никак не используется).

    • В модуль amxFile добавлены функции fcopy() и fcreatedir() для копирования файлов и создания новых папок соответственно.
      Поскольку изначально данные функции были реализованы в Pawn 4.0, после смены лицензии на код, для 3.2 их пришлось делать заново.
      Новая реализация fcopy() не настолько проста, как оригинал в 4.0, но зато она не подвержена атаке по принципу инъекции кода (в оригинале из Pawn 4 для копирования вызывается команда "cp <файл-источник> <файл-назначение>", однако имена файлов не экранируются, в результате чего в вызываемую команду можно подставить вредоносный код).
      1. native bool: fcopy(const source[], const target[]);
      2. native bool: fcreatedir(const name[]);


    • Функция fremove() наделена способностью удалять не только файлы, но и папки (логичный шаг после добавления функции для создания папок).

    • Исправлены баги в функции strins().
      • Функция была склонна к переполнению буфера, поскольку не учитывала размер массива под результирующую строку (параметр "maxlen").
      • В некоторых случаях функция не завершала строку нуль-символом (возможно, она полагалась на то, что массив под результирующую строку уже проинициализирован нулевыми значениями, что не совсем правильно).

      Также добавлен тестовый скрипт для проверки работы обновлённой реализации strins().
      Интересный факт: оригинальная реализация strins() из Pawn 4.0 build 5514 (если адаптировать её к Pawn 3.2 путём замены вызовов amx_Address на amx_GetAddr), в которой также были предприняты меры по устранению переполнения буфера, всё ещё заваливает 9 из 23 тестовых кейсов из упомянутого скрипта - строки либо не завершаются нуль-символом, либо этот нуль-символ добавляется уже за пределами массива (т.е. выход за пределы буфера в 4.0 так и не устранён до конца).

    • Исправлен баг в функции fputchar().
      Функция возвращала неправильные значения при параметре "utf8" равном "true".

    • Для конструкции switch реализован опциональный бинарный поиск среди значений case (активируется, когда в таблице более 30 значений, при меньшем количестве используется простой линейный поиск).


    В ближайшее время планируется сделать исправления для некоторых уязвимостей из оригинала (3.2) опциональными для совместимости с кодом для SA-MP (к примеру, для таких библиотек как YSI и amx_assembly).
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  10. 3 пользователя(ей) сказали cпасибо:
    DeimoS (06.03.2018) Web (06.03.2018) ziggi (04.03.2018)
  11. #8
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Состояние на 31.03.2018:
    • Бэкпортированы функции для работы с файлами конфигурации ("*.cfg", "*.ini").
      1. native readcfg(const filename[]="", const section[]="", const key[], value[], size=sizeof value, const defvalue[]="", bool: pack=false);
      2. native readcfgvalue(const filename[]="", const section[]="", const key[], defvalue=0);
      3. native bool: writecfg(const filename[]="", const section[]="", const key[], const value[]);
      4. native bool: writecfgvalue(const filename[]="", const section[]="", const key[], value);
      5. native bool: deletecfg(const filename[]="", const section[]="", const key[]="");

    • Теперь файловые функции (fopen(), fclose(), fwrite(), fread(), ...) оперируют идентификаторами файлов (1, 2, ...), а не приводят указатель на файловый объект (FILE *) к типу ячейки Pawn и наоборот.
      Недостаток предыдущего подхода с приведением типов был в том, что указатель не на всех платформах и конфигурациях может вместиться в ячейку (например, если собрать интерпретатор с 32-битными ячейками под 64-разрядную архитектуру, часть указателя при попытке уместить его в ячейку окажется "урезанной"). Кроме того, при прежнем подходе на некоторых платформах (в т.ч. и на Windows) файловые функции из стандартной библиотеки C не проверяли указатель на файловый объект, из-за чего было возможно падение интерпретатора при передаче неправильного указателя.
      Таким образом, в рантайме устранена последняя зависимость размера ячейки от размера указателя.

    • Проведён рефакторинг кода нативных функций, теперь неудачное резервирование пространства в стеке с помощью функции alloca() и неправильные виртуальные адреса, передаваемые в нативные функции (посредством #emit или каким-либо другим способом) воспринимаются.
      В стоковом Pawn 3.2 (да и Pawn 4 до сих пор) ошибки подобного типа не отлавливаются и могут привести к падению интерпретатора из-за разыменования нулевого указателя.

    • Также в нативных функциях была добавлена верификация размера буфера, чтобы исключить возможность записи за пределами памяти скрипта.

    • Исправлен баг в функции ispacked(): функция могла вернуть неправильное значение (0), если в первой ячейке упакованной строки самый старший бит установлен в 1 (например, с символами кириллицы).
      Пример:
      1. static const packed_str[] = !"абвг";
      2. printf("ispacked(): %d\n", ispacked(packed_str)); // "ispacked(): 0"

    • Исправлен баг в функции strfind(): функция не проверяла позицию начала поиска, и если эта позиция была отрицательной - искала указанную подстроку в данных перед началом строки.
      1. static const str1[] = "1234567890";
      2. static const str2[] = "abcdefghij";
      3. #pragma unused str1
      4. new result = strfind(str2, "5", false, -10);
      5. printf("result: %d", result); // "result: -7"

    • В заголовке функции getchar() (файл console.inc) перед параметром "echo" добавлен недостающий тег "bool".
      Данный недочёт был найден при сравнении заголовков функций в console.inc с комментариями в нативных функциях из amxconsole.c.
      Заголовок getchar() в console.inc (перед исправлением):
      1. native getchar(echo=true);

      Комментарий перед реализацией getchar() в amxconsole.c:
      1. /* getchar(bool:echo=true) */

      Заголовок getchar() после исправления:
      1. native getchar(bool:echo=true);

      Аналогичным образом в заголовке fstat() (amxfile.inc) добавлен недостающий квалификатор "const" перед параметром "name".
      До:
      1. native bool: fstat(name[], &size = 0, &timestamp = 0, &mode = 0, &inode = 0);

      После:
      1. native bool: fstat(const name[], &size = 0, &timestamp = 0, &mode = 0, &inode = 0);
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  12. 5 пользователя(ей) сказали cпасибо:
    0x452 (11.05.2018) DeimoS (31.03.2018) Desulaid (08.04.2018) Osetin (31.03.2018) VVWVV (31.03.2018)
  13. #9
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Состояние на 09.09.2018:
    • Компилятор обновлён до версии 3.10.8.

    • Бэкпортированы функции urlencode() и urldecode().
      1. native urlencode(dest[], const source[], maxlength=sizeof dest, bool:pack=false);
      2. native urldecode(dest[], const source[], maxlength=sizeof dest, bool:pack=false);
      Функции были доступны ещё в Pawn 3.3, но по неизвестной причине не были объявлены в string.inc.

    • Добавлен форматный спецификатор "%b" для функций printf() и strformat().
      1. printf("%b", 23); // Вывод: "10111"

    • Исправлен баг с выводом cellmin в strformat(), printf() и valstr():
      1. printf("%d", cellmin); // До исправления: "-(", после: "-2147483648"

    • Исправлен баг в функциях getarg() и setarg(): если индекс аргумента был отрицательным, функции всё ещё считали его правильным.

    • Исправлена неправильная работа функции uuencode().

    • Теперь при выгрузке скрипта интерпретатор удаляет не все свойства ("properties", создаются с помощью функции setproperty()), а только те, которые были созданы выгруженным скриптом.

    • Добавлена дополнительная валидация заголовка AMX и проверка адресов переменных и функций с атрибутом public при загрузке скрипта.
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  14. 5 пользователя(ей) сказали cпасибо:
    DeimoS (13.09.2018) Desulaid (11.09.2018) Osetin (11.09.2018) Seregamil (10.09.2018) VVWVV (09.09.2018)
  15. #10
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Состояние на 13.04.2019:
    • Компилятор обновлён до версии 3.10.9.

    • В модуле amxFloat добавлены обратные тригонометрические функции:
      1. native Float:floatasin(Float:value, anglemode:mode=radian);
      2. native Float:floatacos(Float:value, anglemode:mode=radian);
      3. native Float:floatatan(Float:value, anglemode:mode=radian);
      4. native Float:floatatan2(Float:y, Float:x, anglemode:mode=radian);

    • Исправлен баг в функции 'fwrite()', из-за которого в файл не записывался последний символ, если строка упакована.

    • Реализована защита от перекрытия кода.
      С помощью инструкций перехода 'jump.pri', 'sctrl 6' или 'jrel' можно было заставить интерпретатор "перепрыгнуть" через следующий опкод, чтобы он принял за опкод один из аргументов инструкции и попытался выполнить его.
      Пример:
      1. emit jrel (cellbits / charbits); // "перепрыгнуть" через одну ячейку (опкод 'push2.c')
      2. emit push2.c 12 1; // '12 1' ошибочно интерпретируется как 'const.alt 1'

      Опасность данной техники заключалась в том, что она позволяла выполнять "замаскированные" инструкции в обход всех статических проверок при загрузке скрипта, тем самым заново открывая возможность для эксплуатации многих исправленных ранее уязвимостей (чтение/запись данных за пределы скриптовой песочницы, выполнение нативного кода и т.д.)

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

    • Исправлено ложное срабатывание проверок безопасности в инструкциях 'push*', 'lref.pri/alt', 'sref.pri/alt', 'lref.s.pri/alt', 'sref.s.pri/alt'.

    • Исправлен неправильный вывод cellmin (-2147483648) в функциях 'printf()', 'strformat()' и 'valstr()' (проблема не проявлялась только под Windows).

    • Исправлено потенциальное состояние гонки в функции 'valstr()'.
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

 

 
Страница 1 из 2 1 2 ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 2 (пользователей: 0 , гостей: 2)

Ваши права

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