__strcat_chk.S revision 68b67113a44311b3568027af5893e316f63ec556
1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *  * Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 *  * Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in
12 *    the documentation and/or other materials provided with the
13 *    distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <machine/asm.h>
30#include "private/libc_events.h"
31
32    .syntax unified
33    .fpu    neon
34    .thumb
35    .thumb_func
36
37// Get the length of src string, then get the source of the dst string.
38// Check that the two lengths together don't exceed the threshold, then
39// do a memcpy of the data.
40ENTRY(__strcat_chk)
41    .cfi_startproc
42    pld     [r0, #0]
43    push    {r0, lr}
44    .save   {r0, lr}
45    .cfi_def_cfa_offset 8
46    .cfi_rel_offset r0, 0
47    .cfi_rel_offset lr, 4
48    push    {r4, r5}
49    .save   {r4, r5}
50    .cfi_adjust_cfa_offset 8
51    .cfi_rel_offset r4, 0
52    .cfi_rel_offset r5, 4
53
54    mov     lr, r2
55
56    // Save the dst register to r5
57    mov     r5, r0
58
59    // Zero out r4
60    eor     r4, r4, r4
61
62    // r1 contains the address of the string to count.
63.L_strlen_start:
64    mov     r0, r1
65
66    ands    r3, r0, #7
67    bne     .L_align_src
68
69    .p2align 2
70.L_mainloop:
71    ldmia   r1!, {r2, r3}
72
73    pld     [r1, #64]
74
75    sub     ip, r2, #0x01010101
76    bic     ip, ip, r2
77    ands    ip, ip, #0x80808080
78    bne     .L_zero_in_first_register
79
80    sub     ip, r3, #0x01010101
81    bic     ip, ip, r3
82    ands    ip, ip, #0x80808080
83    bne     .L_zero_in_second_register
84    b       .L_mainloop
85
86.L_zero_in_first_register:
87    sub     r3, r1, r0
88    // Check for zero in byte 0.
89    lsls    r2, ip, #17
90    beq     .L_check_byte1_reg1
91
92    sub     r3, r3, #8
93    b       .L_finish
94
95.L_check_byte1_reg1:
96    bcc     .L_check_byte2_reg1
97
98    sub     r3, r3, #7
99    b       .L_finish
100
101.L_check_byte2_reg1:
102    // Check for zero in byte 2.
103    tst     ip, #0x800000
104    it      ne
105    subne   r3, r3, #6
106    bne     .L_finish
107    sub     r3, r3, #5
108    b       .L_finish
109
110.L_zero_in_second_register:
111    sub     r3, r1, r0
112    // Check for zero in byte 0.
113    lsls    r2, ip, #17
114    beq     .L_check_byte1_reg2
115
116    sub     r3, r3, #4
117    b       .L_finish
118
119.L_check_byte1_reg2:
120    bcc     .L_check_byte2_reg2
121
122    sub     r3, r3, #3
123    b       .L_finish
124
125.L_check_byte2_reg2:
126    // Check for zero in byte 2.
127    tst     ip, #0x800000
128    it      ne
129    subne   r3, r3, #2
130    bne     .L_finish
131    sub     r3, r3, #1
132    b       .L_finish
133
134.L_align_src:
135    // Align to a double word (64 bits).
136    rsb     r3, r3, #8
137    lsls    ip, r3, #31
138    beq     .L_align_to_32
139
140    ldrb    r2, [r1], #1
141    cbz     r2, .L_done
142
143.L_align_to_32:
144    bcc     .L_align_to_64
145
146    ldrb    r2, [r1], #1
147    cbz     r2, .L_done
148    ldrb    r2, [r1], #1
149    cbz     r2, .L_done
150
151.L_align_to_64:
152    tst     r3, #4
153    beq     .L_mainloop
154    ldr     r2, [r1], #4
155
156    sub     ip, r2, #0x01010101
157    bic     ip, ip, r2
158    ands    ip, ip, #0x80808080
159    bne     .L_zero_in_second_register
160    b       .L_mainloop
161
162.L_done:
163    sub     r3, r1, r0
164    sub     r3, r3, #1
165
166.L_finish:
167    cmp     r4, #0
168    bne     .L_strlen_done
169
170    // Time to get the dst string length.
171    mov     r1, r5
172
173    // Save the original source address to r5.
174    mov     r5, r0
175
176    // Save the current length (adding 1 for the terminator).
177    add     r4, r3, #1
178    b       .L_strlen_start
179
180    // r0 holds the pointer to the dst string.
181    // r3 holds the dst string length.
182    // r4 holds the src string length + 1.
183.L_strlen_done:
184    add     r2, r3, r4
185    cmp     r2, lr
186    bhi     __strcat_chk_fail
187
188    // Set up the registers for the memcpy code.
189    mov     r1, r5
190    pld     [r1, #64]
191    mov     r2, r4
192    add     r0, r0, r3
193    pop     {r4, r5}
194
195    // Fall through into the memcpy_base function.
196    .cfi_endproc
197END(__strcat_chk)
198
199#define MEMCPY_BASE         __strcat_chk_memcpy_base
200#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned
201#include "memcpy_base.S"
202
203ENTRY_PRIVATE(__strcat_chk_fail)
204    .cfi_startproc
205
206    .save   {r0, lr}
207    .save   {r4, r5}
208    .cfi_def_cfa_offset 8
209    .cfi_rel_offset r0, 0
210    .cfi_rel_offset lr, 4
211    .cfi_adjust_cfa_offset 8
212    .cfi_rel_offset r4, 0
213    .cfi_rel_offset r5, 4
214
215    ldr     r0, error_message
216    ldr     r1, error_code
2171:
218    add     r0, pc
219    bl      __fortify_chk_fail
220error_code:
221    .word   BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW
222error_message:
223    .word   error_string-(1b+4)
224
225    .cfi_endproc
226END(__strcat_chk_fail)
227
228    .data
229error_string:
230    .string "strcat: prevented write past end of buffer"
231