Subject: lib/3583: strncpy() error in libc/time/localtime.c
To: None <gnats-bugs@gnats.netbsd.org>
From: David Holland <dholland@bordeaux.eecs.harvard.edu>
List: netbsd-bugs
Date: 05/07/1997 14:40:32
>Number:         3583
>Category:       lib
>Synopsis:       strncpy() doesn't guarantee null-termination
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    lib-bug-people (Library Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Wed May  7 12:05:01 1997
>Last-Modified:
>Originator:     dholland@eecs.harvard.edu
>Organization:
VINO project
>Release:        NetBSD-current May 7 1997
>Environment:

	N/A. Problem was detected in source code while merging the current 
	localtime into VINO's libc.

>Description:

	strncpy() doesn't produce null-terminated output when the input
	string doesn't fit in the output buffer. Therefore it's necessary
	to follow every strncpy() with output_buffer[size-1] = 0.

>How-To-Repeat:
	N/A.
>Fix:

This patch is against the current version of src/lib/libc/time/localtime.c,
and fixes the incorrect assumption that strncpy guarantees null-termination
of its output.


Index: localtime.c
===================================================================
RCS file: /home/vino/repo/src/libc/libc/time/localtime.c,v
retrieving revision 1.1.1.2
diff -C2 -r1.1.1.2 localtime.c
*** localtime.c	1997/05/07 17:15:41	1.1.1.2
--- localtime.c	1997/05/07 17:17:29
***************
*** 971,976 ****
  		return;
  	lcl_is_set = (strlen(name) < sizeof(lcl_TZname));
! 	if (lcl_is_set)
  		(void)strncpy(lcl_TZname, name, sizeof(lcl_TZname) - 1);
  
  #ifdef ALL_STATE
--- 971,978 ----
  		return;
  	lcl_is_set = (strlen(name) < sizeof(lcl_TZname));
! 	if (lcl_is_set) {
  		(void)strncpy(lcl_TZname, name, sizeof(lcl_TZname) - 1);
+ 		lcl_TZname[sizeof(lcl_TZname)-1] = 0;
+ 	}
  
  #ifdef ALL_STATE
***************
*** 992,995 ****
--- 994,998 ----
  		lclptr->ttis[0].tt_abbrind = 0;
  		(void)strncpy(lclptr->chars, gmt, sizeof(lclptr->chars) - 1);
+ 		lclptr->chars[sizeof(lclptr->chars)-1] = 0;
  	} else if (tzload(name, lclptr) != 0)
  		if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
>Audit-Trail:
>Unformatted: