From patchwork Mon May 11 12:56:13 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 48278 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wg0-f72.google.com (mail-wg0-f72.google.com [74.125.82.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 6E3842121F for ; Mon, 11 May 2015 12:56:16 +0000 (UTC) Received: by wgtl5 with SMTP id l5sf39332638wgt.1 for ; Mon, 11 May 2015 05:56:15 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:x-original-sender:x-original-authentication-results :precedence:mailing-list:list-id:list-post:list-help:list-archive :list-unsubscribe; bh=wu/yHuH5UB8iQa4pdjYZtmy7zI4Bgf8n23BK5DFYp3A=; b=bQpuyCPsM5GS/35YvDIid5V1iwYb1aNsxY0xHsI1XBspvcJ4YprUwDGI3UF2/sl16h OWr8W1KHJUePKAzwnM+vyx5hQJKSAmQ1e3guEm/uvugeMX/qsGD3ubUoSeHaNT8ihSNo xPPwGpAgsjkdJObasCIlzJe9L8rkz5n/OSVEgwI9l9zsMtc26+Uhn+n1mJ60bkC1HZX4 tGUf6ub77MVTJwiIKsBDL5N0gLyRnXnEOFwzBDTQQkpVYMeCrnjjO0dkWZSAn/ziQAhJ gofu1Shtzmhsq1g/sRw/x5JyeirVO1VxrN3hMeNC3PeODXxxZDWdrux3qhJmYXzB7RbM EIGA== X-Gm-Message-State: ALoCoQmDvXR6NFjldQRPlTMCo6E9HeTyrgDLxDDRYrGxM3e56KmnOjBoVIUNeXBk6EGA3tjv3nkK X-Received: by 10.112.189.131 with SMTP id gi3mr7382680lbc.6.1431348975733; Mon, 11 May 2015 05:56:15 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.26.232 with SMTP id o8ls666365lag.39.gmail; Mon, 11 May 2015 05:56:15 -0700 (PDT) X-Received: by 10.112.72.132 with SMTP id d4mr8005732lbv.1.1431348975593; Mon, 11 May 2015 05:56:15 -0700 (PDT) Received: from mail-la0-f52.google.com (mail-la0-f52.google.com. [209.85.215.52]) by mx.google.com with ESMTPS id ms4si8321571lbb.65.2015.05.11.05.56.15 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 May 2015 05:56:15 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.52 as permitted sender) client-ip=209.85.215.52; Received: by layy10 with SMTP id y10so92425921lay.0 for ; Mon, 11 May 2015 05:56:15 -0700 (PDT) X-Received: by 10.153.6.36 with SMTP id cr4mr8207444lad.56.1431348975449; Mon, 11 May 2015 05:56:15 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.112.108.230 with SMTP id hn6csp1488816lbb; Mon, 11 May 2015 05:56:14 -0700 (PDT) X-Received: by 10.180.81.3 with SMTP id v3mr18915458wix.36.1431348974874; Mon, 11 May 2015 05:56:14 -0700 (PDT) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk. [2001:8b0:1d0::1]) by mx.google.com with ESMTPS id vf7si21912014wjc.127.2015.05.11.05.56.14 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Mon, 11 May 2015 05:56:14 -0700 (PDT) Received-SPF: none (google.com: pm215@archaic.org.uk does not designate permitted sender hosts) client-ip=2001:8b0:1d0::1; Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1YrnFl-0005YG-MR; Mon, 11 May 2015 13:56:13 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org Subject: [PATCH] target-arm: Avoid buffer overrun on UNPREDICTABLE ldrd/strd Date: Mon, 11 May 2015 13:56:13 +0100 Message-Id: <1431348973-21315-1-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: peter.maydell@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.52 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , A LDRD or STRD where rd is not an even number is UNPREDICTABLE. We were letting this fall through, which is OK unless rd is 15, in which case we would attempt to do a load_reg or store_reg to a nonexistent r16 for the second half of the double-word. Catch the odd-numbered-rd cases and UNDEF them instead. To do this we rearrange the structure of the code a little so we can put the UNDEF catches at the top before we've allocated TCG temporaries. Cc: qemu-stable@nongnu.org Signed-off-by: Peter Maydell --- Spotted as a result of clang's sanitizer warning about it while I was trying to debug a guest that had gone off the rails. target-arm/translate.c | 56 ++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/target-arm/translate.c b/target-arm/translate.c index 9116529..f8f72be 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -8423,34 +8423,30 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) } } else { int address_offset; - int load; + bool load = insn & (1 << 20); + bool doubleword = false; /* Misc load/store */ rn = (insn >> 16) & 0xf; rd = (insn >> 12) & 0xf; + + if (!load && (sh & 2)) { + /* doubleword */ + ARCH(5TE); + if (rd & 1) { + /* UNPREDICTABLE; we choose to UNDEF */ + goto illegal_op; + } + load = (sh & 1) == 0; + doubleword = true; + } + addr = load_reg(s, rn); if (insn & (1 << 24)) gen_add_datah_offset(s, insn, 0, addr); address_offset = 0; - if (insn & (1 << 20)) { - /* load */ - tmp = tcg_temp_new_i32(); - switch(sh) { - case 1: - gen_aa32_ld16u(tmp, addr, get_mem_index(s)); - break; - case 2: - gen_aa32_ld8s(tmp, addr, get_mem_index(s)); - break; - default: - case 3: - gen_aa32_ld16s(tmp, addr, get_mem_index(s)); - break; - } - load = 1; - } else if (sh & 2) { - ARCH(5TE); - /* doubleword */ - if (sh & 1) { + + if (doubleword) { + if (!load) { /* store */ tmp = load_reg(s, rd); gen_aa32_st32(tmp, addr, get_mem_index(s)); @@ -8459,7 +8455,6 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) tmp = load_reg(s, rd + 1); gen_aa32_st32(tmp, addr, get_mem_index(s)); tcg_temp_free_i32(tmp); - load = 0; } else { /* load */ tmp = tcg_temp_new_i32(); @@ -8469,15 +8464,28 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) tmp = tcg_temp_new_i32(); gen_aa32_ld32u(tmp, addr, get_mem_index(s)); rd++; - load = 1; } address_offset = -4; + } else if (load) { + /* load */ + tmp = tcg_temp_new_i32(); + switch (sh) { + case 1: + gen_aa32_ld16u(tmp, addr, get_mem_index(s)); + break; + case 2: + gen_aa32_ld8s(tmp, addr, get_mem_index(s)); + break; + default: + case 3: + gen_aa32_ld16s(tmp, addr, get_mem_index(s)); + break; + } } else { /* store */ tmp = load_reg(s, rd); gen_aa32_st16(tmp, addr, get_mem_index(s)); tcg_temp_free_i32(tmp); - load = 0; } /* Perform base writeback before the loaded value to ensure correct behavior with overlapping index registers.