LINUX.ORG.RU

Fil-C 0.682 — memory safety без переписывания

 , , , ,


1

2

Состоялся выпуск Fil-C 0.682 — компилятора C и C++, обеспечивающего полную безопасность работы с памятью (memory safety) и дающего гарантии бОльшие, чем многие другие языки, такие как, например, Rust. Проект разрабатывается Филипом Пизло (Filip Pizlo), который в представлениях не нуждается.

Fil-C основан на кодовой базе Clang/LLVM 20.x и позволяет компилировать традиционный код на C/C++ с гарантией предотвращения всех основных уязвимостей (out-of-bounds access, use-after-free, double free, type confusion). В отличие от ASan или MTE, Fil-C использует строго безопасную объектную модель и принципиально не содержит лазеек вроде блоков unsafe.

За прошедший год проект прошёл путь от концептуального доказательства возможностей до полноценного инструментария с масштабной экосистемой.

Основные особенности и технические детали:

  • InvisiCaps 2.0 и развитие модели Capability: Существенно переработана система полномочий (capabilities), отслеживающих границы и типы указателей без изменения их 64-битного размера в адресном пространстве C. Оптимизировано хранение capability, снижены накладные расходы, а также добавлена корректная поддержка union, memcpy, атомарных операций со структурами и передачи мандатов через инлайн-ассемблер.
  • Параллельный сборщик мусора (FUGC): В рантайм-сборщик мусора Fil’s Unbelievable Garbage Collector добавлены параллельная сборка, поддержка сложных объектов вроде замыканий и GNU Indirect Function.
  • Поддержка ARM64: Практически с нуля реализован бэкенд, рантайм, загрузчик и ABI для архитектуры ARM64 (Linux/aarch64), проект перешел в фазу бета-тестирования на этой платформе.
  • Безопасный инлайн-ассемблер и SIMD: Добавлена уникальная возможность выполнения безопасных ассемблерных вставок (включая ассемблерные блоки OpenSSL) с сохранением проверки полномочий. Реализована полная поддержка векторных инструкций SSE, AVX, AVX2 и AVX512 (включая masked load/store, expand/compress, sfence и prefetch).
  • Escape Analysis: Начиная с версии 0.671 внедрен статический анализ утечек памяти из областей стека. Это стало самым крупным оптимизационным изменением за год: скорость выполнения QuickJS выросла более чем в 6 раз, а большинства остальных программ — более чем на 10%.
  • Совместимость с C++ и современными стандартами: Реализована поддержка исключений C++, принудительного развертывания стека, ucontext, вычисляемых переходов, std::optional и указателей на члены классов.
  • Защита от опасных UB-оптимизаций LLVM: Fil-C фактически отключил агрессивные оптимизации LLVM, полагающиеся на Undefined Behavior (UB). В частности, принудительно отключен strict aliasing и включен аналог -fwrapv, что предотвращает некорректное удаление проверок безопасности компилятором.
  • Переход на LLVM/Clang 20: Компилятор переведен на кодовую базу Clang 20 (c версии Fil-C 0.670), что обеспечило лучшую совместимость и переносимость кодогенерации.
  • Расширение Linux ABI и FFI нового поколения: Реализована эмуляция и безопасные обертки для десятков системных вызовов Linux (statx, openat2, pidfd, epoll, splice, futex, timer API и др.), а также поддержка dlopen, dlvsym, libffi и FFI-слоя для взаимодействия с внешним кодом.
  • Новая конвенция вызовов и API рантайма: Оптимизирован внутренний ABI вызова функций для снижения оверхеда. Добавлены новые API, включая zlock_runtime_threads() (фиксация потоков для построения строгих песочниц), а также встроенный sampling profiler и инструменты дампов памяти.
  • Полноценный userspace-дистрибутив /opt/fil: безопасное системное окружение на базе glibc 2.40, включающее OpenSSH, OpenSSL, sudo, git, curl, wget, rsync, tmux, make, grep, а также системные библиотеки (PAM, Kerberos, SELinux, ICU).

Готовые бинарные сборки распространяются в двух вариантах: автономном на базе musl (filc) и полном системном окружении /opt/fil для архитектур x86_64 и ARM64.

GitHub проекта

Также отметим, что имеется и безопасный по памяти дистрибутив Linux — Pizlix

>>> Сайт проекта

★★★★

Проверено: hobbit ()
Последнее исправление: hobbit (всего исправлений: 2)

Вместо gcc/clang в обычных программах отработает? Ключи gcc понимает?
При нахождении ошибки(compile time/runtime) какие действия происходят?
P.S. это к Fil-C .

Atlant ★★★★★
()
Последнее исправление: Atlant (всего исправлений: 1)

> дающий гарантии бОльшие, чем многие дургие языки, такие как, например, Rust

Теперь будем гадать, опечатка ли это в слове «другие» или так и должно быть.

kaldeon ★★
()
Ответ на: комментарий от Atlant

Вместо gcc/clang в обычных программах отработает? Ключи gcc понимает?

Автор на гитхабе пишет что да, и вообще проект основан на clang. Будем посмотреть.

Ygor ★★★★★
()

Слоп

Подходи, честной народ! Налетай на свежий код!
Не скупись, скорей выбирай, в ОЗУ баги не пускай!
На прилавке два товара — для релиза и навара!

Слева — Раст, ядрёный овощ, программисту враз на помощь!
Долго зреет на прилавке, компилятор крутит гайки.
Мучит сборкой, как в аду? Зато баги — на виду!
А как вынесешь на волю — полетит стрелой по полю!
Шустрый, чистый, без греха — покупай для релиза-стиха!

Справа — Фил-Си, хитрый малый, жрёт Си-код, как волк бывалый!
Примет всё без лишних слов, без придирок и оков!
Налету скомплит базу, не поморщится ни разу!
Но в рантайме он — конвой, ходит следом за тобой.
Чуть косяк — наступит крах, бьёт паникой во пах!
Скорость рухнет на ходу, зато память вся в ряду!

Эй, сишник, не коси глазами, выбирай товар усами!
Что возьмёшь в свою корзину, чтоб спасти свою махину?
Стерпишь Борова нападки, что твой мозг имеет сборкой,
Или выберешь рантайм ты с его унылой поркой?
Налетай, выбирай!

gurujosh
()
Ответ на: комментарий от Atlant

fil-c - это фактически шланг с кастомным ABI и дополнительной стадией компиляции. Понимает все те же ключи что шланг, логи компиляции тоже те же самые. Проблемы могут возникнуть только в рантайме с софтом, который сериализует адреса указателей в какое-нибудь кастомное представление, типа строки, потом десериализует и пытается с ними работать - т.к. fil-c естественно не может отследить такие указатели и выкидывает ошибку.

При нахождении ошибки работы с памятью на уровне fil-c программа завершит свою работу.

Lrrr ★★★★★
()

инструментария с масштабной экосистемой

Чего, где?

переведен на кодовую базу Clang 20

Старьё. :)

dataman ★★★★★
()
Ответ на: комментарий от mister_me

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

hobbit ★★★★★
()

Fil-C — это не новый язык, а реализация C/C++ с гарантией безопасности памяти во время выполнения. Идея в том, чтобы взять существующий C-код и перекомпилировать его почти без изменений, но так, чтобы любые ошибки работы с памятью превращались в контролируемую ошибку (panic), а не в неопределённое поведение или возможность эксплуатации.

Если очень упрощённо, то схема такая:

C код │ clang (Fil-C) │ LLVM IR │ FilPizlonator (LLVM pass) │

  • проверки безопасности
  • преобразование указателей │ машинный код + runtime

Главное отличие от обычного Clang

Fil-C вставляет проверки во все потенциально опасные операции:

разыменование указателей;

арифметика указателей;

вызовы через function pointer;

malloc/free;

memcpy, memmove и т.д.

То есть вместо

*p = 5;

компилятор генерирует что-то похожее на

if (!pointer_is_valid(p)) panic();

if (!within_bounds(p)) panic();

*p = 5;

Хотя реальные проверки значительно сложнее.

InvisiCaps — «невидимые capability»

Самая интересная идея Fil-C — InvisiCaps.

Обычный C-указатель:

0x12345678

Логически превращается в

(pointer, capability)

где capability знает:

на какой объект указывает указатель;

где начинаются и заканчиваются допустимые границы;

жив ли объект;

можно ли писать;

является ли это вообще областью данных.

При этом capability не хранится прямо внутри указателя — отсюда название Invisible Capabilities. Runtime восстанавливает эту информацию при проверках.

Почему нужен GC

Fil-C использует точный конкурентный garbage collector (FUGC).

Причина неожиданная.

В обычном C:

free(ptr);

После этого где-то могут существовать ещё десятки копий ptr.

Fil-C должен гарантировать, что все они мгновенно станут недействительными.

С помощью GC runtime может сделать так, что любое последующее использование старого указателя вызовет panic вместо use-after-free.

Это не AddressSanitizer

AddressSanitizer:

используется в основном для отладки;

ловит многие ошибки только в протестированных путях;

не меняет семантику программы.

