mirror of
https://github.com/torvalds/linux.git
synced 2024-12-17 08:31:39 +00:00
637a99022f
Commit 0119536c
, which added the assembly version of strncmp to
powerpc, mentions that it adds two instructions to the version from
boot/string.S to allow it to handle len=0. Unfortunately, it doesn't
always return 0 when that is the case. The length is passed in r5, but
the return value is passed back in r3. In certain cases, this will
happen to work. Otherwise it will pass back the address of the first
string as the return value.
This patch lifts the len <= 0 handling code from memcpy to handle that
case.
Reported by: Christian_Sellars@symantec.com
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
CC: <stable@kernel.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
208 lines
3.4 KiB
ArmAsm
208 lines
3.4 KiB
ArmAsm
/*
|
|
* String handling functions for PowerPC.
|
|
*
|
|
* Copyright (C) 1996 Paul Mackerras.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*/
|
|
#include <asm/processor.h>
|
|
#include <asm/errno.h>
|
|
#include <asm/ppc_asm.h>
|
|
|
|
.section __ex_table,"a"
|
|
PPC_LONG_ALIGN
|
|
.text
|
|
|
|
_GLOBAL(strcpy)
|
|
addi r5,r3,-1
|
|
addi r4,r4,-1
|
|
1: lbzu r0,1(r4)
|
|
cmpwi 0,r0,0
|
|
stbu r0,1(r5)
|
|
bne 1b
|
|
blr
|
|
|
|
/* This clears out any unused part of the destination buffer,
|
|
just as the libc version does. -- paulus */
|
|
_GLOBAL(strncpy)
|
|
cmpwi 0,r5,0
|
|
beqlr
|
|
mtctr r5
|
|
addi r6,r3,-1
|
|
addi r4,r4,-1
|
|
1: lbzu r0,1(r4)
|
|
cmpwi 0,r0,0
|
|
stbu r0,1(r6)
|
|
bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
|
|
bnelr /* if we didn't hit a null char, we're done */
|
|
mfctr r5
|
|
cmpwi 0,r5,0 /* any space left in destination buffer? */
|
|
beqlr /* we know r0 == 0 here */
|
|
2: stbu r0,1(r6) /* clear it out if so */
|
|
bdnz 2b
|
|
blr
|
|
|
|
_GLOBAL(strcat)
|
|
addi r5,r3,-1
|
|
addi r4,r4,-1
|
|
1: lbzu r0,1(r5)
|
|
cmpwi 0,r0,0
|
|
bne 1b
|
|
addi r5,r5,-1
|
|
1: lbzu r0,1(r4)
|
|
cmpwi 0,r0,0
|
|
stbu r0,1(r5)
|
|
bne 1b
|
|
blr
|
|
|
|
_GLOBAL(strcmp)
|
|
addi r5,r3,-1
|
|
addi r4,r4,-1
|
|
1: lbzu r3,1(r5)
|
|
cmpwi 1,r3,0
|
|
lbzu r0,1(r4)
|
|
subf. r3,r0,r3
|
|
beqlr 1
|
|
beq 1b
|
|
blr
|
|
|
|
_GLOBAL(strncmp)
|
|
PPC_LCMPI r5,0
|
|
ble- 2f
|
|
mtctr r5
|
|
addi r5,r3,-1
|
|
addi r4,r4,-1
|
|
1: lbzu r3,1(r5)
|
|
cmpwi 1,r3,0
|
|
lbzu r0,1(r4)
|
|
subf. r3,r0,r3
|
|
beqlr 1
|
|
bdnzt eq,1b
|
|
blr
|
|
2: li r3,0
|
|
blr
|
|
|
|
_GLOBAL(strlen)
|
|
addi r4,r3,-1
|
|
1: lbzu r0,1(r4)
|
|
cmpwi 0,r0,0
|
|
bne 1b
|
|
subf r3,r3,r4
|
|
blr
|
|
|
|
_GLOBAL(memcmp)
|
|
cmpwi 0,r5,0
|
|
ble- 2f
|
|
mtctr r5
|
|
addi r6,r3,-1
|
|
addi r4,r4,-1
|
|
1: lbzu r3,1(r6)
|
|
lbzu r0,1(r4)
|
|
subf. r3,r0,r3
|
|
bdnzt 2,1b
|
|
blr
|
|
2: li r3,0
|
|
blr
|
|
|
|
_GLOBAL(memchr)
|
|
cmpwi 0,r5,0
|
|
ble- 2f
|
|
mtctr r5
|
|
addi r3,r3,-1
|
|
1: lbzu r0,1(r3)
|
|
cmpw 0,r0,r4
|
|
bdnzf 2,1b
|
|
beqlr
|
|
2: li r3,0
|
|
blr
|
|
|
|
_GLOBAL(__clear_user)
|
|
addi r6,r3,-4
|
|
li r3,0
|
|
li r5,0
|
|
cmplwi 0,r4,4
|
|
blt 7f
|
|
/* clear a single word */
|
|
11: stwu r5,4(r6)
|
|
beqlr
|
|
/* clear word sized chunks */
|
|
andi. r0,r6,3
|
|
add r4,r0,r4
|
|
subf r6,r0,r6
|
|
srwi r0,r4,2
|
|
andi. r4,r4,3
|
|
mtctr r0
|
|
bdz 7f
|
|
1: stwu r5,4(r6)
|
|
bdnz 1b
|
|
/* clear byte sized chunks */
|
|
7: cmpwi 0,r4,0
|
|
beqlr
|
|
mtctr r4
|
|
addi r6,r6,3
|
|
8: stbu r5,1(r6)
|
|
bdnz 8b
|
|
blr
|
|
90: mr r3,r4
|
|
blr
|
|
91: mfctr r3
|
|
slwi r3,r3,2
|
|
add r3,r3,r4
|
|
blr
|
|
92: mfctr r3
|
|
blr
|
|
|
|
.section __ex_table,"a"
|
|
PPC_LONG 11b,90b
|
|
PPC_LONG 1b,91b
|
|
PPC_LONG 8b,92b
|
|
.text
|
|
|
|
_GLOBAL(__strncpy_from_user)
|
|
addi r6,r3,-1
|
|
addi r4,r4,-1
|
|
cmpwi 0,r5,0
|
|
beq 2f
|
|
mtctr r5
|
|
1: lbzu r0,1(r4)
|
|
cmpwi 0,r0,0
|
|
stbu r0,1(r6)
|
|
bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
|
|
beq 3f
|
|
2: addi r6,r6,1
|
|
3: subf r3,r3,r6
|
|
blr
|
|
99: li r3,-EFAULT
|
|
blr
|
|
|
|
.section __ex_table,"a"
|
|
PPC_LONG 1b,99b
|
|
.text
|
|
|
|
/* r3 = str, r4 = len (> 0), r5 = top (highest addr) */
|
|
_GLOBAL(__strnlen_user)
|
|
addi r7,r3,-1
|
|
subf r6,r7,r5 /* top+1 - str */
|
|
cmplw 0,r4,r6
|
|
bge 0f
|
|
mr r6,r4
|
|
0: mtctr r6 /* ctr = min(len, top - str) */
|
|
1: lbzu r0,1(r7) /* get next byte */
|
|
cmpwi 0,r0,0
|
|
bdnzf 2,1b /* loop if --ctr != 0 && byte != 0 */
|
|
addi r7,r7,1
|
|
subf r3,r3,r7 /* number of bytes we have looked at */
|
|
beqlr /* return if we found a 0 byte */
|
|
cmpw 0,r3,r4 /* did we look at all len bytes? */
|
|
blt 99f /* if not, must have hit top */
|
|
addi r3,r4,1 /* return len + 1 to indicate no null found */
|
|
blr
|
|
99: li r3,0 /* bad address, return 0 */
|
|
blr
|
|
|
|
.section __ex_table,"a"
|
|
PPC_LONG 1b,99b
|