LINUX.ORG.RU

Kaitai Struct 0.5

 , , ,


7

5

После трёх месяцев разработки состоялся релиз Kaitai Struct 0.5 — языка описания форматов структур данных. Идея проекта состоит в том, что описав структуру формата файла или сетевого протокола единожды на формальном языке .ksy, можно скомплировать такое описание в исходный код парсера на любом поддерживаемом языке программирования.

Список нововведений внушительный, самые заметные из них:

  • полная поддержка C++/STL;
  • поддержка новых целевых языков PHP7 (благодаря ProtoH) и Perl;
  • генерация GraphViz-диаграмм для форматов (ранние примеры демонстрировались в галерее);
  • новые возможности языка: switch-подобная конструкция для типов (чтобы не писать много условий), атрибут doc (для генерации документации в комментариях на целевом языке), цикл repeat-until, поддержка булевых типов, поддержка операций с объектом потока из языка выражений (_io.eof, _io.size, _io.pos);
  • существенное улучшение строгости парсинга .ksy компилятором, понятные сообщения об ошибках;
  • работа консольного визуализатора на Windows.

Семейство инструментов, поддерживающих Kaitai Struct, пополнилось:

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

>>> Подробности

★★

Проверено: Falcon-peregrinus ()
Последнее исправление: sudopacman (всего исправлений: 1)
Ответ на: комментарий от GreyCat

Ну всё, что Gtk - glib уже есть. Qt тоже что-то от glib берёт. Консольные утилиты? Демоны? Тут не берусь судить, но судя по данным apt зависящих от glib немало:

$ apt rdepends libglib2.0-0 | grep -v glib | sort | uniq | wc -l
3050

а всего у меня пакетов поставлено 4707.

Выборка, конечно, так себе, но каждый проверить может.

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

Вообще, если опускаться до теории, все давно уже придумали до нас: Тьюринг, Мили, Мур и все такое. Уже много раз показано, как выглядит теоретически минимальная машина, умеющая делать любое преобразование, т.е. парсить «произвольный формат». Я это все вполне себе представляю и делать очередной брейнфак мне на самом деле не очень интересно.

Повторюсь, меня интересует несколько другая, хотя и во многом похожая задача: для 90-95% встречающихся на практике бинарных форматов ввести какую-то систему примитивов, которая бы их хорошо представляла и давала связующий мостик между представлением в памяти и на диске. И, как мне кажется, у меня это более-менее получается.

Круг плохо решаемых на данный момент задач (а не неких теоретических «файловая система, в которой будет какая-то структура со сложной математикой») мне в целом понятен - они все более-менее описаны у нас на гитхабе в issues. В частности, это:

  • штуки с подглядыванием предыдущих state'ов (как в MIDI running status),
  • variable-length integers,
  • unaligned bit parsing,
  • alignment'ы (хотя как раз с KS 0.5 они теперь точно *возможны*, хотя и весьма неудобно - через `_io.pos % alignment`)
  • всевозможные распространенные алгоритмы криптографии (шифрование, хэширование)
  • переключаемый на лету endianness с переиспользованием одного и того же кода
GreyCat ★★
() автор топика
Ответ на: комментарий от h4tr3d

Все, что будет на Qt, будет скорее всего хотеть использовать отдельную C++ реализацию, но не на STL, а на Qt core. Когда-нибудь у нас, надеюсь, будет «cpp_qt», кроме «cpp_stl».

Потыкайте лучше прямо руками какую-нибудь выборку из тех, кто (1) написан на C, (2) как-то связан с парсингом каких-либо нетривиальных бинарных форматов. Что это будут за программы?

GreyCat ★★
() автор топика

В отсутствие С - не нужно совсем.

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

Не хватает базовых типов данных

glibc тоже не хватит?

строки или растущие массивы

А если у меня протокол не использует строки и массивы всегда вида TLV? Неполная поддержка С лучше, чем вообще никакой.

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

CSN.1 я видел - это что-то весьма мертворожденное

К сожалению нет. В идеале хотелось бы что-нибудь, что позволило бы быстро-быстро переделать описание в CSN.1 в .ksy - это вообще возможно? Аналогично по поводу ASN.1 - не планируется конвертор в .ksy?

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

а не неких теоретических «файловая система, в которой будет какая-то структура со сложной математикой»

Это не теоретическая проблема, а вполне реальная: https://en.wikipedia.org/wiki/HTree https://web.archive.org/web/20071024001500/http://www.namesys.com/v4/v4.html#...

SZT ★★★★★
()

Интересно бы поковырять. Советую добавить инструкции по сборке всех тулзов для тех, кто обделён знакомством с джавой или системой сборки проекта

jeuta ★★★★
()