Fil-C:

меняет ABI;

вставляет проверки постоянно;

предназначен для запуска в production;

стремится сделать всю программу безопасной по памяти, а не только обнаруживать ошибки при тестировании.

Ограничения

Пока есть компромиссы:

производительность ниже обычного C;

требуется перекомпиляция библиотек под Fil-C (обычные бинарные библиотеки подключить нельзя);

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

Интересная особенность

В отличие от Rust, Fil-C не требует borrow checker, lifetimes или переписывания языка. Он пытается сохранить совместимость с существующим C-кодом, обеспечивая безопасность за счёт трансформации LLVM IR и runtime-проверок.

xor2003
()

Опустим то, что автор проекта очень странно понимает «memory safety». Основных минусов у проекта 2: 1) После его использования у программы появляется GC 2) Проект не работает ни на чем, кроме Linux и потому о портабельности на другие ОС можно забыть

X-Pilot ★★★★★
()

Самое главное не говорят что 4x просадка по производительности, это считай как с включеным санитайзером запускать, да безопасно но медленнее джавы исполняется.

pftBest ★★★★
()

Прекрасно, я щитаю. Лучше допиливать любимый Си\Си++ чем изобретать safe языки с вырвиглазным синтаксисом (как будто кто-то сел жёпой на весь верхний ряд кнопок на клавиатуре).

vvb333007
()
Ответ на: комментарий от unclestephen

Отнюдь. Была уже новость, что растаманы решили переписать Fil-C на Rust. Типа, безопаснее.

vvb333007
()
Ответ на: комментарий от xor2003

Если вы сделали free(), а у вас еще десять копий указателя - значит у вас неправильная модель ownership. Refcounter в конце-концов же можно в таких случаях использовать, если владелец и убивец объекта заранее неизвестны.

vvb333007
()

сборщик мусора

Скриптота!

goingUp ★★★★★
()

Проект разрабатывается Филипом Пизло (Filip Pizlo), который в представлениях не нуждается.

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

Adamos ★★★
()
Ответ на: комментарий от xor2003

Fil-C — это не новый язык, а реализация C/C++ с гарантией безопасности памяти во время выполнения.

Не катит. Весь смысл растового борова чекера в гарантиях в компайл тайме. Зис из зэ вей.

yvv1 ★★
()

Fil-C основан на кодовой базе Clang/LLVM 20.x и позволяет компилировать традиционный код на C/C++ с гарантией предотвращения всех основных уязвимостей

Не понимать, если в коде есть утечки то он не должен компилится, если утечек нет, то какая разница кто его компилит?

ya-betmen ★★★★★
()
Ответ на: комментарий от X-Pilot

Можно использовать Fil-C в девелопменте, а потом перекомпилировать обычным компилятором, типа релиз.

vvb333007
()
Ответ на: комментарий от vvb333007

Удобно, прямо как яваскрипт: если где-то затесался null или undefined, то будет запускаться и работать, пока не доберёшься до неожиданного значения. Но это не точно.

unC0Rr ★★★★★
()
Ответ на: комментарий от vvb333007

Так если ты уже забил на варнинги, чем поможет ещё один?

ya-betmen ★★★★★
()
Ответ на: комментарий от xor2003

Пока есть компромиссы:

производительность ниже обычного C;

Пока

А что, есть план, как избавиться от этих компромиссов?

unC0Rr ★★★★★
()

Проект разрабатывается Филипом Пизло (Filip Pizlo), который в представлениях не нуждается.

Ну конечно! Ведь он известен не менее, чем Наполеон Бонапарт, Александр Пушкин, Юрий Гагарин…

seiken ★★★★★
()
Ответ на: комментарий от pftBest

Самое главное не говорят что 4x просадка по производительности, это считай как с включеным санитайзером запускать, да безопасно но медленнее джавы исполняется.

Для разработки и отладки думаю неплох и такой вариант. А в релиз - нафиг нафиг!

Atlant ★★★★★
()
Ответ на: комментарий от pftBest

А написано, что

скорость выполнения QuickJS выросла более чем в 6 раз,

ya-betmen ★★★★★
()
Ответ на: комментарий от Atlant

Все внешние библиотеки под его ABI как бы пересобирать не пришлось... А то ведь как, накосячил ты в своем коде, а падает библиотека...

gns ★★★★★
()
Ответ на: комментарий от Adamos

Авторитетом хотят задавить. В представлении, мол, не нуждается, но мы все равно его представим.

sklprogs
()

