Subject: port-pc532/7710: strcmp can read past terminating null and cause a core dump
To: None <>
From: Ian Dall <>
List: netbsd-bugs
Date: 06/05/1999 06:35:46
>Number:         7710
>Category:       port-pc532
>Synopsis:       strcmp can read past terminating null and cause a core dump
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    port-pc532-maintainer (NetBSD/pc532 Portmaster)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Jun  5 06:35:00 1999
>Originator:     Ian Dall
>Release:        <NetBSD-current source date> 1.4C
System: NetBSD 1.4C NetBSD 1.4C (SIBYL) #1: Tue Jun 1 15:34:02 CST 1999 pc532

strcmp uses double word compares to speed comparison. It double word aligns S2
ensuring that the null byte in S2 is always detected before cross a page boundary, but
in the case where S2 is longer than S1 the (last) double word compare can cause
up to 3 bytes to be read from S1 past the terminating null. If so doing causes
a unmapped memory to be read a SIGSEGV results.

This is not easy to fix keeping the same approach. One could use the double word
approach up to a page boundary, tip toe across the page boundary a byte at a time
and then continue double word at a time.

However, in the short term, it is better to be correct than fast so I propose
strcmp be adapted from strncmp but with effectively infinite n. It is not clear
how useful these clever algorithms are in practice anyway as they have more
overhead for short strings, presumably the most common case. Here is a simple
strcpy.S in its entirety.

/*	$NetBSD: strcmp.S,v 1.3 1998/04/03 22:58:10 matthias Exp $	*/

 * Written by Matthias Pfaller, 1996
 * Public domain.

#include <machine/asm.h>

#if defined(LIBC_SCCS)
	RCSID("$NetBSD: strcmp.S,v 1.3 1998/04/03 22:58:10 matthias Exp $")

 * int
 * strcmp(const char *s1, const char *s2)
KENTRY(strcmp, 12)
	enter	[r4],0
	movd	-1,r0
	movd	B_ARG0,r1
	movd	B_ARG1,r2
	movqd	0,r4
	cmpsb	u
	bfc	0f
	cmpb	0(r1),0(r2)
0:	movqd	0,r0
	beq	1f
	movqd	-1,r0
	blo	1f
	movqd	1,r0
1:	exit	[r4]
	ret	ARGS