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 <private/bionic_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 pld [r0, #0] 42 push {r0, lr} 43 .save {r0, lr} 44 .cfi_def_cfa_offset 8 45 .cfi_rel_offset r0, 0 46 .cfi_rel_offset lr, 4 47 push {r4, r5} 48 .save {r4, r5} 49 .cfi_adjust_cfa_offset 8 50 .cfi_rel_offset r4, 0 51 .cfi_rel_offset r5, 4 52 53 mov lr, r2 54 55 // Save the dst register to r5 56 mov r5, r0 57 58 // Zero out r4 59 eor r4, r4, r4 60 61 // r1 contains the address of the string to count. 62.L_strlen_start: 63 mov r0, r1 64 65 ands r3, r0, #7 66 bne .L_align_src 67 68 .p2align 2 69.L_mainloop: 70 ldmia r1!, {r2, r3} 71 72 pld [r1, #64] 73 74 sub ip, r2, #0x01010101 75 bic ip, ip, r2 76 ands ip, ip, #0x80808080 77 bne .L_zero_in_first_register 78 79 sub ip, r3, #0x01010101 80 bic ip, ip, r3 81 ands ip, ip, #0x80808080 82 bne .L_zero_in_second_register 83 b .L_mainloop 84 85.L_zero_in_first_register: 86 sub r3, r1, r0 87 // Check for zero in byte 0. 88 lsls r2, ip, #17 89 beq .L_check_byte1_reg1 90 91 sub r3, r3, #8 92 b .L_finish 93 94.L_check_byte1_reg1: 95 bcc .L_check_byte2_reg1 96 97 sub r3, r3, #7 98 b .L_finish 99 100.L_check_byte2_reg1: 101 // Check for zero in byte 2. 102 tst ip, #0x800000 103 it ne 104 subne r3, r3, #6 105 bne .L_finish 106 sub r3, r3, #5 107 b .L_finish 108 109.L_zero_in_second_register: 110 sub r3, r1, r0 111 // Check for zero in byte 0. 112 lsls r2, ip, #17 113 beq .L_check_byte1_reg2 114 115 sub r3, r3, #4 116 b .L_finish 117 118.L_check_byte1_reg2: 119 bcc .L_check_byte2_reg2 120 121 sub r3, r3, #3 122 b .L_finish 123 124.L_check_byte2_reg2: 125 // Check for zero in byte 2. 126 tst ip, #0x800000 127 it ne 128 subne r3, r3, #2 129 bne .L_finish 130 sub r3, r3, #1 131 b .L_finish 132 133.L_align_src: 134 // Align to a double word (64 bits). 135 rsb r3, r3, #8 136 lsls ip, r3, #31 137 beq .L_align_to_32 138 139 ldrb r2, [r1], #1 140 cbz r2, .L_done 141 142.L_align_to_32: 143 bcc .L_align_to_64 144 145 ldrb r2, [r1], #1 146 cbz r2, .L_done 147 ldrb r2, [r1], #1 148 cbz r2, .L_done 149 150.L_align_to_64: 151 tst r3, #4 152 beq .L_mainloop 153 ldr r2, [r1], #4 154 155 sub ip, r2, #0x01010101 156 bic ip, ip, r2 157 ands ip, ip, #0x80808080 158 bne .L_zero_in_second_register 159 b .L_mainloop 160 161.L_done: 162 sub r3, r1, r0 163 sub r3, r3, #1 164 165.L_finish: 166 cmp r4, #0 167 bne .L_strlen_done 168 169 // Time to get the dst string length. 170 mov r1, r5 171 172 // Save the original source address to r5. 173 mov r5, r0 174 175 // Save the current length (adding 1 for the terminator). 176 add r4, r3, #1 177 b .L_strlen_start 178 179 // r0 holds the pointer to the dst string. 180 // r3 holds the dst string length. 181 // r4 holds the src string length + 1. 182.L_strlen_done: 183 add r2, r3, r4 184 cmp r2, lr 185 bhi __strcat_chk_fail 186 187 // Set up the registers for the memcpy code. 188 mov r1, r5 189 pld [r1, #64] 190 mov r2, r4 191 add r0, r0, r3 192 pop {r4, r5} 193 194 // Fall through into the memcpy_base function. 195END(__strcat_chk) 196 197#define MEMCPY_BASE __strcat_chk_memcpy_base 198#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned 199#include "memcpy_base.S" 200 201ENTRY_PRIVATE(__strcat_chk_fail) 202 .save {r0, lr} 203 .save {r4, r5} 204 .cfi_def_cfa_offset 8 205 .cfi_rel_offset r0, 0 206 .cfi_rel_offset lr, 4 207 .cfi_adjust_cfa_offset 8 208 .cfi_rel_offset r4, 0 209 .cfi_rel_offset r5, 4 210 211 ldr r0, error_message 212 ldr r1, error_code 2131: 214 add r0, pc 215 bl __fortify_chk_fail 216error_code: 217 .word BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW 218error_message: 219 .word error_string-(1b+4) 220END(__strcat_chk_fail) 221 222 .data 223error_string: 224 .string "strcat: prevented write past end of buffer" 225