Инженеры из компании Apple объявили о готовности для тестирования режима "-fbounds-safety" для компилятора Clang, предоставляющего гарантии безопасной работы с буферами в коде на языке Си. Режим включён в состав форка LLVM, поддерживаемого компанией Apple для проекта Swift. В дальнейшем запланирована постепенная передача функциональности "-fbounds-safety" в основную кодовую базу LLVM/Clang.

Отмечается, что предложенный механизм защиты уже активно применяется в продуктах Apple, таких как ядро XNU, прошивки, библиотеки для работы со звуком и декодировщики изображений. Включение режима "-fbounds-safety" снижает производительность приложений в среднем на 5% (разброс от -1% до 29%), увеличивает размер кода на 9.1% (разброс от -1.4% до 38%) и замедляет компиляцию на 11%.

Использование режима "-fbounds-safety" для автоматического выявления выхода за границы области памяти, связанной с указателем, требует добавления в код специальных аннотаций и включения заголовочного файла "ptrcheck.h". Суть предложенного метода защиты в автоматическом прикреплении проверок соблюдения допустимых границ, добавляемых на основе выставленных вручную аннотаций или известных компилятору размеров.

В отличие от использования в коде расширенных указателей (wide pointer), в которых кроме адреса имеются сведения о верхней и нижней границе буфера, использование режима "-fbounds-safety" не нарушает ABI (Application Binary Interface), не меняет формат экспортируемых указателей и не требует переработки сразу для всего проекта. В режиме "-fbounds-safety" расширенные указатели применяются только в областях, не пересекающихся с ABI, а для указателей, влияющих на ABI, применяются обычные указатели с подстановкой проверок, формируемых на основе аннотаций с информацией о границах.

Аннотации необходимо прикреплять к указателям в полях структур и параметрах функций, указывающих на массив объектов, а также к глобальным переменным с указателями. Для указателей в локальных переменных аннотации добавлять не нужно, так как они автоматически обрабатываются как расширенные указатели, уже включающие информацию о допустимых границах. Подсказки о конструкциях в коде, для которых требуется добавление аннотаций, выводятся компилятором при запуске с флагом "-fbounds-safety".

Модель защиты на основе "-fbounds-safety" можно внедрять постепенно, файл за файлом, не прерывая разработку всего проекта. Добавление защиты в проект сводится к указанию аннотаций в определённом файле с кодом, устранению предупреждений компилятора и проведению тестирования работы программы, после чего данные этапы повторяются для следующего файла. Код с добавленными аннотациями остаётся совместим с обычным Си-кодом и компиляторами, не поддерживающими "-fbounds-safety" (при сборке другими компиляторами или при сборке без флага "-fbounds-safety" просто не будут добавлены дополнительные проверки границ).

Во время работы программы, в случае выявления обращения за пределы допустимых границ, генерируется исключение и программа завершает своё выполнение. Аварийное завершение также может произойти при указании некорректных аннотаций, поэтому при использовании "-fbounds-safety" необходимо проведение дополнительного тестирования работы программы.

В примере ниже в параметр "int *p" вставлена аннотация "__counted_by(n)", добавляющая дополнительную проверку на допустимые границы, действующую во время выполнения. Если попытаться скомпилировать код в режиме "-fbounds-safety" без указания данной аннотации, компилятор выведет предупреждение об отсутствии информации о границах массива при обработке выражения "p[i] = 0".

#include <ptrcheck.h>void init_buf(int *__counted_by(n) p, int n) for (int i = 0; i < n; ++i)p[i] = 0; // в режиме “-fbounds-safety” компилятор сам подставит проверку, аналогичную коду "if (i < 0 | i >= n) trap();"

Для локальных переменных с указателями проверки прикрепляются автоматически, например:

void foo(int i)char *buf = (char *)malloc(10); // для указателя buf будут сохранены сведения о границахbuf[i] = 0xff; // будет автоматически подставлена проверка "if (buf + i < buf | buf + i >= buf + 10) trap();"

По возможности компилятор проводит оптимизацию и исключает добавление лишнего кода, если в коде уже имеются необходимые проверки. Например:

for (size_t i = 0; i < count; ++i) buf[i] = i; // проверка "if (i < 0 | i >= count) trap()" добавлена не будет, так как выше уже имеется условие “i < count” и i не может быть меньше 0.