А если у меня код где попиксельно одна картинка в другую копируется и так 50 раз в секунду и размер картинки дветыщи_на_тыщу и он при копировании каждого пикселя будет проверять не вышел ли я за границы массива? Звучит как будто тут мне нужен ансейв :)

pihter ★★★★★
()
Ответ на: комментарий от xor2003

Так, пажжите, я правильно понял, что Fil-C нифига не ищет ошибки работы с памятью, просто раскладывает вокруг них обёртки, чтобы их нельзя было заэксплуатировать. Если в программе есть use-after-free, то она всё равно скомпилируется, просто безопасно упадёт во время исполнения. В отличие от Rust’ишки, где боров обнаружит ошибку на этапе компиляции. Так?

Camel ★★★★★
()
Ответ на: комментарий от Camel

Да. Смысл Fil-C — реализация Си без UB.

В отличие от Rust’ишки, где боров обнаружит ошибку на этапе компиляции.

Или то, что ему кажется ошибкой. И тогда приходится писать unsafe.

monk ★★★★★
()
Ответ на: комментарий от monk

Или то, что ему кажется ошибкой. И тогда приходится писать unsafe.

Так была ж новость, что в свежей Растишке более другой боров (или какая-то его важная часть), который позволяет обойти некоторые ложные возбуждения старого борова.

Camel ★★★★★
()
Ответ на: комментарий от monk

Fil-C — реализация Си без UB

Ещё один вопрос, ответа на который я не смог получить в треде (не утверждаю, однако, что ответа нет, просто я не сумел его правильно прочитать). Если в коде есть ошибка работы с памятью, то Fil-C при компиляции выдаст ли по этому поводу какое-то сообщение? Или он только лишь гарантирует мягкое падение когда до ошибки дойдёт исполнение?

Другими словами, Fil-C находит ошибки на этапе компиляции, или только лишь делает их безопасными на этапе исполнения? Такое чувство, что второй вариант. Если бы первый вариант был возможен, то сейчас все сишные проекты использовали бы сборку Fil-C для поиска ошибок. В этом случае Fil-C превратился бы в анализатор, но это компилятор, и скомпилированные программы нужно запускать чтобы ловить баги.

Camel ★★★★★
()
Ответ на: комментарий от xor2003

Всё равно новые проекты будут писать на Rust. Ну не на этом же проект начинать? Значит проектов с Си будет становиться меньше, и в итоге Си выведут из эксплуатации (а ядро Linux всё на Rust перепишут).

Saakx
()
Ответ на: комментарий от Camel

Если в коде есть ошибка работы с памятью, то Fil-C при компиляции выдаст ли по этому поводу какое-то сообщение? Или он только лишь гарантирует мягкое падение когда до ошибки дойдёт исполнение?

Если код гарантировано имеет ошибку, то выведет. Если нет, то нет. Но gcc и clang в таком случае тоже предупреждение пишут. У Fil-C анализатор вроде чуть лучше.

Другими словами, Fil-C находит ошибки на этапе компиляции, или только лишь делает их безопасными на этапе исполнения?

Язык Си не позволяет определить, есть ли ошибки на этапе компиляции. Вызов strcpy, например, является ошибкой?

monk ★★★★★
()
Ответ на: комментарий от monk

Теоретически возможен анализ кода и вынос проверки всего диапазона перед картинкой.

Теоритически-то понятно что возможно, но в сабже - сомневаюсь. Надо пробовать

pihter ★★★★★
()
Ответ на: комментарий от Saakx

Значит проектов с Си будет становиться меньше, и в итоге Си выведут из эксплуатации

Водород в звёздах тоже потихоньку кончается и да, потихоньку звезды выйдут из эксплуатации, но мы до этого не доживём :)

pihter ★★★★★
()
Ответ на: комментарий от monk

Язык Си не позволяет определить, есть ли ошибки на этапе компиляции

int a = 10;
int* p = &a;
free(p);
free(p);
*p = 20;

Upd: malloc конечно же :)

pihter ★★★★★
()
Последнее исправление: pihter (всего исправлений: 1)
Ответ на: комментарий от pihter

Такое и gcc умеет:

$ gcc -fanalyzer test.c
test.c: In function ‘test’:
test.c:7:9: warning: double-‘free’ of ‘p’ [CWE-415] [-Wanalyzer-double-free]
    7 |         free(p);
      |         ^~~~~~~
  ‘test’: events 1-2
    6 |         free(p);
      |         ^~~~~~~
      |         |
      |         (1) first ‘free’ here
    7 |         free(p);
      |         ~~~~~~~
      |         |
      |         (2) ⚠️  second ‘free’ here; first ‘free’ was at (1)

monk ★★★★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.