НЕМЕЩЕННЫЙ ВЫБОР в ASN.1
Мы используем компилятор JAC ASN.1 в нашем (унаследованном) проекте и столкнулись с ситуацией, когда мы получали сообщения ASN.1, которые мы не смогли проанализировать.
Я взглянул на код синтаксического анализатора и заметил, что это ошибка в библиотеке. Поскольку переход на коммерческое решение не так прост, мы вынуждены раскошелиться на библиотеку и исправить ее.
TL; DR
Есть ли ситуации во время декодирования ASN.1, когда вы читаете номер тега и вместо того, чтобы посмотреть, есть ли у вашей схемы этот номер тега на уровне структуры, в которой вы находитесь, вы посмотрите, есть ли у этого вложенного элемента этот тег?
Вот минимальный пример воспроизведения ошибки в библиотеке. Вы можете использовать эту онлайн-площадку для компиляции схемы и т. Д. И увидеть, что с функционирующим парсером проблем нет.
схема
По сути, это структура с двумя элементами: выбор и строка, которые являются необязательными. Ключом к примеру является то, что элемент choice содержит элемент с номером тега, равным номеру тега необязательной строки.
Example DEFINITIONS ::= BEGIN
Message ::= SEQUENCE {
params [1] EXPLICIT Params OPTIONAL,
confuser [2] IMPLICIT PrintableString OPTIONAL
}
Params ::= CHOICE {
unimportant [1] IMPLICIT PrintableString,
accident [2] IMPLICIT Accident
}
Accident ::= SEQUENCE {
irrelevant [1] IMPLICIT PrintableString OPTIONAL
}
END
Пример сообщения
message Message ::= {
confuser "Foo"
}
Пример сообщения (закодировано, BER)
30058203 466F6F
При использовании парсера JAC он будет правильно читать номер тега 2
в сообщении, а затем перебирает элементы в схеме, чтобы найти элемент, с которым он связан. Однако, с элементами выбора это имеет некоторую дополнительную логику:
Вместо того чтобы сказать "у params есть тег 1, который не равен 2, поэтому это значение ему не соответствует", он идет "у params есть тег 1, который не равен 2, но это элемент выбора, и он содержит элемент с тегом 2, так что это должен быть элемент, который я ищу ".
Затем он принимает Accident
класс, продолжает синтаксический анализ и, наконец, терпит неудачу, потому что теперь не может найти тег 2
в этом классе.
Комментарий в логике синтаксического анализатора говорит, что это для случаев нетегированных элементов выбора. Но это сбивает меня с толку: согласно всему, что я читаю, непомеченные элементы выбора не имеют тега по умолчанию, но вместо этого будут помечены явно; Более того, выбор никогда не может быть помечен неявно.
Но с этой информацией я не могу представить ни одного сценария, где эта логика в парсере полезна, и я склоняюсь к ее простому удалению. Тем не менее, я только что познакомился с ASN.1 из-за этой ошибки и, возможно, что-то упускаю из виду - я?
2 ответа
Существует одна возможность просмотра тегов выбранного члена, и выбор добавляется без тегов:
Например, если ваше определение было:
Message ::= SEQUENCE {
params Params OPTIONAL,
confuser [2] IMPLICIT PrintableString OPTIONAL
}
Отвечая на ваш вопрос.
Комментарий в логике синтаксического анализатора говорит, что это для случаев нетегированных элементов выбора. Но это сбивает меня с толку: согласно всему, что я читаю, непомеченные элементы выбора не имеют тега по умолчанию, но вместо этого будут помечены явно; Более того, выбор никогда не может быть помечен неявно.
Нет, непомеченные элементы выбора берут тег выбора. Это помеченные элементы выбора, которые должны быть помечены явно и никогда не могут быть помечены неявно.
Возвращаясь к вашему определению
Message ::= SEQUENCE {
params [1] EXPLICIT Params OPTIONAL,
confuser [2] IMPLICIT PrintableString OPTIONAL
}
Компонент params должен иметь явный тег (как потому, что вы пометили его как EXPLICIT..., так и из-за условия 30.7.c X.680:
30.6. Конструкция тегирования определяет явное тегирование, если выполняется любое из следующего:
...
с. используется альтернатива "Tag Type", и значением "TagDefault" для модуля является "IMPLICIT TAGS" или "AUTOMATIC TAGS", но тип, определенный "Type", представляет собой тип выбора без тега, открытый тип без тега или без тега "DummyReference" (см. Рекомендацию МСЭ-Т X.683 | ИСО / МЭК 8824-4, 8.3).
В этом сценарии кодирование идет:
х.690: п. 8.9.2 и 8.9.3
8.9.2 Октеты содержимого должны состоять из полного кодирования одного значения данных из каждого из типов, перечисленных в определении типа последовательности ASN.1, в порядке их появления в определении, если только тип не был указан с помощью ключевое слово ДОПОЛНИТЕЛЬНО или ключевое слово ПО УМОЛЧАНИЮ.
8.9.3 Кодирование значения данных может, но не обязательно, присутствовать для типа, на который ссылается ключевое слово OPTIONAL или ключевое слово DEFAULT. Если он присутствует, он должен появляться в кодировке в точке, соответствующей появлению типа в определении ASN.1.
Но для компонента params сначала применяется правило 8.14.2.
8.14.2 Если неявное тегирование (см. Рекомендацию МСЭ-Т X.680 | ИСО / МЭК 8824-1, 30.6) не использовалось при определении типа, должно быть построено кодирование, и октеты содержимого должны быть полной основой кодирование.
... и только в пределах явно помеченного типа мы можем рассмотреть кодировку выбора 8.13
8.13 Кодирование значения выбора Кодирование значения выбора должно быть таким же, как и кодирование значения выбранного типа.
Настоящая проблема здесь заключается в том, что парсер просматривает вложенные элементы, несмотря на указанный тег. params
Поле, если оно присутствует, всегда будет помечено [1] в кодировке.
Для полей без тегов имеет смысл искать теги во вложенных типах.