summaryrefslogtreecommitdiffstats
path: root/dexlayout
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2018-02-06 01:16:13 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2018-02-06 01:16:13 +0000
commit83784ca898f823e6f02c86996626b5e48e328d85 (patch)
tree6e49bf5bdc66c959d820f02dc8c3908725ecdec8 /dexlayout
parent540d4be4514b3d02e046d5faebd3cb55a8ea9eff (diff)
parenta27af08ee0c5f307366be73363369cc1d95d6d4c (diff)
downloadandroid_art-83784ca898f823e6f02c86996626b5e48e328d85.tar.gz
android_art-83784ca898f823e6f02c86996626b5e48e328d85.tar.bz2
android_art-83784ca898f823e6f02c86996626b5e48e328d85.zip
Merge "Handle code item overruns in cdex code item write"
Diffstat (limited to 'dexlayout')
-rw-r--r--dexlayout/compact_dex_writer.cc13
-rw-r--r--dexlayout/dexlayout_test.cc48
2 files changed, 51 insertions, 10 deletions
diff --git a/dexlayout/compact_dex_writer.cc b/dexlayout/compact_dex_writer.cc
index 9462fe563b..ca13f7588b 100644
--- a/dexlayout/compact_dex_writer.cc
+++ b/dexlayout/compact_dex_writer.cc
@@ -162,11 +162,18 @@ void CompactDexWriter::WriteCodeItem(Stream* stream,
static constexpr size_t kPayloadInstructionRequiredAlignment = 4;
const uint32_t current_code_item_start = stream->Tell() + preheader_bytes;
- if (!IsAlignedParam(current_code_item_start, kPayloadInstructionRequiredAlignment)) {
+ if (!IsAlignedParam(current_code_item_start, kPayloadInstructionRequiredAlignment) ||
+ kIsDebugBuild) {
// If the preheader is going to make the code unaligned, consider adding 2 bytes of padding
// before if required.
- for (const DexInstructionPcPair& instruction : code_item->Instructions()) {
- const Instruction::Code opcode = instruction->Opcode();
+ IterationRange<DexInstructionIterator> instructions = code_item->Instructions();
+ SafeDexInstructionIterator it(instructions.begin(), instructions.end());
+ for (; !it.IsErrorState() && it < instructions.end(); ++it) {
+ // In case the instruction goes past the end of the code item, make sure to not process it.
+ if (std::next(it).IsErrorState()) {
+ break;
+ }
+ const Instruction::Code opcode = it->Opcode();
// Payload instructions possibly require special alignment for their data.
if (opcode == Instruction::FILL_ARRAY_DATA ||
opcode == Instruction::PACKED_SWITCH ||
diff --git a/dexlayout/dexlayout_test.cc b/dexlayout/dexlayout_test.cc
index be272fcf2c..db35a039b8 100644
--- a/dexlayout/dexlayout_test.cc
+++ b/dexlayout/dexlayout_test.cc
@@ -221,6 +221,12 @@ static const char kDuplicateCodeItemInputDex[] =
"AHAAAAACAAAAAwAAAIwAAAADAAAAAQAAAJgAAAAFAAAABAAAAKQAAAAGAAAAAQAAAMQAAAABIAAA"
"AwAAAOQAAAACIAAABwAAACQBAAADIAAAAwAAAFYBAAAAIAAAAQAAAGUBAAAAEAAAAQAAAHgBAAA=";
+// Returns the default compact dex option for dexlayout based on kDefaultCompactDexLevel.
+static std::vector<std::string> DefaultCompactDexOption() {
+ return (kDefaultCompactDexLevel == CompactDexLevel::kCompactDexLevelFast) ?
+ std::vector<std::string>{"-x", "fast"} : std::vector<std::string>{"-x", "none"};
+}
+
static void WriteBase64ToFile(const char* base64, File* file) {
// Decode base64.
CHECK(base64 != nullptr);
@@ -289,7 +295,7 @@ class DexLayoutTest : public CommonRuntimeTest {
for (const std::string &dex_file : GetLibCoreDexFileNames()) {
std::vector<std::string> dexlayout_args =
{ "-w", tmp_dir, "-o", tmp_name, dex_file };
- if (!DexLayoutExec(dexlayout_args, error_msg)) {
+ if (!DexLayoutExec(dexlayout_args, error_msg, /*pass_default_cdex_option*/ false)) {
return false;
}
size_t dex_file_last_slash = dex_file.rfind('/');
@@ -467,7 +473,7 @@ class DexLayoutTest : public CommonRuntimeTest {
// -v makes sure that the layout did not corrupt the dex file.
std::vector<std::string> dexlayout_args =
{ "-i", "-v", "-w", tmp_dir, "-o", tmp_name, "-p", profile_file, dex_file };
- if (!DexLayoutExec(dexlayout_args, error_msg)) {
+ if (!DexLayoutExec(dexlayout_args, error_msg, /*pass_default_cdex_option*/ false)) {
return false;
}
@@ -479,7 +485,7 @@ class DexLayoutTest : public CommonRuntimeTest {
// -i since the checksum won't match from the first layout.
std::vector<std::string> second_dexlayout_args =
{ "-i", "-v", "-w", tmp_dir, "-o", tmp_name, "-p", profile_file, output_dex };
- if (!DexLayoutExec(second_dexlayout_args, error_msg)) {
+ if (!DexLayoutExec(second_dexlayout_args, error_msg, /*pass_default_cdex_option*/ false)) {
return false;
}
@@ -512,7 +518,7 @@ class DexLayoutTest : public CommonRuntimeTest {
std::string output_dex = tmp_dir + "classes.dex.new";
std::vector<std::string> dexlayout_args = { "-w", tmp_dir, "-o", "/dev/null", input_dex };
- if (!DexLayoutExec(dexlayout_args, error_msg)) {
+ if (!DexLayoutExec(dexlayout_args, error_msg, /*pass_default_cdex_option*/ false)) {
return false;
}
@@ -550,12 +556,18 @@ class DexLayoutTest : public CommonRuntimeTest {
return true;
}
- bool DexLayoutExec(const std::vector<std::string>& dexlayout_args, std::string* error_msg) {
+ bool DexLayoutExec(const std::vector<std::string>& dexlayout_args,
+ std::string* error_msg,
+ bool pass_default_cdex_option = true) {
std::vector<std::string> argv;
std::string dexlayout = GetDexLayoutPath();
CHECK(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path";
argv.push_back(dexlayout);
+ if (pass_default_cdex_option) {
+ std::vector<std::string> cdex_level = DefaultCompactDexOption();
+ argv.insert(argv.end(), cdex_level.begin(), cdex_level.end());
+ }
argv.insert(argv.end(), dexlayout_args.begin(), dexlayout_args.end());
@@ -730,11 +742,33 @@ TEST_F(DexLayoutTest, CodeItemOverrun) {
CHECK(mutated_successfully)
<< "Failed to find candidate code item with only one code unit in last instruction.";
});
- std::vector<std::string> dexlayout_args = { "-i", "-o", "/dev/null", temp_dex.GetFilename() };
+
+ std::string error_msg;
+
+ ScratchFile tmp_file;
+ const std::string& tmp_name = tmp_file.GetFilename();
+ size_t tmp_last_slash = tmp_name.rfind('/');
+ std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
+ ScratchFile profile_file;
+
+ std::vector<std::string> dexlayout_args =
+ { "-i",
+ "-v",
+ "-w", tmp_dir,
+ "-o", tmp_name,
+ "-p", profile_file.GetFilename(),
+ temp_dex.GetFilename()
+ };
+ // -v makes sure that the layout did not corrupt the dex file.
ASSERT_TRUE(DexLayoutExec(&temp_dex,
/*dex_filename*/ nullptr,
- nullptr /* profile_file */,
+ &profile_file,
dexlayout_args));
+
+ std::string output_dex = temp_dex.GetFilename() + ".new";
+ std::vector<std::string> rm_exec_argv =
+ { "/bin/rm", output_dex };
+ ASSERT_TRUE(::art::Exec(rm_exec_argv, &error_msg));
}
// Test that link data is written out (or at least the header is updated).