Генератор диссекторов для wireshark уже спрашивали? Если не спрашивали, то спрошу. Можете оценить трудоёмкость?

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

glibc тоже не хватит?

0. точно glibc, а не glib? 1. glibc у нас есть, например, на Android или Windows? 2. glibc у нас внезапно реализует какие-то типы данных? насколько я помню, там все как раз по хардкору через char* и void*

Неполная поддержка С лучше, чем вообще никакой.

«Хотя какая-то» поддержка C и так фактически есть - пожалуйста, собирай с C++/STL, линкуйся с libstdc++ и вызывай _ZN20foo_tC1EPN6kaitai7kstreamEPNS0_7kstructEPS_ - никто не запрещает.

Бросаться делать «неполную» поддержку смысла, не продумав до конца основные концептуальные вопросы - бессмысленно. Ну, будет оно, может быть, проходить 2-3 теста из наших текущих 57. Для того, чтобы проходило остальные, надо все-таки все продумать, а потом выкинуть то, что есть и переписать все в новой парадигме.

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

Советую добавить инструкции по сборке всех тулзов для тех, кто обделён знакомством с джавой или системой сборки проекта

Инструкции вполне есть. Знакомство с джавой, кстати, относительно перпендикулярно и вряд ли радикально поможет.

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

В идеале хотелось бы что-нибудь, что позволило бы быстро-быстро переделать описание в CSN.1 в .ksy - это вообще возможно?

Теоретически я проблем никаких не вижу, CSN.1 - относительно простой формат.

Практически оно, во-первых, упирается в то, что CSN.1 по умолчанию работает с unaligned bits (поддержки которых в KS пока нет), во-вторых, меня придется сильно поубеждать, что это дико актуально и полезно, потому что я в реальной жизни ни разу с CSN.1 не сталкивался. Единственная библиотека каких-то древних коммуникационных форматов, которая была якобы в нем специфицирована, которую я видел, имела рабочую версию с C structs. Проще уж тогда из них конвертировать.

Аналогично по поводу ASN.1 - не планируется конвертор в .ksy?

Если вы имеете в виду BER/DER - нет, не планируется, а зачем? Они прекрасно читаются и без формата.

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

Генератор диссекторов для wireshark уже спрашивали? Если не спрашивали, то спрошу. Можете оценить трудоёмкость?

Могу. Реализация на lua API, скорее всего, займет примерно как реализация поддержки среднестатистического языка - 1-2-3 недели плотной работы по вечерам. Реализация на native C API - видимо, подольше.

Есть желание сделать это вместе?

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

Спасибо за ответ. Если для вас трудозатраты в 1-2-3 недели, то мне потребуется несколько месяцев. Думал, что задача проще и можно получить крутой инструмент для анализа непонятных протоколов. Сейчас столько времени выделить не могу. Буду делать диссекторы руками.

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

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

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

К огромному сожалению, у меня есть только потребность в анализе множества плохо документированных самодельных протоколов. Представления о диссекторах тоже нет. Но придётся разбираться. Вполне возможно, что попробую решить эту задачку с помощью вашего проекта, но обещать своё участие будет нечестно. Тем более, что и scala, и ruby мне абсолютно неизвестные языки. Большое спасибо за код. И спасибо за дискуссию на LOR из которой можно узнать много интересного.

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

Занимаюсь в свободное время добавлением одного протокола в wireshark. Если не к спеху, и надумаете скооперироваться, я бы присоединился. Пользы от меня будет мало, т.к. я не разбираюсь ни в wireshark толком, ни в kaitai полностью. Но всё же что-то да подсоблю, буду разбираться.

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

А вам точно тогда нужны диссекторы и wireshark вообще? Просто в базовом виде парсить (и что-то там обсчитывать) по pcap + семейству внутренних протоколов вполне можно без него, чисто на KS.

GreyCat ★★
() автор топика

Как я уже писал, пока нет битовых полей и Голомба, особо не нужно. Автор, посмотрите на H.264, чтобы понять о чем речь.

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

Я в целом сильно сомневаюсь, что кому-либо будет нужно разбирать H.264 по полочкам так, как это делает KS. mp4, mkv - да, а вот смысл разбора H.264 примерно такой же, как разбор zlib stream или какого-нибудь стрима с Хаффманом внутри.

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

Будет, будет. Банально, как дело до какого-нибудь BPG дойдет.

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

У wireshark удобная шкала времени. Для разбора некоторых аппаратных протоколов это нужно. Также есть быстрый фильтр. Но, к сожалению, нет простого создания структуры разбора.

anonymous
()

Насколько понял — обработку ошибок вешать нельзя? А-ля:

meta:
  id: test_format
  endian: le
seq:
  - id: files
    type: file
    repeat: eos
    err_evt: allfilespzdc
