Файл .dex
— это транспортный формат для байт-кода Dalvik. Существуют определенные синтаксические и семантические ограничения для того, чтобы файл был допустимым файлом .dex
, и среда выполнения должна поддерживать только допустимые файлы .dex.
Общие ограничения целостности .dex
Общие ограничения целостности касаются более крупной структуры файла .dex
, как подробно описано в формате .dex
.
Идентификатор | Описание |
---|---|
Г1 | magic число файла .dex должно быть dex\n035\0 или dex\n037\0 . |
G2 | Контрольная сумма должна быть контрольной суммой Adler-32 всего содержимого файла, за исключением magic поля и поля checksum . |
G3 | Подпись должна представлять собой хеш SHA-1 всего содержимого файла, за исключением magic , checksum и signature . |
G4 | file_size должен соответствовать фактическому размеру файла в байтах. |
G5 | header_size должен иметь значение: 0x70 |
G6 | endian_tag должен иметь значение ENDIAN_CONSTANT или REVERSE_ENDIAN_CONSTANT . |
G7 | Для каждой из разделов link , string_ids , type_ids , proto_ids , field_ids , method_ids , class_defs и data поля offset и size должны быть либо нулевыми, либо оба ненулевыми. В последнем случае смещение должно быть выровнено по четырем байтам. |
G8 | Все поля смещения в заголовке, кроме map_off должны быть выровнены по четырем байтам. |
G9 | Поле 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 | Для каждого string_id_item поле string_data_off должно содержать действительную ссылку на раздел data . Для указанного string_data_item поле data должно содержать допустимую строку MUTF-8, а utf16_size должно соответствовать декодированной длине строки. |
G16 | Для каждого type_id_item поле descriptor_idx должно содержать действительную ссылку на список string_ids . Ссылочная строка должна быть допустимым дескриптором типа. |
G17 | Для каждого proto_id_item поле shorty_idx должно содержать действительную ссылку на список string_ids . Ссылочная строка должна быть допустимым коротким дескриптором. Кроме того, поле 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 . Ссылочная запись не должна быть ссылочным типом, отличным от массива. |
Статические ограничения байт-кода
Статические ограничения — это ограничения на отдельные элементы байт-кода. Обычно их можно проверить без использования методов контроля или анализа потока данных.
Идентификатор | Описание |
---|---|
А1 | Массив insns не должен быть пустым. |
А2 | Первый код операции в массиве insns должен иметь нулевой индекс. |
А3 | Массив insns должен содержать только допустимые коды операций Dalvik. |
А4 | Индекс инструкции n+1 должен равняться индексу инструкции n плюс длине инструкции n с учетом возможных операндов. |
А5 | Последняя инструкция в массиве insns должна заканчиваться индексом insns_size-1 . |
А6 | Все цели goto и if-<kind> должны быть кодами операций одного и того же метода. |
А7 | Все цели инструкции packed-switch должны быть кодами операций одного и того же метода. Размер и список целей должны быть последовательными. |
А8 | Все цели инструкции sparse-switch должны быть кодами операций одного и того же метода. Соответствующая таблица должна быть последовательной и отсортированной по возрастанию. |
А9 | Операнд B инструкций const-string и const-string/jumbo должен быть допустимым индексом в пуле строковых констант. |
А10 | Операнд C инструкций iget<kind> и iput<kind> должен быть допустимым индексом в пуле констант полей. Ссылочная запись должна представлять поле экземпляра. |
А11 | Операнд C инструкций sget<kind> и sput<kind> должен быть допустимым индексом в пуле констант полей. Ссылочная запись должна представлять статическое поле. |
А12 | Операнд C инструкций invoke-virtual , invoke-super , invoke-direct и invoke-static должен быть допустимым индексом в пуле констант метода. |
А13 | Операнд B инструкций invoke-virtual/range , invoke-super/range , invoke-direct/range и invoke-static/range должен быть допустимым индексом в пуле констант метода. |
А14 | Метод, имя которого начинается с '<', должен вызываться только неявно виртуальной машиной, а не кодом, созданным из файла .dex . Единственным исключением является инициализатор экземпляра, который можно вызвать с помощью invoke-direct . |
А15 | Операнд C инструкции invoke-interface должен быть допустимым индексом в пуле констант метода. Ссылочный method_id должен принадлежать интерфейсу (а не классу). |
А16 | Операнд B инструкции invoke-interface/range должен быть допустимым индексом в пуле констант метода. Ссылочный method_id должен принадлежать интерфейсу (а не классу). |
А17 | Операнд B инструкций const-class , check-cast , new-instance и filled-new-array/range должен быть допустимым индексом в пуле констант типа. |
А18 | Операнд C инструкций instance-of , new-array и filled-new-array должен быть допустимым индексом в пуле констант типа. |
А19 | Размеры массива, созданного командой создания new-array должны быть меньше 256 . |
А20 | new инструкция не должна ссылаться на классы массивов, интерфейсы или абстрактные классы. |
А21 | Тип, на который ссылается инструкция создания new-array должен быть допустимым, не ссылочным типом. |
А22 | Все регистры, на которые ссылается инструкция одинарной ширины (не парные), должны быть допустимы для текущего метода. То есть их индексы должны быть неотрицательными и меньшими, чем registers_size . |
А23 | Все регистры, на которые ссылается инструкция в виде двойной ширины (пары), должны быть допустимы для текущего метода. То есть их индексы должны быть неотрицательными и меньше, чем registers_size-1 . |
А24 | Операнд method_id инструкций invoke-virtual и invoke-direct должен принадлежать классу (а не интерфейсу). В файлах Dex до версии 037 то же самое должно быть справедливо для инструкций invoke-super и invoke-static . |
А25 | Операнд method_id инструкций invoke-virtual/range и invoke-direct/range должен принадлежать классу (а не интерфейсу). В файлах Dex до версии 037 то же самое должно быть справедливо для инструкций invoke-super/range и invoke-static/range . |
Структурные ограничения байт-кода
Структурные ограничения — это ограничения на отношения между несколькими элементами байт-кода. Обычно их невозможно проверить без использования методов контроля или анализа потока данных.
Идентификатор | Описание |
---|---|
Б1 | Количество и типы аргументов (регистры и непосредственные значения) всегда должны соответствовать инструкции. |
Би 2 | Пары регистров никогда не должны разбиваться. |
Б3 | Регистр (или пара) должен быть назначен первым, прежде чем его можно будет прочитать. |
Б4 | Инструкция invoke-direct должна вызывать инициализатор экземпляра или метод только в текущем классе или одном из его суперклассов. |
Б5 | Инициализатор экземпляра должен вызываться только для неинициализированного экземпляра. |
Б6 | Методы экземпляра можно вызывать только в экземплярах, а поля экземпляра доступны только в уже инициализированных экземплярах. |
Б7 | Регистр, в котором хранится результат инструкции new-instance не должен использоваться, если та же самая инструкция new-instance снова выполняется до инициализации экземпляра. |
Б8 | Инициализатор экземпляра должен вызвать другой инициализатор экземпляра (того же класса или суперкласса), прежде чем можно будет получить доступ к каким-либо членам экземпляра. Исключениями являются ненаследуемые поля экземпляра, которые можно назначить перед вызовом другого инициализатора, а также класс Object в целом. |
Б9 | Все фактические аргументы метода должны быть совместимы по присваиванию с соответствующими формальными аргументами. |
Б10 | Для каждого вызова метода экземпляра фактический экземпляр должен быть совместим по назначению с классом или интерфейсом, указанным в инструкции. |
Б11 | Инструкция return<kind> должна соответствовать типу возвращаемого значения своего метода. |
Б12 | При доступе к защищенным членам суперкласса фактический тип экземпляра, к которому осуществляется доступ, должен быть либо текущим классом, либо одним из его подклассов. |
Б13 | Тип значения, хранящегося в статическом поле, должен быть совместимым по присваиванию или конвертируемым в тип поля. |
Б14 | Тип значения, хранящегося в поле, должен быть совместимым по присваиванию или конвертируемым в тип поля. |
Б15 | Тип каждого значения, хранящегося в массиве, должен быть совместим по присваиванию с типом компонента массива. |
Б16 | Операнд A инструкции throw должен быть совместим по назначению с java.lang.Throwable . |
Б17 | Последняя достижимая инструкция метода должна быть либо инструкцией обратного goto или перехода, либо инструкцией return , либо инструкцией throw . Не должно быть возможности оставить массив insns внизу. |
Б18 | Неназначенная половина бывшей пары регистров не может быть прочитана (считается недействительной) до тех пор, пока она не будет переназначена какой-либо другой инструкцией. |
Б19 | Инструкции move-result<kind> должна предшествовать (в массиве insns ) инструкция invoke-<kind> . Единственным исключением является инструкция move-result-object , которой также может предшествовать инструкция filled-new-array . |
Б20 | Инструкции move-result<kind> должна предшествовать (в фактическом потоке управления) соответствующая инструкция return-<kind> (к ней нельзя переходить). Единственным исключением является инструкция move-result-object , которой также может предшествовать инструкция filled-new-array . |
Б21 | Инструкция move-exception должна появляться только в качестве первой инструкции в обработчике исключений. |
Б22 | Псевдоинструкции packed-switch-data , sparse-switch-data и fill-array-data не должны быть доступны для потока управления. |