summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2014-09-19 16:48:19 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2014-09-19 16:48:20 +0000
commit8147dcb6b149ba5bba0915fdf0cbcb2dd18d431e (patch)
tree177fb4a55f5abb4211c9797cdac75cde0bce8925
parent87258edd817672daefc1d262af4cfdf732d4e454 (diff)
parentf9f0ed401f7fe4138a71b36719423b908a3b7bfb (diff)
downloadart-8147dcb6b149ba5bba0915fdf0cbcb2dd18d431e.zip
art-8147dcb6b149ba5bba0915fdf0cbcb2dd18d431e.tar.gz
art-8147dcb6b149ba5bba0915fdf0cbcb2dd18d431e.tar.bz2
Merge "ART: Overflow of bound check in ArrayCopy intrinsic"
-rwxr-xr-xcompiler/dex/quick/x86/target_x86.cc34
1 files changed, 26 insertions, 8 deletions
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index 675d6ac..de11996 100755
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -1124,37 +1124,51 @@ bool X86Mir2Lir::GenInlinedArrayCopyCharArray(CallInfo* info) {
LoadValueDirectFixed(rl_src, rs_rAX);
LoadWordDisp(rs_rAX, mirror::Array::LengthOffset().Int32Value(), rs_rAX);
LIR* src_bad_len = nullptr;
+ LIR* src_bad_off = nullptr;
LIR* srcPos_negative = nullptr;
if (!rl_srcPos.is_const) {
LoadValueDirectFixed(rl_srcPos, tmp_reg);
srcPos_negative = OpCmpImmBranch(kCondLt, tmp_reg, 0, nullptr);
- OpRegReg(kOpAdd, tmp_reg, rs_rDX);
- src_bad_len = OpCmpBranch(kCondLt, rs_rAX, tmp_reg, nullptr);
+ // src_pos < src_len
+ src_bad_off = OpCmpBranch(kCondLt, rs_rAX, tmp_reg, nullptr);
+ // src_len - src_pos < copy_len
+ OpRegRegReg(kOpSub, tmp_reg, rs_rAX, tmp_reg);
+ src_bad_len = OpCmpBranch(kCondLt, tmp_reg, rs_rDX, nullptr);
} else {
int32_t pos_val = mir_graph_->ConstantValue(rl_srcPos.orig_sreg);
if (pos_val == 0) {
src_bad_len = OpCmpBranch(kCondLt, rs_rAX, rs_rDX, nullptr);
} else {
- OpRegRegImm(kOpAdd, tmp_reg, rs_rDX, pos_val);
- src_bad_len = OpCmpBranch(kCondLt, rs_rAX, tmp_reg, nullptr);
+ // src_pos < src_len
+ src_bad_off = OpCmpImmBranch(kCondLt, rs_rAX, pos_val, nullptr);
+ // src_len - src_pos < copy_len
+ OpRegRegImm(kOpSub, tmp_reg, rs_rAX, pos_val);
+ src_bad_len = OpCmpBranch(kCondLt, tmp_reg, rs_rDX, nullptr);
}
}
LIR* dstPos_negative = nullptr;
LIR* dst_bad_len = nullptr;
+ LIR* dst_bad_off = nullptr;
LoadValueDirectFixed(rl_dst, rs_rAX);
LoadWordDisp(rs_rAX, mirror::Array::LengthOffset().Int32Value(), rs_rAX);
if (!rl_dstPos.is_const) {
LoadValueDirectFixed(rl_dstPos, tmp_reg);
dstPos_negative = OpCmpImmBranch(kCondLt, tmp_reg, 0, nullptr);
- OpRegRegReg(kOpAdd, tmp_reg, tmp_reg, rs_rDX);
- dst_bad_len = OpCmpBranch(kCondLt, rs_rAX, tmp_reg, nullptr);
+ // dst_pos < dst_len
+ dst_bad_off = OpCmpBranch(kCondLt, rs_rAX, tmp_reg, nullptr);
+ // dst_len - dst_pos < copy_len
+ OpRegRegReg(kOpSub, tmp_reg, rs_rAX, tmp_reg);
+ dst_bad_len = OpCmpBranch(kCondLt, tmp_reg, rs_rDX, nullptr);
} else {
int32_t pos_val = mir_graph_->ConstantValue(rl_dstPos.orig_sreg);
if (pos_val == 0) {
dst_bad_len = OpCmpBranch(kCondLt, rs_rAX, rs_rDX, nullptr);
} else {
- OpRegRegImm(kOpAdd, tmp_reg, rs_rDX, pos_val);
- dst_bad_len = OpCmpBranch(kCondLt, rs_rAX, tmp_reg, nullptr);
+ // dst_pos < dst_len
+ dst_bad_off = OpCmpImmBranch(kCondLt, rs_rAX, pos_val, nullptr);
+ // dst_len - dst_pos < copy_len
+ OpRegRegImm(kOpSub, tmp_reg, rs_rAX, pos_val);
+ dst_bad_len = OpCmpBranch(kCondLt, tmp_reg, rs_rDX, nullptr);
}
}
// Everything is checked now.
@@ -1198,11 +1212,15 @@ bool X86Mir2Lir::GenInlinedArrayCopyCharArray(CallInfo* info) {
src_null_branch->target = check_failed;
if (srcPos_negative != nullptr)
srcPos_negative ->target = check_failed;
+ if (src_bad_off != nullptr)
+ src_bad_off->target = check_failed;
if (src_bad_len != nullptr)
src_bad_len->target = check_failed;
dst_null_branch->target = check_failed;
if (dstPos_negative != nullptr)
dstPos_negative->target = check_failed;
+ if (dst_bad_off != nullptr)
+ dst_bad_off->target = check_failed;
if (dst_bad_len != nullptr)
dst_bad_len->target = check_failed;
AddIntrinsicSlowPath(info, launchpad_branch, return_point);