types:
  file:
    seq:
      - id: len
        type: u4
      - id: name
        type: str
        size: len
        encoding: UTF-8
        err_evt: onefilepzdc
Ну хоть что-то для валидации, допустим проверить значение в какой-то позиции, и если значение невалидно (eq, lt, gt) — бросить событие. Где события будут слушать чьи-то кастомные хендлеры. Им передаются какие-то данные и пусть хендлеры их анализируют. А если хендлер хочет остановить парсинг или проскочить хреновое место или еще что-то — return ERR_HANDLE_STATUS_N или пусть заполняет переданную в аргументах структуру и возвращает: «я тут придумал чо хочу, давай, сделай» или «мне пох» (по умолчанию).

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

Из того, что у вас там описано - больше похоже на то, что вы реально искали некий безсхемный формат - т.е. JSON / BSON / Protobuf / Avro / Thrift / ASN.1 BER / DER и далее по списку.

GreyCat ★★
() автор топика
Ответ на: комментарий от deep-purple

Единственная валидация, которая пока есть - штуки типа:

- id: magic
  contents: [0x11, 0x55, 0x66]

Это вещь зачитает три байта, сравнит их с 11 55 66, выбросит exception (или его ближайший аналог в целевом языке), если это не так, и прервет дальнейший парсинг.

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

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

выбросит exception

А где-то в этом треде я успел прочитать что присвоит null и без каких-либо сообщений поедет парсить дальше. Но это не суть. Суть в том что это не гибко.

Нужно дать возможность выбирать поведение при обнаружении невалидного куска данных. Может быть оно действительно не важно и надо присвоить null (или иное значение) и поехать дальше, а может быть это критично и нет смысла разбирать дальше.

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

deep-purple ★★★★★
()
Ответ на: комментарий от GreyCat

некий безсхемный формат

Таки нет, я искал всетаки «схемный».

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

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

Я вижу здесь две основных задачи:

  • Научиться определять ситуацию невалидности данных.
  • Научиться реагировать на нее.

Первое относительно тривиально: добавляем какой-нибудь `check` и получаем что-то типа:

- id: foo
  type: u4
  check: _ <= 50

(по образу и подобию `repeat-until` - здесь подчеркивание - это значение текущего поля; хотя, в принципе, можно и `foo <= 50` писать).

Второе - сложнее.

Первое, что приходит в голову - можно выкидывать определенный exception в этом месте. При желании можно даже попробовать генерировать классы exception'ов (все унаследованные от какого-нибудь Kaitai::Struct::DataCheckException), и задавать каким-то образом идентификатор класса выкидываемого exception'а.

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

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

Вот я про второй вариант. Про «выдачу наружу» я предлагал дать возможность маркировать ошибку (err_evt). Кстати, смотри ниже — и не только ошибку, а даже просто пробросить сообщение «я дошел уже вот до сюда».

1) человек описывает правила парсинга.
2) в каком-то месте описания «просит» сгенерить ивент при таких-то условиях.
3) уже в своем коде подписывается на это событие своим хендлером.
4) задача каитаи передать какое-то состояние в этот (если таковой будет и подписан на ивент) хендлер чтобы он мог разобрать что где когда случилось и а) вернул скалярный тип через ретурн, б) заполнил какую-то структуру/массив/объект переданный ему же в аргементах, в) комбинации «а» и «б».
5) на основании возвращенного/заполненного хендлером состояния либо просто продолжить, либо просто остановить парсинг, либо бросить исключение, либо скипнуть стрим до следующей секвенции, либо до нужного оффсета переданного из хендлера, либо, либо, либо... тут можно придумать еще много чего что может быть доступным.

И для frob тоже.

Источник песца прост — некорректная декларация правил парсинга. Вернее, она может быть и корректна, быть полностью по спекам формата, но, можно напороться на файл сгенеренный хрен пойми кем хрен пойми как и хрен пойми на чем. Если бы все придерживались спеков, то не было бы миллиона костылей в приложениях даже для одного формата.

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

Я бы как минимум четко разделял фазы «определения песца» и «действий по итогам определения». Делать определение императивным я большого смысла не вижу, честно говоря. Почти все, что я могу себе представить, вполне можно описать выражением, которое без проблем оттранслировать во все языки — и не заморачиваться с записыванием этого кода на каждом целевом языке по очереди.

Вопрос с пробрасыванием сообщений и вообще pubsub-based модели тоже интересный, но его надо сильно более детально продумывать.

GreyCat ★★
() автор топика
Ответ на: комментарий от deep-purple

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

Принимаемый «родным» приложением файл сгенерённый так, что ломается парсер формата? А есть примеры из реальной жизни?

Посылать какие-нибудь сигналы — это интересно. Например если файл огромный, чтобы приложение могло обновлять прогрессбар.

