Ограничения

Файл .dex — это транспортный формат для Dalvik Bytecode. Существуют определенные синтаксические и семантические ограничения для того, чтобы файл был допустимым файлом .dex , и среда выполнения должна поддерживать только допустимые файлы .dex.

Общие ограничения целостности .dex

Общие ограничения целостности связаны с большей структурой файла .dex , как подробно описано в формате .dex .

Идентификатор Описание
G1 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 Для каждого вызова метода экземпляра фактический экземпляр должен быть совместим по присваиванию с классом или интерфейсом, указанным в инструкции.
B11 Инструкция return<kind> должна соответствовать типу возвращаемого значения ее метода.
В12 При доступе к защищенным членам суперкласса фактический тип экземпляра, к которому осуществляется доступ, должен быть либо текущим классом, либо одним из его подклассов.
Б13 Тип значения, хранящегося в статическом поле, должен быть совместим с присваиванием или преобразовываться в тип поля.
B14 Тип значения, хранящегося в поле, должен быть совместим с присваиванием или преобразовываться в тип поля.
В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 не должны быть доступны потоку управления.