Merge "Remove PauseTiming/ResumeTiming calls."
diff --git a/init/selinux.cpp b/init/selinux.cpp
index c4b01e6..331fad6 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -115,7 +115,7 @@
// fork succeeded -- this is executing in the child process
// Close the pipe FD not used by this process
- TEMP_FAILURE_RETRY(close(pipe_fds[0]));
+ close(pipe_fds[0]);
// Redirect stderr to the pipe FD provided by the parent
if (TEMP_FAILURE_RETRY(dup2(pipe_fds[1], STDERR_FILENO)) == -1) {
@@ -123,7 +123,7 @@
_exit(127);
return false;
}
- TEMP_FAILURE_RETRY(close(pipe_fds[1]));
+ close(pipe_fds[1]);
if (execv(filename, argv) == -1) {
PLOG(ERROR) << "Failed to execve " << filename;
@@ -137,7 +137,7 @@
// fork succeeded -- this is executing in the original/parent process
// Close the pipe FD not used by this process
- TEMP_FAILURE_RETRY(close(pipe_fds[1]));
+ close(pipe_fds[1]);
// Log the redirected output of the child process.
// It's unfortunate that there's no standard way to obtain an istream for a file descriptor.
@@ -148,7 +148,7 @@
if (!android::base::ReadFdToString(child_out_fd, &child_output)) {
PLOG(ERROR) << "Failed to capture full output of " << filename;
}
- TEMP_FAILURE_RETRY(close(child_out_fd));
+ close(child_out_fd);
if (!child_output.empty()) {
// Log captured output, line by line, because LOG expects to be invoked for each line
std::istringstream in(child_output);
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index 8b30b76..b8164c5 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -225,11 +225,13 @@
// Find the return address location.
if (return_address_undefined) {
cur_regs->set_pc(0);
- *finished = true;
} else {
cur_regs->set_pc((*cur_regs)[cie->return_address_register]);
- *finished = false;
}
+
+ // If the pc was set to zero, consider this the final frame.
+ *finished = (cur_regs->pc() == 0) ? true : false;
+
cur_regs->set_sp(cfa);
// Return false if the unwind is not finished or the cfa and pc didn't change.
return *finished || prev_cfa != cfa || prev_pc != cur_regs->pc();
diff --git a/libunwindstack/ElfInterfaceArm.cpp b/libunwindstack/ElfInterfaceArm.cpp
index 30a1532..170a5cd 100644
--- a/libunwindstack/ElfInterfaceArm.cpp
+++ b/libunwindstack/ElfInterfaceArm.cpp
@@ -121,8 +121,10 @@
}
regs_arm->set_sp(arm.cfa());
(*regs_arm)[ARM_REG_SP] = regs_arm->sp();
- *finished = false;
return_value = true;
+
+ // If the pc was set to zero, consider this the final frame.
+ *finished = (regs_arm->pc() == 0) ? true : false;
}
if (arm.status() == ARM_STATUS_NO_UNWIND) {
diff --git a/libunwindstack/tests/DwarfSectionImplTest.cpp b/libunwindstack/tests/DwarfSectionImplTest.cpp
index c701a29..7e85bbb 100644
--- a/libunwindstack/tests/DwarfSectionImplTest.cpp
+++ b/libunwindstack/tests/DwarfSectionImplTest.cpp
@@ -340,6 +340,23 @@
EXPECT_EQ(0x10U, regs.sp());
}
+TYPED_TEST_P(DwarfSectionImplTest, Eval_pc_zero) {
+ DwarfCie cie{.return_address_register = 5};
+ RegsImplFake<TypeParam> regs(10, 9);
+ dwarf_loc_regs_t loc_regs;
+
+ regs.set_pc(0x100);
+ regs.set_sp(0x2000);
+ regs[5] = 0;
+ regs[8] = 0x10;
+ loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
+ bool finished;
+ ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
+ EXPECT_TRUE(finished);
+ EXPECT_EQ(0U, regs.pc());
+ EXPECT_EQ(0x10U, regs.sp());
+}
+
TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
DwarfCie cie{.return_address_register = 5};
RegsImplFake<TypeParam> regs(10, 9);
@@ -854,7 +871,7 @@
Eval_cfa_expr_is_register, Eval_cfa_expr, Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa,
Eval_cfa_bad, Eval_cfa_register_prev, Eval_cfa_register_from_value, Eval_double_indirection,
Eval_invalid_register, Eval_different_reg_locations, Eval_return_address_undefined,
- Eval_return_address, Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr,
+ Eval_pc_zero, Eval_return_address, Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr,
Eval_same_cfa_same_pc, GetCie_fail_should_not_cache, GetCie_32_version_check,
GetCie_negative_data_alignment_factor, GetCie_64_no_augment, GetCie_augment, GetCie_version_3,
GetCie_version_4, GetFdeFromOffset_fail_should_not_cache, GetFdeFromOffset_32_no_augment,
diff --git a/libunwindstack/tests/ElfInterfaceArmTest.cpp b/libunwindstack/tests/ElfInterfaceArmTest.cpp
index feb24ce..4b621c9 100644
--- a/libunwindstack/tests/ElfInterfaceArmTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceArmTest.cpp
@@ -401,4 +401,40 @@
ASSERT_EQ(0x1234U, regs.pc());
}
+TEST_F(ElfInterfaceArmTest, StepExidx_pc_zero) {
+ ElfInterfaceArmFake interface(&memory_);
+
+ interface.FakeSetStartOffset(0x1000);
+ interface.FakeSetTotalEntries(1);
+ memory_.SetData32(0x1000, 0x6000);
+ // Set the pc using a pop r15 command.
+ memory_.SetData32(0x1004, 0x808800b0);
+
+ // pc value of zero.
+ process_memory_.SetData32(0x10000, 0);
+
+ RegsArm regs;
+ regs[ARM_REG_SP] = 0x10000;
+ regs[ARM_REG_LR] = 0x20000;
+ regs.set_sp(regs[ARM_REG_SP]);
+ regs.set_pc(0x1234);
+
+ bool finished;
+ ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished));
+ ASSERT_TRUE(finished);
+ ASSERT_EQ(0U, regs.pc());
+
+ // Now set the pc from the lr register (pop r14).
+ memory_.SetData32(0x1004, 0x808400b0);
+
+ regs[ARM_REG_SP] = 0x10000;
+ regs[ARM_REG_LR] = 0x20000;
+ regs.set_sp(regs[ARM_REG_SP]);
+ regs.set_pc(0x1234);
+
+ ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished));
+ ASSERT_TRUE(finished);
+ ASSERT_EQ(0U, regs.pc());
+}
+
} // namespace unwindstack
diff --git a/libutils/Unicode.cpp b/libutils/Unicode.cpp
index 5fd9155..e7520a8 100644
--- a/libutils/Unicode.cpp
+++ b/libutils/Unicode.cpp
@@ -297,23 +297,22 @@
char16_t* strstr16(const char16_t* src, const char16_t* target)
{
- const char16_t needle = *target++;
- const size_t target_len = strlen16(target);
- if (needle != '\0') {
- do {
+ const char16_t needle = *target;
+ if (needle == '\0') return (char16_t*)src;
+
+ const size_t target_len = strlen16(++target);
+ do {
do {
- if (*src == '\0') {
- return nullptr;
- }
+ if (*src == '\0') {
+ return nullptr;
+ }
} while (*src++ != needle);
- } while (strncmp16(src, target, target_len) != 0);
- src--;
- }
+ } while (strncmp16(src, target, target_len) != 0);
+ src--;
return (char16_t*)src;
}
-
int strzcmp16(const char16_t *s1, size_t n1, const char16_t *s2, size_t n2)
{
const char16_t* e1 = s1+n1;
diff --git a/libutils/tests/Unicode_test.cpp b/libutils/tests/Unicode_test.cpp
index d23e43a..b92eef8 100644
--- a/libutils/tests/Unicode_test.cpp
+++ b/libutils/tests/Unicode_test.cpp
@@ -15,7 +15,11 @@
*/
#define LOG_TAG "Unicode_test"
-#include <utils/Log.h>
+
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include <log/log.h>
#include <utils/Unicode.h>
#include <gtest/gtest.h>
@@ -119,6 +123,31 @@
<< "should return the original pointer";
}
+TEST_F(UnicodeTest, strstr16EmptyTarget_bug) {
+ // In the original code when target is an empty string strlen16() would
+ // start reading the memory until a "terminating null" (that is, zero)
+ // character is found. This happens because "*target++" in the original
+ // code would increment the pointer beyond the actual string.
+ void* memptr;
+ const size_t alignment = sysconf(_SC_PAGESIZE);
+ const size_t size = 2 * alignment;
+ ASSERT_EQ(posix_memalign(&memptr, alignment, size), 0);
+ // Fill allocated memory.
+ memset(memptr, 'A', size);
+ // Create a pointer to an "empty" string on the first page.
+ char16_t* const emptyString = (char16_t* const)((char*)memptr + alignment - 4);
+ *emptyString = (char16_t)0;
+ // Protect the second page to show that strstr16() violates that.
+ ASSERT_EQ(mprotect((char*)memptr + alignment, alignment, PROT_NONE), 0);
+ // Test strstr16(): when bug is present a segmentation fault is raised.
+ ASSERT_EQ(strstr16((char16_t*)memptr, emptyString), (char16_t*)memptr)
+ << "should not read beyond the first char16_t.";
+ // Reset protection of the second page
+ ASSERT_EQ(mprotect((char*)memptr + alignment, alignment, PROT_READ | PROT_WRITE), 0);
+ // Free allocated memory.
+ free(memptr);
+}
+
TEST_F(UnicodeTest, strstr16SameString) {
const char16_t* result = strstr16(kSearchString, kSearchString);
EXPECT_EQ(kSearchString, result)
diff --git a/logd/LogTags.cpp b/logd/LogTags.cpp
index fcd45bd..ff7e762 100644
--- a/logd/LogTags.cpp
+++ b/logd/LogTags.cpp
@@ -105,7 +105,7 @@
android::base::WriteStringToFd(
formatEntry_locked(it.first, AID_ROOT), fd);
}
- TEMP_FAILURE_RETRY(close(fd));
+ close(fd);
}
}
@@ -601,7 +601,7 @@
std::string ret = formatEntry_locked(tag, uid, false);
android::base::WriteStringToFd(ret, fd);
- TEMP_FAILURE_RETRY(close(fd));
+ close(fd);
size_t size = 0;
file2watermark_const_iterator iwater;
@@ -625,7 +625,7 @@
std::string ret = formatEntry_locked(tag, uid, false);
android::base::WriteStringToFd(ret, fd);
- TEMP_FAILURE_RETRY(close(fd));
+ close(fd);
size_t size = 0;
file2watermark_const_iterator iwater;