Основные аннотации:

  • "__counted_by(N)" - определяет размер буфера в элементах целевого типа.
  • "__sized_by(N)" - определяет размер буфера в байтах.
  • " __ended_by(P)" - задаёт верхнюю границу буфера.
  • "__null_terminated" - учитывает нулевой символ в качестве конца буфера.
  • "__single" - привязывает указатель к одному объекту. Применяется по умолчанию для указателей, влияющих на ABI, если явно не выставлена аннотация.
  • "__bidi_indexable" - расширенный указатель с информацией о верхней и нижней границах. Применяется по умолчанию для указателей, не влияющих на ABI.
  • "__indexable" - расширенный указатель с информацией о верхней границе.
  • "__unsafe_indexable" - указатель без проверки границ (для переносимости с незащищённым кодом, например, для получения указателей из внешнего кода).
  • cocucka
    link
    fedilink
    arrow-up
    0
    ·
    1 year ago

    Я – Великий Кукурузо! А ты дырка от задницы.

    • MrSugomaOP
      link
      fedilink
      arrow-up
      0
      ·
      1 year ago

      Если ты не троллишь сейчас, то ты точно что-то забористое употребил.

      • cocucka
        link
        fedilink
        arrow-up
        0
        ·
        1 year ago

        Школьник, спок. Это классика, тебе не понять.

        • MrSugomaOP
          link
          fedilink
          arrow-up
          0
          ·
          1 year ago

          @crypt, а ты знал, что твоя свинья стала троллем и начала употреблять запрещенные вещества?

          • cocucka
            link
            fedilink
            arrow-up
            0
            ·
            1 year ago

            К мамке под юбку побежал?

            • MrSugomaOP
              link
              fedilink
              arrow-up
              0
              ·
              1 year ago

              @cocucka, я тебя в игнор кидаю.

              • Oberstserj
                link
                fedilink
                arrow-up
                0
                ·
                1 year ago

                Ой, и меня кинь, чо уж)

                Дебил малолетний)

                • MrSugomaOP
                  link
                  fedilink
                  arrow-up
                  0
                  ·
                  1 year ago

                  Ты меня еще не бесишь так сильно.

            • Anoxemian
              link
              fedilink
              arrow-up
              0
              ·
              1 year ago

              луууууул, пополнение @crypt прибыло

            • crypt
              link
              fedilink
              arrow-up
              0
              ·
              1 year ago

              слыш, свинья, ты чего малыша обижаешь?:) и вещества верни обратно на полку. @Kaschenko видать пакеты с мивиной перепутал.


              а кроме того, сосискин - мамкин пирожок и вахтер

          • crypt
            link
            fedilink
            arrow-up
            0
            ·
            1 year ago

            слыш, свинья, ты чего малыша обижаешь?:) и вещества верни обратно на полку. @Kaschenko видать пакеты с мивиной перепутал.


            а кроме того, сосискин - мамкин пирожок и вахтер

              • crypt
                link
                fedilink
                arrow-up
                0
                ·
                1 year ago

                а, да, спасибо.


                а кроме того, сосискин - мамкин пирожок и вахтер

            • MrSugomaOP
              link
              fedilink
              arrow-up
              0
              ·
              1 year ago

              слыш, свинья, ты чего малыша обижаешь?:)

              Толсто!

              • crypt
                link
                fedilink
                arrow-up
                0
                ·
                1 year ago

                а у меня толстая свинья!:)


                а кроме того, сосискин - мамкин пирожок и вахтер

      • Oberstserj
        link
        fedilink
        arrow-up
        0
        ·
        1 year ago

        Я не пойму, ты какого года рождения? 2010 штоле?

        • MrSugomaOP
          link
          fedilink
          arrow-up
          0
          ·
          1 year ago

          Зачем тебе знать? Знание года рождения — значительный этап на пути к деанону.

          • Oberstserj
            link
            fedilink
            arrow-up
            0
            ·
            1 year ago

            Знание года рождения — значительный этап на пути к деанону.

            Чувак, сдеанонить тебя не самая большая проблема, учитывая количество твоих проебов в одной только этой ветке))

            • MrSugomaOP
              link
              fedilink
              arrow-up
              0
              ·
              1 year ago

              учитывая количество твоих проебов в одной только этой ветке

              И что я в этой новости такого написал, что меня сдеанонят? В городском округе Истра живет больше 100 000 человек. Да и тем более, если меня сдеанонят, я не делаю ничего противозаконного, Россию люблю, в отличие от тебя.

              • Oberstserj
                link
                fedilink
                arrow-up
                0
                ·
                1 year ago

                Да и тем более, если меня сдеанонят, я не делаю ничего противозаконного, Россию люблю, в отличие от тебя.

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

                • MrSugomaOP
                  link
                  fedilink
                  arrow-up
                  0
                  ·
                  1 year ago

                  Бояться нечего, но и выкладывать себя сюда тоже не хочется.