-----Original Message----- From: wine-devel-admin@winehq.com [mailto:wine-devel-admin@winehq.com]On Behalf Of Alexandre Julliard Sent: Monday, December 02, 2002 9:03 AM To: Shachar Shemesh Cc: David Laight; David Fraser; Shachar Shemesh; Francois Gouget; wine-devel@winehq.com Subject: Re: strcat+strcat+strcat == baaad
Shachar Shemesh winehebhaim@sun.consumer.org.il writes:
I suggest implementing strlcat and strlcpy, as in OpenBSD.
I can write
them, but I'm not sure where to place them. They should either be inlined (as in - implemented in an include file as a static
func), or
in some library that will be linked (statically, I hope). Ideas?
We don't need that, there are Windows API functions like lstrcpyn that can be used for that. And in any case the right approach to writing correct and secure code is not to truncate every string in sight to some fixed buffer size; it's to make sure you allocate buffers of the right size, and then you can use standard strcpy/strcat/sprintf/etc. without worrying about lengths.
You're right in theory but you're partly wrong in practice. Some time back I changed a shared library which had been used by ten or so developers for about eight years. I changed all possible unspecified length string copies and concatenates to versions with length limits. The programs using the library crashed less and displayed bad output less. Nobody noticed any speed change there might have been. We all had access to all of the source code involved and none of it was deliberately hostile to the library. The changes caught things the application programmers had missed in their testing and odd or corrupt data which ended up in the databases and made them less harmful. It was then also easier to follow up and fix "the program displayed xyz trash here" than it was to fix "my PC crashed" or "your program died".
As programmers we all try to follow the limits and take care with buffer sizes and lengths and validation. We all fail and we all fail to catch every time we fail. That's just the nature of bugs and what we do. Buffer length issues are particularly hard to find and no realistic testing for a project the size of wine will catch them all.
Wine also needs to remember that hostile Windows program developers may deliberately try to break programs under wine by passing invalid parameters. Even if wine doesn't check all of those, it shouldn't die when it happens. At least one company has an interest in breaking wine when running its programs and coding defensively is a prudent thing.
Performance is unknown and won't be known until any possible shared function is implemented. Just announce it with the length parameter and do it with a define. Let the person who implements it decide whether to use strcat, strlcat or whatever in the first implementation, a function or inline or whatever. Six months or a year from now someone can try different implementations to see whether there is a speed difference. Then they can do something about selecting the most efficient. It's an issue, so deal with it, but there's no way to know today which will be the best implementation because it depends on the data and it is obvious that nobody knows the data well enough to be certain which will work best. If you don't like the strlcat implementeation, then you can try it with strcat and tell everyone how much faster it is when the l is ignored. Or not.
Even if the l is eventually ignored in production, having it around offers the opportunity to turn it on with a compile option and/or to use it for assert sanity checking in a debug build.
Finally, hi.:) Just started monitoring this list because I'm helping to get a Windows application (OzWin) working under wine.
James Day
___________________________________________________ The ALL NEW CS2000 from CompuServe Better! Faster! More Powerful! 250 FREE hours! Sign-on Now! http://www.compuserve.com/trycsrv/cs2000/webmail/
vkxzjq6lg@cswebmail.com writes:
Wine also needs to remember that hostile Windows program developers may deliberately try to break programs under wine by passing invalid parameters. Even if wine doesn't check all of those, it shouldn't die when it happens.
Yes it should, just like glibc should crash if you pass it bad pointers. What you are suggesting is the Microsoft approach: swipe bugs under the rug and let the app stumble along a bit further before dying, possibly corrupting files in the process. It's the kind of thinking that leads to having an exception handler inside strlen() like Windows does. It's just plain wrong.
(Of course we have to be compatible, and we have to hide bugs where actual applications depend on Windows doing it; but that doesn't mean it's the right philosophy)
On December 5, 2002 11:16 am, Alexandre Julliard wrote:
It's the kind of thinking that leads to having an exception handler inside strlen() like Windows does. It's just plain wrong.
<nod/>. This is generally true for other things as well:
1. Many places in our code where we have invariant like pointer p is never NULL, yet we always have:
if (!p) return NULL; /* or whatever error condition */
Such a check is harmful (hides bugs), slow (useless runtime check), bloat (more generated code), ugly (clutters the code), at the very least. Just Don't Do It (TM) -- let the code crash.
2. ZeroMemory when we don't need to, when we pass struct internally, yet same functions can be called externally with no guarantee that the struct has unused field zeroed out.
3. In general, we have all sort of 'defensive programming' checks for invariants. Problem is, we never going to catch bugs in this area this way. Just use assert() if you feel a check is needed.
In short, this defensive programming crap is just that: crap.