|
|||||||||||
|
Re: Are bad developer libraries the problem with M$ software?
From: Tom Cosgrove <tcosgrove3579(at)lineone.net>
Date: Tue Nov 19 2002 - 09:24:19 EST
#2 is easier if the APIs are properly designed. The strn*() functions are good examples here. While they _can_ be used correctly, it's difficult, and correct use can't be verified by rapid inspection. The OpenBSD folks created strlcpy() and strlcat() for just this reason (see http://www.openbsd.org/papers/strlcpy-paper.ps) so they can do:
strlcpy(path, homedir, sizeof(path)) ;
strlcat(path, "/", sizeof(path)) ;
strlcat(path, ".foorc", sizeof(path)) ;
instead of something like:
strncpy(path, homedir, sizeof(path) - 1) ;
path[sizeof(path) - 1] = '\0' ;
Sensible use of return values is important too (as with the Microsoft _snprintf(), which just returns -1 if the buffer is too small, where the "standard" snprintf() calls give enough information to be able to resize the buffer correctly). A set of coding conventions also help. On all my projects, a function being passed a buffer (e.g. char *p) should also be passed the size of the buffer. Generally I make this something that can be calculated with sizeof(), so I would define the semantics to take a number of bytes, even for wide-character functions. That way I can do: wchar_t buffer[100] ; rc = function(buffer, sizeof(buffer)) ; On various projects I often find myself implementing wcslcpy() and wcslcat(), so I can do: wchar_t path[100] ;
wcslcpy(path, homedir, sizeof(path)) ;
wcslcat(path, L"/", sizeof(path)) ;
wcslcat(path, L".foorc", sizeof(path)) ;
It's much easier to use APIs like these, which have been designed correctly. It's much easier to audit code like this, when it's simpler to use (auditing complex code is non-trivial). There's also the memset() vs bzero() comments in Unix Network Programming, W Richard Stevens, p.8: occasionally one sees memset(p, sizeof(p), 0) ; i.e. getting the final two arguments the wrong way round. And following on from other comments in this thread, I have also seen cases of: struct foo *p ; p = malloc(sizeof(struct foo)) ;
:
memset(p, 0, sizeof(p)) ; It's all about having the right tools, and knowing how to use them. And even then we all make mistakes :-( Thanks
Tom Cosgrove
>>> Michael Howard 18-Nov-02 20:51 >>>
This simply proves my point - the 'n' versions are not necessarily any more secure than the non-'n' versions when people make mistakes like sizeof(*foo) thinking it's the same as strlen(foo) :-)
Cheers, Michael
This archive was generated by hypermail 2.1.8 : Wed Aug 23 2006 - 14:02:44 EDT |
||||||||||
|
|||||||||||