А вообще любопытно выглядит задача по ksy-описанию формата генерировать не просто парсер, а парсер устойчивый к («любым») сбоям =)

frob ★★★★★
()

А можно приспособить сабж для распарсивания сообщений и новостей на форуме? А то бывает так завернут лоровские аналитики..

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

Принимаемый «родным» приложением файл сгенерённый так, что ломается парсер формата? А есть примеры из реальной жизни?

Миллионы их. По сути - любые распространенные форматы, которые реализовали и перереализовывали десятки раз. Те же файловые системы вроде FAT, всякие GIF-JPEG (с PNG, кстати, сильно меньше бардака - сказывается приличная референсная реализация в libpng). Прямо сейчас у нас на github жалуется на жизнь товарищ, который какой-то из подвидов mbus'а разбирать пытается и натыкается на ошибки и всякие прочие забавные особенности реализации smart-счетчиков, которые этот самый mbus шлют.

Посылать какие-нибудь сигналы — это интересно. Например если файл огромный, чтобы приложение могло обновлять прогрессбар.

Интересно, и уже далеко не один человек просил. Но надо думать, как это сделать. С моей точки зрения - сама по себе модель pubsub не должна затрагивать .ksy, а либо должна описываться где-то отдельно, либо (в идеале) - вообще нигде не описываться, а просто активироваться как-то из приложения, которое вызывает парсить ksy-формат.

А вообще любопытно выглядит задача по ksy-описанию формата генерировать не просто парсер, а парсер устойчивый к («любым») сбоям =)

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

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

Я правильно понял, что главное отличие от того же Protobuf в том, что Protobuf по описанию строит формат данных, а сабж позволяет описать уже существующий формат на достаточно низком уровне?

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

Главное отличие в том, что protobuf идет от структуры данных в памяти (и разработчику, как правило, глубоко фиолетово, что же получается в потоке), а KS идет как раз от потока (и порождает автоматом в памяти некую сгенерированную структуру, близко повторяющую эту самую структуру потока). С помощью KS прочитать данные, сериализованные protobuf можно (но, возможно, API будет не такой удобный, как у самого protobuf), а вот прочитать с помощью protobuf то, что умеет читать KS (например, JPEG или ELF) - фактически нельзя.

GreyCat ★★
() автор топика
22 января 2017 г.
Ответ на: комментарий от frob

Спасибо. К сожалению, сейчас и Recon Brussels, и FOSDEM сильно под вопросом из-за глобальных проблем со здоровьем :(

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

читал однажды статью, про боль opensource разработчика. все что-то требуют, качают права, ругают, угрожают и т.д.
так вот, я джва года работал с бинарными протоколами в виде различных девиаций ASTM, а о kaitai узнал только сегодня
какого черта?
я угрожающе требую, качая права, чтобы кто-то из вас, хотя бы раз в три месяца, писал статью про разбор очередного простенького протокола в kaitai struct с ключевыми словами в заголовке

ну а по теме: выздоравливай, поправляйся

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

Спасибо на добром слове :)

Для написания статей нужно: (1) понять, где их размещать, чтобы их хоть кто-то увидел, (2) чтобы их кто-то писал.

Есть идеи по поводу первого и второго?

GreyCat ★★
() автор топика
Ответ на: комментарий от GreyCat
  1. если говорить о русских статьях, то монополия ТМ™ к сожалению очевидна, а есть ещё реддит, медиум, свой сайт, чтоб не потерялось
  2. и есть мнение: «поднимать хайп важнее коммитов», а слог у тебя годный, там может и вовлеченные подтянутся?

просто серьезно, «Реверс-инжиниринг визуальных новелл» с тегами «Разработка игр, Ruby» — это вообще не то, что откроют люди, которым нужен ваш инструмент
а если откроют, будет только хуже, картинки там.. ппц

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

Я пока наблюдаю скорее то, что говорить о каком-то русскоязычном сообществе разработчиков/программистов как-то грустно. Если даже говорить про того же nakamura с его «разработка игр, Ruby» — я и сам статистику вижу, и у него пару раз спрашивал — одни и те же статьи на русском и английском языке имеют разницу по читаемости (и переходам) раз в 20-30. Если, как ты говоришь, эта - самая большая русскоязычная площадка — то я склоняюсь к тому, что писать на русском языке не нужно вообще. Судя по себе — года 2-3 назад я заходил на Хабр практически каждый день, сейчас — хорошо, если раз в пару недель, и то скорее по ссылкам из твиттера.

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

Если есть желание помочь статьями или форматами — приглашаю присоединяться.

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

В общем, выступление даже состоится - можно будет видеотрансляцию посмотреть на страничке. А еще мы сегодня 0.6 зарелизили. Может до завтра подтвердят ;)

GreyCat ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.