Файл .dex – это формат передачи байт-кода Dalvik. Чтобы файл считался действительным файлом .dex, он должен соответствовать определенным синтаксическим и семантическим ограничениям .Кроме того, для поддержки действительных файлов DEX требуется среда выполнения.
Общие ограничения целостности DEX-файлов
Общие ограничения целостности относятся к структуре файла .dex, которая подробно описана в разделе Формат .dex.
| Идентификатор | Описание |
|---|---|
| G1 |
Номер magic файла .dex должен быть dex\n035\0 для версии 35 или аналогичным для более поздних версий.
|
| G2 |
Контрольная сумма должна быть контрольной суммой Adler-32 всего содержимого файла, кроме полей magic и checksum.
|
| Г3 |
Подпись должна представлять собой хеш SHA-1 всего содержимого файла, кроме magic, checksum и signature.
|
| Г4 |
Значение
|
| Г5 |
Атрибут Параметр |
| Г6 |
В поле endian_tag должно быть указано одно из следующих значений: ENDIAN_CONSTANT или REVERSE_ENDIAN_CONSTANT.
|
| Г7 |
Для каждого из разделов
Поля |
| G8 |
Все поля смещения в заголовке, кроме map_off, должны быть выровнены по четырем байтам.
|
| Г9 |
Поле map_off должно быть равно нулю или указывать на раздел данных. В последнем случае раздел data должен существовать.
|
| g10 |
Разделы link, string_ids, type_ids, proto_ids, field_ids, method_ids, class_defs и data не должны перекрывать друг друга или заголовок.
|
| G11 | Если карта существует, то каждая запись на ней должна иметь допустимый тип. Каждый тип может встречаться не более одного раза. |
| G12 |
Если карта существует, то в каждой записи карты должны быть ненулевые смещение и размер. Смещение должно указывать на соответствующий раздел файла (например, string_id_item должен указывать на раздел string_ids), а явный или неявный размер элемента должен соответствовать фактическому содержимому и размеру раздела.
|
| G13 |
Если карта существует, то смещение записи карты n+1 должно быть больше или равно смещению записи карты n plus than size of map entry n. Это означает, что записи не должны пересекаться и должны быть упорядочены от меньшего к большему.
|
| G14 |
Смещение следующих типов записей должно быть выровнено по четырем байтам: string_id_item, type_id_item, proto_id_item, field_id_item, method_id_item, class_def_item, type_list, code_item, annotations_directory_item.
|
| G15 |
Для каждого элемента Для каждого элемента Для параметра |
| G16 |
Для каждого объекта type_id_item поле descriptor_idx должно содержать действительную ссылку на список string_ids. Строка должна быть действительным дескриптором типа.
|
| G17 |
Для каждого объекта proto_id_item поле shorty_idx должно содержать действительную ссылку на список string_ids. Указанная строка должна быть действительным дескриптором shorty. Кроме того, поле return_type_idx должно быть действительным индексом в разделе type_ids, а поле parameters_off должно быть либо нулевым, либо действительным смещением в разделе data. Если значение не равно нулю, список параметров не должен содержать пустых записей.
|
| G18 |
Для каждого элемента field_id_item поля class_idx и type_idx должны быть действительными индексами в списке type_ids. Запись, на которую ссылается class_idx, должна быть ссылочного типа, не являющегося массивом. Кроме того, поле name_idx должно содержать действительную ссылку на раздел string_ids, а содержимое записи, на которую указывает ссылка, должно соответствовать спецификации MemberName.
|
| G19 |
Для каждого элемента method_id_item поле class_idx должно быть допустимым индексом в разделе type_ids, а запись, на которую указывает ссылка, должна быть ссылочным типом, не являющимся массивом. Поле proto_id должно содержать действительную ссылку на список proto_ids. Поле name_idx должно содержать действительную ссылку на раздел string_ids, а содержимое записи, на которую указывает ссылка, должно соответствовать спецификации MemberName.
|
| g20 |
Для каждого поля field_id_item поле class_idx должно быть действительным индексом в списке type_ids. Запись, на которую указывает ссылка, не должна быть ссылочным типом массива.
|
Ограничения на статический байт-код
Статические ограничения – это ограничения на отдельные элементы байт-кода. Обычно их можно проверить без использования методов анализа потока управления или данных.
| Идентификатор | Описание |
|---|---|
| A1 |
Массив insns не должен быть пустым.
|
| A2 |
Первый код операции в массиве insns должен иметь индекс ноль.
|
| A3 |
Массив insns должен содержать только действительные коды операций Dalvik.
|
| A4 |
Индекс инструкции n+1 должен быть равен индексу инструкции n плюс длина инструкции n с учетом возможных операндов.
|
| A5 |
Последняя инструкция в массиве insns должна заканчиваться на индексе insns_size-1.
|
| A6 |
Все цели goto и if-<kind> должны быть кодами операций в одном и том же методе.
|
| A7 |
Все цели инструкции packed-switch должны быть кодами операций в одном методе. Размер и список целевых значений должны быть согласованы.
|
| A8 |
Все цели инструкции sparse-switch должны быть кодами операций в одном методе. Соответствующая таблица должна быть согласованной и отсортированной по возрастанию.
|
| A9 |
Операнд B инструкций const-string и const-string/jumbo должен быть действительным индексом в пуле строковых констант.
|
| A10 |
Операнд C инструкций iget<kind> и iput<kind> должен быть действительным индексом в пуле констант поля. Указанная запись должна представлять поле экземпляра.
|
| A11 |
Операнд C инструкций sget<kind> и sput<kind> должен быть действительным индексом в пуле констант поля. Запись, на которую указывает ссылка, должна представлять статическое поле.
|
| A12 |
Операнд C инструкций invoke-virtual, invoke-super, invoke-direct и invoke-static должен быть действительным индексом в пуле констант метода.
|
| A13 |
Операнд B инструкций invoke-virtual/range, invoke-super/range, invoke-direct/range и invoke-static/range должен быть действительным индексом в пуле констант метода.
|
| A14 |
Метод, название которого начинается с символа "<", может вызываться только неявно виртуальной машиной, а не кодом из файла .dex. Единственное исключение – инициализатор экземпляра, который может быть вызван invoke-direct.
|
| A15 |
Операнд C инструкции invoke-interface должен быть действительным индексом в пуле констант метода. Указанный method_id должен принадлежать интерфейсу, а не классу.
|
| A16 |
Операнд B инструкции invoke-interface/range должен быть действительным индексом в пуле констант метода.
Указанный элемент method_id должен принадлежать интерфейсу (а не классу).
|
| A17 |
Операнд B инструкций const-class, check-cast, new-instance и filled-new-array/range должен быть действительным индексом в пуле констант типа.
|
| A18 |
Операнд C инструкций instance-of, new-array и filled-new-array должен быть действительным индексом в пуле констант типа.
|
| A19 |
Размеры массива, созданного с помощью инструкции new-array, должны быть меньше 256.
|
| A20 |
Инструкция new не должна ссылаться на классы массивов, интерфейсы или абстрактные классы.
|
| A21 |
Тип, на который ссылается инструкция new-array, должен быть действительным и не должен быть ссылочным.
|
| A22 |
Все регистры, на которые ссылается инструкция в одноширинном (непарном) режиме, должны быть действительны для текущего метода. Индексы должны быть неотрицательными и меньше registers_size.
|
| A23 |
Все регистры, на которые ссылается инструкция в двойной ширине (паре), должны быть действительны для текущего метода. Их индексы должны быть неотрицательными и меньше registers_size-1.
|
| A24 |
Операнд method_id инструкций invoke-virtual и invoke-direct должен принадлежать классу (не интерфейсу). В файлах Dex более ранних версий (до 037) это также относится к инструкциям invoke-super и invoke-static.
|
| A25 |
Операнд method_id инструкций invoke-virtual/range и invoke-direct/range должен принадлежать классу (не интерфейсу). В файлах Dex более ранних версий (до 037) это также относится к инструкциям invoke-super/range и invoke-static/range.
|
Структурные ограничения на байт-код
Структурные ограничения – это ограничения на отношения между несколькими элементами байт-кода. Обычно их нельзя проверить без использования методов анализа управления или потока данных.
| Идентификатор | Описание |
|---|---|
| B1 | Количество и типы аргументов (регистры и непосредственные значения) должны всегда соответствовать инструкции. |
| B2 | Пары регистров нельзя разделять. |
| B3 | Прежде чем читать регистр (или пару регистров), его необходимо назначить. |
| B4 |
Инструкция invoke-direct должна вызывать инициализатор экземпляра или метод только в текущем классе или одном из его надклассов.
|
| B5 | Инициализатор экземпляра должен вызываться только для неинициализированного экземпляра. |
| B6 | Методы экземпляра могут вызываться только для уже инициализированных экземпляров, а поля экземпляра могут быть доступны только для них. |
| B7 |
Регистр, в котором хранится результат выполнения инструкции new-instance, нельзя использовать, если та же инструкция new-instance выполняется снова до инициализации экземпляра.
|
| B8 |
Инициализатор экземпляра должен вызвать другой инициализатор экземпляра (того же класса или надкласса), прежде чем можно будет получить доступ к любым членам экземпляра.
Исключение составляют ненаследуемые поля экземпляра, которые можно назначить до вызова другого инициализатора, и класс Object в целом.
|
| B9 | Все фактические аргументы метода должны быть совместимы по присваиванию со своими формальными аргументами. |
| B10 | При каждом вызове метода экземпляра фактический экземпляр должен быть совместим по присваиванию с классом или интерфейсом, указанным в инструкции. |
| B11 |
Инструкция return<kind> должна соответствовать типу возвращаемого значения метода.
|
| B12 | При обращении к защищенным членам суперкласса фактический тип экземпляра должен быть текущим классом или одним из его подклассов. |
| B13 | Тип значения, хранящегося в статическом поле, должен быть совместим с типом поля или преобразуем в него. |
| B14 | Тип значения, хранящегося в поле, должен быть совместим с типом поля или преобразуемым в него. |
| B15 | Тип каждого значения, хранящегося в массиве, должен быть совместим с типом компонента массива. |
| B16 |
Операнд A инструкции throw должен быть совместим с java.lang.Throwable по присваиванию.
|
| B17 |
Последняя доступная инструкция метода должна быть инструкцией перехода назад goto или ветвления, return или throw. Нельзя, чтобы массив insns можно было покинуть снизу.
|
| B18 | Неназначенная половина бывшей пары регистров не может быть прочитана (считается недействительной), пока она не будет переназначена другой инструкцией. |
| B19 |
Инструкция move-result<kind> должна непосредственно предшествовать инструкции invoke-<kind> в массиве insns. Единственное исключение – инструкция move-result-object, перед которой может стоять инструкция filled-new-array.
|
| B20 |
Инструкция move-result<kind> должна непосредственно предшествовать (в фактическом потоке управления) соответствующей инструкции return-<kind> (переход к ней недопустим). Единственное исключение – инструкция move-result-object, перед которой также может быть указана инструкция filled-new-array.
|
| B21 |
Инструкция move-exception должна быть первой в обработчике исключений.
|
| B22 |
Псевдоинструкции packed-switch-data, sparse-switch-data и fill-array-data не должны быть доступны для управления потоком.
|