Bug 1478623 - Add r/w constraints to modified registers to asm blocks in mpi_arm.c. r=fkiefer
authorMike Hommey <mh@glandium.org>
Thu, 26 Jul 2018 20:39:36 +0900
changeset 14437 09ab3310e71028dbdbf6846289cb4d3cea249534
parent 14436 e2a0d66b122f873a5ca370de7674af377279e37e
child 14438 f89a359d962a875c8729ce0a4a750566f486a9f0
push id3154
push usermh@glandium.org
push dateThu, 02 Aug 2018 10:21:18 +0000
reviewersfkiefer
bugs1478623, 1477929
Bug 1478623 - Add r/w constraints to modified registers to asm blocks in mpi_arm.c. r=fkiefer While bug 1477929 fixed the obvious build failure, it still allowed the compiler to break things when it inlines the mpi_arm.c functions into its callers via LTO. The problem is that all those assembly blocks take a length as input in a register, and decrement that register. They also update both registers they're passed in with pointers, via post-indexed offsets on ldr and str. But the constraints are not explicit about those writes to the registers, so the compiler may decide to reuse them as if they had their original value in code following the inlined code. It actually happily does so, which leads to interesting crashes.
lib/freebl/mpi/mpi_arm.c
--- a/lib/freebl/mpi/mpi_arm.c
+++ b/lib/freebl/mpi/mpi_arm.c
@@ -24,27 +24,27 @@ s_mpv_mul_d(const mp_digit *a, mp_size a
 #else
         "cmp     %1, r5\n" /* r5 is 0 now */
         "beq     2f\n"
 #endif
 
         "1:\n"
         "mov     r4, #0\n"
         "ldr     r6, [%0], #4\n"
-        "umlal   r5, r4, r6, %2\n"
-        "str     r5, [%3], #4\n"
+        "umlal   r5, r4, r6, %3\n"
+        "str     r5, [%2], #4\n"
         "mov     r5, r4\n"
 
         "subs    %1, #1\n"
         "bne     1b\n"
 
         "2:\n"
-        "str     r5, [%3]\n"
-        :
-        : "r"(a), "l"(a_len), "r"(b), "r"(c)
+        "str     r5, [%2]\n"
+        : "+r"(a), "+l"(a_len), "+r"(c)
+        : "r"(b)
         : "memory", "cc", "%r4", "%r5", "%r6");
 }
 
 void
 s_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
 {
     __asm__ __volatile__(
         "mov     r5, #0\n"
@@ -52,76 +52,76 @@ s_mpv_mul_d_add(const mp_digit *a, mp_si
         "cbz     %1, 2f\n"
 #else
         "cmp     %1, r5\n" /* r5 is 0 now */
         "beq     2f\n"
 #endif
 
         "1:\n"
         "mov     r4, #0\n"
-        "ldr     r6, [%3]\n"
+        "ldr     r6, [%2]\n"
         "adds    r5, r6\n"
         "adc     r4, r4, #0\n"
 
         "ldr     r6, [%0], #4\n"
-        "umlal   r5, r4, r6, %2\n"
-        "str     r5, [%3], #4\n"
+        "umlal   r5, r4, r6, %3\n"
+        "str     r5, [%2], #4\n"
         "mov     r5, r4\n"
 
         "subs    %1, #1\n"
         "bne     1b\n"
 
         "2:\n"
-        "str     r5, [%3]\n"
-        :
-        : "r"(a), "l"(a_len), "r"(b), "r"(c)
+        "str     r5, [%2]\n"
+        : "+r"(a), "+l"(a_len), "+r"(c)
+        : "r"(b)
         : "memory", "cc", "%r4", "%r5", "%r6");
 }
 
 void
 s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
 {
     if (!a_len)
         return;
 
     __asm__ __volatile__(
         "mov     r5, #0\n"
 
         "1:\n"
         "mov     r4, #0\n"
-        "ldr     r6, [%3]\n"
+        "ldr     r6, [%2]\n"
         "adds    r5, r6\n"
         "adc     r4, r4, #0\n"
         "ldr     r6, [%0], #4\n"
-        "umlal   r5, r4, r6, %2\n"
-        "str     r5, [%3], #4\n"
+        "umlal   r5, r4, r6, %3\n"
+        "str     r5, [%2], #4\n"
         "mov     r5, r4\n"
 
         "subs    %1, #1\n"
         "bne     1b\n"
 
 #ifdef __thumb2__
         "cbz     r4, 3f\n"
 #else
         "cmp     r4, #0\n"
         "beq     3f\n"
 #endif
 
         "2:\n"
         "mov     r4, #0\n"
-        "ldr     r6, [%3]\n"
+        "ldr     r6, [%2]\n"
         "adds    r5, r6\n"
         "adc     r4, r4, #0\n"
-        "str     r5, [%3], #4\n"
+        "str     r5, [%2], #4\n"
         "movs    r5, r4\n"
         "bne     2b\n"
 
         "3:\n"
-        :
-        : "r"(a), "r"(a_len), "r"(b), "r"(c)
+        : "+r"(a), "+l"(a_len), "+r"(c)
+        : "r"(b)
         : "memory", "cc", "%r4", "%r5", "%r6");
 }
 #endif
 
 #ifdef MP_ASSEMBLY_SQUARE
 void
 s_mpv_sqr_add_prop(const mp_digit *pa, mp_size a_len, mp_digit *ps)
 {
@@ -162,14 +162,14 @@ s_mpv_sqr_add_prop(const mp_digit *pa, m
         "ldr     r5, [%2]\n"
         "adds    r3, r5\n"
         "adc     r4, r4, #0\n"
         "str     r3, [%2], #4\n"
         "movs    r3, r4\n"
         "bne     2b\n"
 
         "3:"
+        : "+r"(pa), "+r"(a_len), "+r"(ps)
         :
-        : "r"(pa), "r"(a_len), "r"(ps)
         : "memory", "cc", "%r3", "%r4", "%r5", "%r6");
 }
 #endif
 #endif