The SEI has published CMU/SEI-2006-TR-006 "Specifications for Managed
Strings" and released a "proof-of-concept" implementation of the managed
string library.
The specification, source code for the library, and other resources
related to managed strings are available for download from the CERT web
site at: http://www.cert.org/secure-coding/managedstring.html
The following is a brief summary of the managed string library:
The managed string library was developed in response to the need for a
string library that can improve the quality and security of newly
developed C-language programs while eliminating obstacles to widespread
adoption and possible standardization. As the name implies, the managed
string library is based on a dynamic approach; memory is allocated and
reallocated as required. This approach eliminates the possibility of
unbounded copies, null-termination errors, and truncation by ensuring
that there is always adequate space available for the resulting string
(including the terminating null character). The one exception is if
memory is exhausted; that is treated as an error condition. In this way,
the managed string library accomplishes the goal of indicating either
success or failure. The managed string library also protects against
improper data sanitization by (optionally) ensuring that all characters
in a string belong to a predefined set of "safe" characters.
rCs
--
Robert C. Seacord
Senior Vulnerability Analyst
CERT/CC
Work: 412-268-7608
FAX: 412-268-6989
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry. 87 4937
Robert Seacord wrote:
The SEI has published CMU/SEI-2006-TR-006 "Specifications for Managed
Strings" and released a "proof-of-concept" implementation of the managed
string library.
The specification, source code for the library, and other resources
related to managed strings are available for download from the CERT web
site at:
http://www.cert.org/secure-coding/managedstring.html
The following is a brief summary of the managed string library:
The managed string library was developed in response to the need for a
string library that can improve the quality and security of newly
developed C-language programs while eliminating obstacles to widespread
adoption and possible standardization.
I'm wondering whether or not you compared it to other available
libraries such as my own ( http://bstring.sf.net/ ) or James Anthill's
( http://www.and.org/vstr/ ) before engaging in this effort?
I understand that need for this solely from the security focus, but
your effort looks like it was born out of a very direct and narrow
approach that takes absolutely nothing else into account. Besides
being slow, the API is somewhat cumbersome, which makes inline usage
impossible. The whole charset filtering thing is not multithreading
friendly, and IMHO, a poorly focused solution to the system() problem.
Instead of hiding all the functionality in the managed string, why not
instead have a "filterstring()" function, or better yet, have a
"safesystem()" function? I have a more complete discussion in the
Bstrlib documentation ( http://bstring.cvs.sourceforge.net/*...t?pathrev=HEAD
, search for "Managed String Library").
Beyond just security concerns, there is 1) The "Software Crisis"
concern. This is the concern that writing software in a scalable
manner (i.e., writing millions of bug-free lines of code) is difficult
to do. 2) Performance. C's string operations often take an additional
O(n) penalty for having to implicitely call strlen(), or the
equivalent, redundantly. 3) The Clib's poor base functionality (no
insert/delete, split, replace, substring functions), additionally
hampered by its inability to deal with aliasing (so strcat(p,p) leads
to UB even though it has a compelling intuitive meaning).
Obviously, I think Bstrlib fares well by such criteria. My point,
though, is that the "Managed String Library" really does not do very
well at all. I think this is important because I think it will be hard
to compell developers to use Managed Strings (or TR 24731) if it
continues to propogate *other* weaknesses of the C std library while
only attempting to solving a very narrow problem.
I.e., I believe Bstrlib to be a better *SECURITY* solution than Managed
Strings (or TR 24731, or pretty much anything else short of a change in
language altogether) because it is more *compelling* to programmers to
use for *OTHER* reasons. I.e., it is not security gained by some
additionally necessary expended effort forcused solely on security, but
rather its a better way of dealing with strings overall which happens
to supply a good security system as a bonus. Bstrlib has been put
through its paces by other programmers who use it, regardless of their
reason (safety/security is certainly not the only reason). With
Managed Strings, it appears that you are starting from scratch.
Also unlike any other solution, the Bstrlib webpage also includes a
public statement on security, which gives a whole set of security
assertions that auditors can test the library against ( http://bstring.cvs.sourceforge.net/*...t?pathrev=HEAD
) How do Managed Strings compare in this regard? For example, in
terms of password input/manipulation, can your proposal make guarantees
that copies of string content be kept out of the heap (from a free or
realloc) outside of programmer control?
Since I have not submitted Bstrlib to the ANSI C committee, perhaps you
see this as a moot point. But what I would suggest to you is that you
at least *study* my library first, and see what ideas from it you
should incorporate into your proposal.
While I see the merit of your intentions, I don't see your effort as
quite there yet. Especially in light of open source alternatives such
as my library. At the very least, I think you should take libraries
such as mine as a yardstick by which to compare yours in developing it.
--
Paul Hsieh http://www.pobox.com/~qed/ http://bstring.sf.net/
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry. we******@gmail.com wrote:
[...] (so strcat(p,p) leads
to UB even though it has a compelling intuitive meaning).
What's the compelling intuitive meaning? To me, it means copy
characters from the start of p over the null that used to mark the end
of p and keep going until you crash.
--
Jonathan Leffler #include <disclaimer.h>
Email: jl******@earthlink.net, jl******@us.ibm.com
Guardian of DBD::Informix v2005.02 -- http://dbi.perl.org/
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Jonathan Leffler wrote:
we******@gmail.com wrote:
[...] (so strcat(p,p) leads
to UB even though it has a compelling intuitive meaning).
What's the compelling intuitive meaning? To me, it means copy
characters from the start of p over the null that used to mark the end
of p and keep going until you crash.
That's not an intuitive meaning. Its just an understanding of an
implementation anomoly. Perhaps for you, implementation details
changes your intuition.
Most people would intuitively think of this as simply replacing the
string with a doubled version of itself -- i.e., its analogous to the
C++ expression p += p for std::string's (and to be honest, I don't know
if that's legal or not), or just p = p + p in most other programming
languages.
You only *know* that this is not the case, because you know that strcat
is implemented as some variation of { d += strlen(d); while (*d++ =
*s++); } instead of { size_t ld = strlen(d), ls = strlen(s); memmove
(d+ld, s, ls); d[ld+ls] = '\0'; }. You know this because the first
variation is going to be faster. This is not intuition -- its just a
technical calculation.
--
Paul Hsieh http://www.pobox.com/~qed/ http://bstring.sf.net/
On 2006-07-27, we******@gmail.com <we******@gmail.comwrote:
Jonathan Leffler wrote:
>we******@gmail.com wrote:
[...] (so strcat(p,p) leads
to UB even though it has a compelling intuitive meaning).
What's the compelling intuitive meaning? To me, it means copy characters from the start of p over the null that used to mark the end of p and keep going until you crash.
That's not an intuitive meaning. Its just an understanding of an
implementation anomoly. Perhaps for you, implementation details
changes your intuition.
No, knowledge that C strings are null-terminated (which any C programmer
needs to know) suggests that intuitively. Either you calculate strlen(),
add a counter variable, and `for' your way through the string, or you
eliminate the counter and superfluous call to strlen(), and code it
efficiently.
It's more intuitive to use the more efficient, less code-intensive, and
easier-to-read version.
Most people would intuitively think of this as simply replacing the
string with a doubled version of itself -- i.e., its analogous to the
C++ expression p += p for std::string's (and to be honest, I don't know
if that's legal or not), or just p = p + p in most other programming
languages.
"Most people" are not C programmers; if you know enough to use strcat(),
you should have an understanding of how C strings work. (And indeed, I've
never seen a C textbook that introduced strcat() prior to introcuding C-
style strings.) (Although I've heard of some pretty terrible textbooks on
this group that I was fortunate enough to avoid!)
You only *know* that this is not the case, because you know that strcat
is implemented as some variation of { d += strlen(d); while (*d++ =
*s++); } instead of { size_t ld = strlen(d), ls = strlen(s); memmove
(d+ld, s, ls); d[ld+ls] = '\0'; }. You know this because the first
variation is going to be faster. This is not intuition -- its just a
technical calculation.
IMHO, _intuitively_, there is no other way to implement strcat().
--
Andrew Poelstra <website down>
To reach my email, use <email also down>
New server ETA: 1 days we******@gmail.com writes:
Jonathan Leffler wrote:
>we******@gmail.com wrote:
[...] (so strcat(p,p) leads
to UB even though it has a compelling intuitive meaning).
What's the compelling intuitive meaning? To me, it means copy characters from the start of p over the null that used to mark the end of p and keep going until you crash.
That's not an intuitive meaning. Its just an understanding of an
implementation anomoly. Perhaps for you, implementation details
changes your intuition.
[...]
In this case, intuition is not necessary. If you read the standard's
description of strcat(), you'll see:
... If copying takes place between objects that overlap, the
behavior is undefined.
Any decent description of strcat() (in a man page or text book, for
example) should have similar wording; if it doesn't, that's the fault
of the author of the documentation.
If you attempt to use strcat(), or any other function, without reading
a description of how it's supposed to work, you can't reasonably
expect any particular behavior.
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Andrew Poelstra wrote:
On 2006-07-27, we******@gmail.com <we******@gmail.comwrote:
>Jonathan Leffler wrote:
>>we******@gmail.com wrote: [...] (so strcat(p,p) leads to UB even though it has a compelling intuitive meaning). What's the compelling intuitive meaning? To me, it means copy characters from the start of p over the null that used to mark the end of p and keep going until you crash.
That's not an intuitive meaning. Its just an understanding of an implementation anomoly. Perhaps for you, implementation details changes your intuition.
No, knowledge that C strings are null-terminated (which any C programmer
needs to know) suggests that intuitively. Either you calculate strlen(),
add a counter variable, and `for' your way through the string, or you
eliminate the counter and superfluous call to strlen(), and code it
efficiently.
It's more intuitive to use the more efficient, less code-intensive, and
easier-to-read version.
[...]
IMHO, _intuitively_, there is no other way to implement strcat().
The argument from an implementors perspective shows how
easily we forget what was intuitive before we came to
think in terms of how to implement string functionality
in C.
Some can't even think of what strcat intuitively means
(append one string to another) without considering how
it's most sensibly implemented in terms of pointer
operations.
-- James
Keith Thompson wrote:
we******@gmail.com writes:
Jonathan Leffler wrote:
we******@gmail.com wrote:
[...] (so strcat(p,p) leads
to UB even though it has a compelling intuitive meaning).
What's the compelling intuitive meaning? To me, it means copy
characters from the start of p over the null that used to mark the end
of p and keep going until you crash.
That's not an intuitive meaning. Its just an understanding of an
implementation anomoly. Perhaps for you, implementation details
changes your intuition.
[...]
In this case, intuition is not necessary.
Just *SAYING* this is the ultimate indictment of the C language. If
the language doesn't match your intuition, then its just takes that
much more effort to program in it.
[...] If you read the standard's
description of strcat(), you'll see:
... If copying takes place between objects that overlap, the
behavior is undefined.
Any decent description of strcat() (in a man page
The latest cygwin man page makes no mention of this and WATCOM C/C++'s
documentation omits this.
[...] or text book, for
example) should have similar wording; if it doesn't, that's the fault
of the author of the documentation.
Here's the first hit on google: http://www.cplusplus.com/ref/cstring/strcat.html
and the second: http://www.mkssoftware.com/docs/man3/strcat.3.asp
Here's the wikipedia entry as of 07/28/2006: http://en.wikipedia.org/wiki/Strcat
and here's the Open BSD documentation that it links to: http://www.openbsd.org/cgi-bin/man.cgi?query=strcat
So I guess none of that counts as "decent documentation".
If you attempt to use strcat(), or any other function, without reading
a description of how it's supposed to work, you can't reasonably
expect any particular behavior.
Right. That's because C is a "throwback to a forgotten era" kind of
language. Compare this to languages like Lua, Ruby and Python, where
your first guess as to how something works after seeing one example of
it has a 99% chance of being correct, and a 99% chance that you don't
even have a candidate second guess in mind.
--
Paul Hsieh http://www.pobox.com/~qed/ http://bstring.sf.net/
Andrew Poelstra wrote:
On 2006-07-27, we******@gmail.com <we******@gmail.comwrote:
Jonathan Leffler wrote:
we******@gmail.com wrote:
[...] (so strcat(p,p) leads
to UB even though it has a compelling intuitive meaning).
What's the compelling intuitive meaning? To me, it means copy
characters from the start of p over the null that used to mark the end
of p and keep going until you crash.
That's not an intuitive meaning. Its just an understanding of an
implementation anomoly. Perhaps for you, implementation details
changes your intuition.
No, knowledge that C strings are null-terminated (which any C programmer
needs to know) suggests that intuitively. Either you calculate strlen(),
add a counter variable, and `for' your way through the string, or you
eliminate the counter and superfluous call to strlen(), and code it
efficiently.
Right -- you are either with us, or you are with the terrorists.
It's more intuitive to use the more efficient, less code-intensive, and
easier-to-read version.
There is a *third option*. Skip the first character which overwrites
the '\0', do the append starting from src+1, then go back and do the
'\0' overwrite at the end. This extra work adds at most O(1) to the
execution time. Voila, like magic you have an aliasing safe strcat().
Ain't the "as-if" rule wonderful?
But this is just coding jujitsu, and has nothing to do with intuition.
Most people would intuitively think of this as simply replacing the
string with a doubled version of itself -- i.e., its analogous to the
C++ expression p += p for std::string's (and to be honest, I don't know
if that's legal or not), or just p = p + p in most other programming
languages.
"Most people" are not C programmers; if you know enough to use strcat(),
you should have an understanding of how C strings work.
Yes, but this "knowledge" is simply bent by force into shape by what
the standard tells you. I.e., its working *against* your intuition.
Which was kind of my point.
You only *know* that this is not the case, because you know that strcat
is implemented as some variation of { d += strlen(d); while (*d++ =
*s++); } instead of { size_t ld = strlen(d), ls = strlen(s); memmove
(d+ld, s, ls); d[ld+ls] = '\0'; }. You know this because the first
variation is going to be faster. This is not intuition -- its just a
technical calculation.
IMHO, _intuitively_, there is no other way to implement strcat().
That is why you fail.
Tell me this. How does *your* intuition tell you how memmove() is
implemented? Keep in mind that this guy actually is completely
aliasing safe.
--
Paul Hsieh http://www.pobox.com/~qed/ http://bstring.sf.net/ we******@gmail.com wrote:
Jonathan Leffler wrote:
we******@gmail.com wrote:
[...] (so strcat(p,p) leads
to UB even though it has a compelling intuitive meaning).
What's the compelling intuitive meaning? To me, it means copy
characters from the start of p over the null that used to mark the end
of p and keep going until you crash.
That's not an intuitive meaning. Its just an understanding of an
implementation anomoly. Perhaps for you, implementation details
changes your intuition.
Intuitive or not, that was not obvious for a beginner in C89, but that
should be obvious in C99, even for a beginner:
char* strcat (char * restrict, const char * restrict);
Thanks to "restrict", the function has a better documentation.
Andrew Poelstra:
IMHO, _intuitively_, there is no other way to implement strcat().
But there are other ways to implement it....
Borland C++ 5.0 and Digital Mars Compiler use alternative
implementations (and they behave weird too, but in another way).
On 28 Jul 2006 09:35:58 -0700, we******@gmail.com wrote:
>Keith Thompson wrote:
>we******@gmail.com writes:
Jonathan Leffler wrote: we******@gmail.com wrote:
[...] (so strcat(p,p) leads
to UB even though it has a compelling intuitive meaning). What's the compelling intuitive meaning? To me, it means copy characters from the start of p over the null that used to mark the end of p and keep going until you crash.
That's not an intuitive meaning. Its just an understanding of an
implementation anomoly. Perhaps for you, implementation details
changes your intuition.
[...]
In this case, intuition is not necessary.
Just *SAYING* this is the ultimate indictment of the C language. If the language doesn't match your intuition, then its just takes that much more effort to program in it.
>[...] If you read the standard's description of strcat(), you'll see:
... If copying takes place between objects that overlap, the behavior is undefined.
Any decent description of strcat() (in a man page
The latest cygwin man page makes no mention of this and WATCOM C/C++'s documentation omits this.
HP-UX man page:
"Character movement is performed differently in different
implementations, so moves involving overlapping source and destination
strings may yield surprises."
--
Al Balmer
Sun City, AZ
On 2006-07-28, we******@gmail.com <we******@gmail.comwrote:
Andrew Poelstra wrote:
>No, knowledge that C strings are null-terminated (which any C programmer needs to know) suggests that intuitively. Either you calculate strlen(), add a counter variable, and `for' your way through the string, or you eliminate the counter and superfluous call to strlen(), and code it efficiently.
Right -- you are either with us, or you are with the terrorists.
;-)
>It's more intuitive to use the more efficient, less code-intensive, and easier-to-read version.
There is a *third option*. Skip the first character which overwrites
the '\0', do the append starting from src+1, then go back and do the
'\0' overwrite at the end. This extra work adds at most O(1) to the
execution time. Voila, like magic you have an aliasing safe strcat().
Ain't the "as-if" rule wonderful?
If you start from src+1, you still have to store the original value of
src, or use a counter variable. My points on code-intensivity and ease
of reading still stand.
But this is just coding jujitsu, and has nothing to do with intuition.
It's clever, I admit. However, jumping through hoops to manage odd
inputs which could be fixed with an
assert (dest src + strlen(src) + 1);
doesn't bode well to me.
Most people would intuitively think of this as simply replacing the
string with a doubled version of itself -- i.e., its analogous to the
C++ expression p += p for std::string's (and to be honest, I don't know
if that's legal or not), or just p = p + p in most other programming
languages.
"Most people" are not C programmers; if you know enough to use strcat(), you should have an understanding of how C strings work.
Yes, but this "knowledge" is simply bent by force into shape by what
the standard tells you. I.e., its working *against* your intuition.
Which was kind of my point.
There are many reasons why I don't qualify as a "normal person" or
"average programmer"; my intuition agrees with that of strcat().
You only *know* that this is not the case, because you know that strcat
is implemented as some variation of { d += strlen(d); while (*d++ =
*s++); } instead of { size_t ld = strlen(d), ls = strlen(s); memmove
(d+ld, s, ls); d[ld+ls] = '\0'; }. You know this because the first
variation is going to be faster. This is not intuition -- its just a
technical calculation.
IMHO, _intuitively_, there is no other way to implement strcat().
That is why you fail.
I'm trying to avoid a flamewar.
Tell me this. How does *your* intuition tell you how memmove() is
implemented? Keep in mind that this guy actually is completely
aliasing safe.
I suspect that memmove() memcpy()'s the data to a safe place and
memcpy()'s it back to the dest. This adds an intermediate step
which prevents problems with src and dest overlapping.
That doesn't sound particularly efficient to me, though; I assume
that compiler/library writers have found much better ways to code
it.
--
Andrew Poelstra <website down>
To reach my email, use <email also down>
New server ETA: 8 hours
On 2006-07-28, SuperKoko <ta*******@yahoo.frwrote:
Andrew Poelstra:
>IMHO, _intuitively_, there is no other way to implement strcat().
But there are other ways to implement it....
Borland C++ 5.0 and Digital Mars Compiler use alternative
implementations (and they behave weird too, but in another way).
Allow me to rephrase that:
IMHO, there is no other _intuitive_ way to implement strcat().
--
Andrew Poelstra <website down>
To reach my email, use <email also down>
New server ETA: 1 days
Andrew Poelstra wrote:
>IMHO, _intuitively_, there is no other way to implement strcat().
websnarf wrote:
That is why you fail.
Tell me this. How does *your* intuition tell you how memmove() is
implemented? Keep in mind that this guy actually is completely
aliasing safe.
....because it's specified that way. And memcpy() is not specified
that way. strcpy() is not specified that way, either.
Are you arguing for ignoring the function specifications?
-drt
websnarf wrote:
>Tell me this. How does *your* intuition tell you how memmove() is implemented? Keep in mind that this guy actually is completely aliasing safe.
Andrew Poelstra wrote:
I suspect that memmove() memcpy()'s the data to a safe place and
memcpy()'s it back to the dest. This adds an intermediate step
which prevents problems with src and dest overlapping.
That doesn't sound particularly efficient to me, though; I assume
that compiler/library writers have found much better ways to code it.
The "typical" implementation of memmove() does a range check on
its arguments to determine if overlapping areas exists, and if so, does
a copy in reverse (high to low) direction. Such an algorithm is
efficient on CPUs with native bidirectional loop (REP) instructions.
-drt we******@gmail.com wrote:
Keith Thompson wrote:
....
[...] If you read the standard's
description of strcat(), you'll see:
... If copying takes place between objects that overlap, the
behavior is undefined.
Any decent description of strcat() (in a man page
The latest cygwin man page makes no mention of this and WATCOM C/C++'s
documentation omits this.
[...] or text book, for
example) should have similar wording; if it doesn't, that's the fault
of the author of the documentation.
Here's the first hit on google:
http://www.cplusplus.com/ref/cstring/strcat.html
and the second:
http://www.mkssoftware.com/docs/man3/strcat.3.asp
Here's the wikipedia entry as of 07/28/2006:
http://en.wikipedia.org/wiki/Strcat
and here's the Open BSD documentation that it links to:
http://www.openbsd.org/cgi-bin/man.cgi?query=strcat
So I guess none of that counts as "decent documentation".
Correct. You disagree?
The man pages on the machines I use most often are much better:
Linux: "The strings may not overlap, and the dest string must have
enough space for the result."
Irix: "If overflow of s1 occurs, or copying takes place when s1 and s2
overlap, the behavior is undefined."
In article <sl**********************@poelstra01.lan>,
Andrew Poelstra <ap*******@poelstra01.lanwrote:
>Allow me to rephrase that:
IMHO, there is no other _intuitive_ way to implement strcat().
Languages are supposed to be intuitive for users, not implementers.
-- Richard we******@gmail.com writes:
Keith Thompson wrote:
>we******@gmail.com writes:
Jonathan Leffler wrote: we******@gmail.com wrote:
[...] (so strcat(p,p) leads
to UB even though it has a compelling intuitive meaning). What's the compelling intuitive meaning? To me, it means copy characters from the start of p over the null that used to mark the end of p and keep going until you crash.
That's not an intuitive meaning. Its just an understanding of an
implementation anomoly. Perhaps for you, implementation details
changes your intuition.
[...]
In this case, intuition is not necessary.
Just *SAYING* this is the ultimate indictment of the C language. If
the language doesn't match your intuition, then its just takes that
much more effort to program in it.
News flash: C is not the most intuitive and beginner-friendly language
ever invented. Does this come as a surprise to you?
In a language where strings are first-class objects, and you can pass
them around as values, use them as operands in expressions, and so
forth, I'd expect something called "strcat" to behave in some
reasonable intuitive manner. I'd still need to see the declaration to
know how to use it, but it would probably be safe to assume that
something like
s1 = strcat(s2, s3)
would do the obvious thing.
C is not like that. Strings are not a data type, they're a data
format, "a contiguous sequence of characters terminated by and
including the first null character", subject to all of C's
complications regarding arrays and pointers. If you think you can
guess, with 99% certainty, how strcat() is going to behave based on
that, you're likely to be disappointed.
>[...] If you read the standard's description of strcat(), you'll see:
... If copying takes place between objects that overlap, the behavior is undefined.
Any decent description of strcat() (in a man page
The latest cygwin man page makes no mention of this and WATCOM C/C++'s
documentation omits this.
The Cygwin man page doesn't mention this, but it's not intended to be
complete:
strcat is part of the libc library. The full documentation for
libc is maintained as a Texinfo manual. If info and libc are
properly installed at your site, the command
info libc
will give you access to the complete manual.
I'm not convinced that's a good idea, but it's explicitly acknowledged
with a reference to the complete documentation.
"info libc" doesn't work for me under Cygwin (I don't know why, but
the reason is clearly irrelevant), but on another system the section
on strcat clearly says:
This function has undefined results if the strings overlap.
I don't know about Watcom.
>[...] or text book, for example) should have similar wording; if it doesn't, that's the fault of the author of the documentation.
Here's the first hit on google:
http://www.cplusplus.com/ref/cstring/strcat.html
and the second:
http://www.mkssoftware.com/docs/man3/strcat.3.asp
Here's the wikipedia entry as of 07/28/2006:
http://en.wikipedia.org/wiki/Strcat
and here's the Open BSD documentation that it links to:
http://www.openbsd.org/cgi-bin/man.cgi?query=strcat
So I guess none of that counts as "decent documentation".
I agree. I don't know what cplusplus.com is, and I'm not too
surprised by an error like this in Wikipedia (possibly someone here
will correct it soon). I am surprised that the OpenBSD documentation
doesn't mention this. That's a problem -- but not a problem with C
itself.
>If you attempt to use strcat(), or any other function, without reading a description of how it's supposed to work, you can't reasonably expect any particular behavior.
Right. That's because C is a "throwback to a forgotten era" kind of
language. Compare this to languages like Lua, Ruby and Python, where
your first guess as to how something works after seeing one example of
it has a 99% chance of being correct, and a 99% chance that you don't
even have a candidate second guess in mind.
Then by all means feel free to go and use those languages. Nobody
here will stop you.
I won't comment on the "throwback to a forgotten era" remark, but
apart from that I think your statement is pretty much factually
correct. You cannot generally look at the name of a C function, or
even a one-sentence description, and infer how it's going to behave in
all circumstances. I don't recall anyone claiming that you could.
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this. we******@gmail.com writes:
Andrew Poelstra wrote:
[...]
>No, knowledge that C strings are null-terminated (which any C programmer needs to know) suggests that intuitively. Either you calculate strlen(), add a counter variable, and `for' your way through the string, or you eliminate the counter and superfluous call to strlen(), and code it efficiently.
Right -- you are either with us, or you are with the terrorists.
First you wrote "Yeah, sieg heil!" in a recent thread in comp.lang.c,
and now you bring terrorists into a discussion of C strings.
I'll say it again:
Shove it, Paul.
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Andrew Poelstra <ap*******@poelstra01.lanwrites:
[...]
It's clever, I admit. However, jumping through hoops to manage odd
inputs which could be fixed with an
assert (dest src + strlen(src) + 1);
doesn't bode well to me.
That assert doesn't bode well. It invokes undefined behavior if dest
and src don't point into the same object (or just past the end of it).
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this. we******@gmail.com wrote:
Just *SAYING* this is the ultimate indictment of the C language. If
the language doesn't match your intuition, then its just takes that
much more effort to program in it.
You're confusing 'intuition' with 'expectation'. Windows users who
try to use an X-windows desktop, find it 'unintuitive' that the active
window is the one with the mouse over it (rather than the one they
last clicked on).
But this is not a matter of intuition, it is just a matter of
them expecting what they are used to. A person who has
not used either system before, would be fine either way.
Regarding the string issue, you would only expect strcat(p, p)
to double p if you had some sort of mental image of p as a
string object. But it is no such thing. It's an array of char. If
you dont understand this then you are not going to get far
with C programming.
Andrew Poelstra wrote:
On 2006-07-28, we******@gmail.com <we******@gmail.comwrote:
Andrew Poelstra wrote:
It's more intuitive to use the more efficient, less code-intensive, and
easier-to-read version.
There is a *third option*. Skip the first character which overwrites
the '\0', do the append starting from src+1, then go back and do the
'\0' overwrite at the end. This extra work adds at most O(1) to the
execution time. Voila, like magic you have an aliasing safe strcat().
Ain't the "as-if" rule wonderful?
If you start from src+1, you still have to store the original value of
src, or use a counter variable. My points on code-intensivity and ease
of reading still stand.
You typically read the source for your compiler's standard runtime
library? You seriously intuitively expect the source for your C lib
functions to be readable? They may be, but if your vendor is serious
about performance (fast strlens, strcpys, memcpys, and even strstr
implementations are quite convoluted), chances are they aren't really.
But this is just coding jujitsu, and has nothing to do with intuition.
It's clever, I admit. However, jumping through hoops to manage odd
inputs which could be fixed with an
assert (dest src + strlen(src) + 1);
doesn't bode well to me.
How does this *fix* anything? If src happens to be on an earlier
address (and not overlap at all) then what exactly is that assert
doing?
Most people would intuitively think of this as simply replacing the
string with a doubled version of itself -- i.e., its analogous to the
C++ expression p += p for std::string's (and to be honest, I don't know
if that's legal or not), or just p = p + p in most other programming
languages.
"Most people" are not C programmers; if you know enough to use strcat(),
you should have an understanding of how C strings work.
Yes, but this "knowledge" is simply bent by force into shape by what
the standard tells you. I.e., its working *against* your intuition.
Which was kind of my point.
There are many reasons why I don't qualify as a "normal person" or
"average programmer"; my intuition agrees with that of strcat().
But you don't have a good justification for this. This intuition can't
have existed before you learned the C language, as there is no other
language or string model with that kind of problem. Meaning, that is
not really intuition.
Tell me this. How does *your* intuition tell you how memmove() is
implemented? Keep in mind that this guy actually is completely
aliasing safe.
I suspect that memmove() memcpy()'s the data to a safe place and
memcpy()'s it back to the dest. This adds an intermediate step
which prevents problems with src and dest overlapping.
(I would throw away any compiler that did that. I'm pretty sure there
are basically no C compilers that do anything like that. Interesting
that your "intuition" seems to have failed you here. You can always
pick between between forward and backward copy depending on the order
of the pointers and memmove will work fine -- you can even then
continue to implement block tricks as is commonly done with memcpy().)
Your *intuition* starts looking a little more like my first "alternate"
suggestion for how strcat might be implemented. So it looks like
you've rushed right over the fence to my side because ...
That doesn't sound particularly efficient to me, though; I assume
that compiler/library writers have found much better ways to code
it.
.... that's right! Its *NOT* efficient, because your idea was just
driven by your *intuition*. So if I simply tell your that I've
implemented strcat_allow_alias() doesn't your intuition end up matching
my first alternative strcat implementation idea?
Yet in *BOTH* cases, it turns out that serious implementations of an
aliasing safe strcat, and memmove do not cost significantly more than
the aliasing unsafe strcat or memcpy functions. So the C standard
decides to pay the penalty of mismatching against people's intuition in
order to save some trivial almost unmeasurable efficiency savings (and
TR24731 is of no help since it takes the exact same position as the
original Clib functions).
--
Paul Hsieh http://www.pobox.com/~qed/ http://bstring.sf.net/
David R Tribble wrote:
Andrew Poelstra wrote:
IMHO, _intuitively_, there is no other way to implement strcat().
websnarf wrote:
That is why you fail.
Tell me this. How does *your* intuition tell you how memmove() is
implemented? Keep in mind that this guy actually is completely
aliasing safe.
...because it's specified that way. And memcpy() is not specified
that way. strcpy() is not specified that way, either.
Are you arguing for ignoring the function specifications?
You, of course, see the word "intuition" constantly being cited in all
the sentences written above right?
--
Paul Hsieh http://www.pobox.com/~qed/ http://bstring.sf.net/
Keith Thompson wrote: we******@gmail.com writes:
Right -- you are either with us, or you are with the terrorists.
First you wrote "Yeah, sieg heil!" in a recent thread in comp.lang.c,
and now you bring terrorists into a discussion of C strings.
Let's just ignore the troll.
Brian
On 2006-07-29, Keith Thompson <ks***@mib.orgwrote:
Andrew Poelstra <ap*******@poelstra01.lanwrites:
[...]
>It's clever, I admit. However, jumping through hoops to manage odd inputs which could be fixed with an assert (dest src + strlen(src) + 1); doesn't bode well to me.
That assert doesn't bode well. It invokes undefined behavior if dest
and src don't point into the same object (or just past the end of it).
Let's see... What I meant was:
assert ((dest - src) 0 && (dest - src) < strlen (src));
Is that right?
--
Andrew Poelstra <website down>
To reach my email, use <email also down>
New server ETA: Who knows?
On 2006-07-29, we******@gmail.com <we******@gmail.comwrote:
Andrew Poelstra wrote:
> assert (dest src + strlen(src) + 1);
How does this *fix* anything? If src happens to be on an earlier
address (and not overlap at all) then what exactly is that assert
doing?
There are a lot of things wrong with that code. I stand corrected.
>There are many reasons why I don't qualify as a "normal person" or "average programmer"; my intuition agrees with that of strcat().
But you don't have a good justification for this. This intuition can't
have existed before you learned the C language, as there is no other
language or string model with that kind of problem. Meaning, that is
not really intuition.
Actually, in my assembler days I used C-style strings, and I was a /lot/
more concerned with how they were implemented, given that my assembler
wasn't going to help me at all with overruns, etc.
C++ allows C-style strings. 0-termination is actually a very simple and
easy-to-understand way to represent strings. Knowing that C represents
strings that way, I can think of intuitive behavior for strcat().
Given another language with a different string representation, I'd
assume other behaviors, yes. Given another language with the /same/
string representation, my point still stands. This wasn't caused by
learning C; it was caused by learning C-style strings.
>I suspect that memmove() memcpy()'s the data to a safe place and memcpy()'s it back to the dest. This adds an intermediate step which prevents problems with src and dest overlapping.
Your *intuition* starts looking a little more like my first "alternate"
suggestion for how strcat might be implemented. So it looks like
you've rushed right over the fence to my side because ...
memmove() is specified to handle overlapping memory boundaries; memcpy()
and strcat() are not. That much is in the Standard, and memmove()'s
specification overrides my intuitive assumption that one shouldn't pass
overlapping memory to the function.
--
Andrew Poelstra <website down>
To reach my email, use <email also down>
New server ETA: 1 days
Keith Thompson wrote:
we******@gmail.com writes:
Keith Thompson wrote:
we******@gmail.com writes:
Jonathan Leffler wrote: we******@gmail.com wrote:
[...] (so strcat(p,p) leads
to UB even though it has a compelling intuitive meaning).
What's the compelling intuitive meaning? To me, it means copy
characters from the start of p over the null that used to mark the end
of p and keep going until you crash.
That's not an intuitive meaning. Its just an understanding of an
implementation anomoly. Perhaps for you, implementation details
changes your intuition.
[...]
In this case, intuition is not necessary.
Just *SAYING* this is the ultimate indictment of the C language. If
the language doesn't match your intuition, then its just takes that
much more effort to program in it.
News flash: C is not the most intuitive and beginner-friendly language
ever invented. Does this come as a surprise to you?
Huh? No, but apparently its a surprise to Jonanthan Leffler and Andrew
Poelstra. They seem to be arguing the case that it *does* match their
intuition.
My *original* contention, is that any proposal such as Richard
Seacord's managed string library should go ahead and pay the basically
0 penalty of actually *matching* intuition (as compared to the enormous
penalty he seems willing to pay for automatic character set filtering).
Anything else so far, are just people's false projections about what I
said *beyond* this, and my responses to them.
In a language where strings are first-class objects, and you can pass
them around as values, use them as operands in expressions, and so
forth, I'd expect something called "strcat" to behave in some
reasonable intuitive manner.
Yeah, that's nice. C is basically the only example of a language of
its kind, yet you feel not the slightly problem with making sweeping
generalizations about it based on its properties. That's kind of like
saying that Joseph Lieberman can't be elected president of the US
because he's jewish. I mean, that's nonsense (he's a right wing
democrat, which means he has no serious base of support outside his
state) in same way your idea here is nonsense.
first-class or not, strcat *CAN* be implemented as aliasing safe, at
very little cost. The fact that it doesn't is a choice that was made;
its nothing more than that. Its certainly not a *property* of
low-level languages (in assembly language, for example, there is no
assertion or expection of being unable to deal with aliased "objects"),
or a property of the fact that its not a first class value (bstrlib is
the obvious counter-example of this.)
[...] I'd still need to see the declaration to
know how to use it, but it would probably be safe to assume that
something like
s1 = strcat(s2, s3)
would do the obvious thing.
You mean if it were a first class value? But you are making a false
association here. There is no reason you cannot perform in-place
mutation of first class values. So the API could still have the same
basic functionality as the current strcat (i.e., two operands, and
modifying the destination.)
C is not like that. Strings are not a data type, they're a data
format, "a contiguous sequence of characters terminated by and
including the first null character", subject to all of C's
complications regarding arrays and pointers. If you think you can
guess, with 99% certainty, how strcat() is going to behave based on
that, you're likely to be disappointed.
These *complications*, as you suggest, have nothing to do with it. Its
all down to pure choice at the specification level. The guesses are
only wrong because the standard chooses that they should be wrong.
[...] If you read the standard's
description of strcat(), you'll see:
... If copying takes place between objects that overlap, the
behavior is undefined.
Any decent description of strcat() (in a man page
The latest cygwin man page makes no mention of this and WATCOM C/C++'s
documentation omits this.
The Cygwin man page doesn't mention this, but it's not intended to be
complete:
strcat is part of the libc library. The full documentation for
libc is maintained as a Texinfo manual. If info and libc are
properly installed at your site, the command
info libc
will give you access to the complete manual.
I'm not convinced that's a good idea, but it's explicitly acknowledged
with a reference to the complete documentation.
"info libc" doesn't work for me under Cygwin (I don't know why, but
the reason is clearly irrelevant),
It works on my system. info libc does nothing more than document the
standard include contents. info strcat just re-echos the man page.
[...] but on another system the section
on strcat clearly says:
This function has undefined results if the strings overlap.
I don't know about Watcom.
Well I just told you about Watcom, so now you do (it reads
substantially similar to the man pages). Its all downloadable from the
open watcom site if you care.
[...] or text book, for
example) should have similar wording; if it doesn't, that's the fault
of the author of the documentation.
Here's the first hit on google: http://www.cplusplus.com/ref/cstring/strcat.html
and the second: http://www.mkssoftware.com/docs/man3/strcat.3.asp
Here's the wikipedia entry as of 07/28/2006: http://en.wikipedia.org/wiki/Strcat
and here's the Open BSD documentation that it links to: http://www.openbsd.org/cgi-bin/man.cgi?query=strcat
So I guess none of that counts as "decent documentation".
I agree. I don't know what cplusplus.com is, and I'm not too
surprised by an error like this in Wikipedia (possibly someone here
will correct it soon). I am surprised that the OpenBSD documentation
doesn't mention this.
So we there have it. The standard for "decent" documentation as you
suggest appears to be quite high, and is certainly different from what
is commonly available.
[...] That's a problem -- but not a problem with C itself.
If you could just *stop* with the false projection for one second. You
know there is a reason why I quote other text when I post responses.
If you attempt to use strcat(), or any other function, without reading
a description of how it's supposed to work, you can't reasonably
expect any particular behavior.
Right. That's because C is a "throwback to a forgotten era" kind of
language. Compare this to languages like Lua, Ruby and Python, where
your first guess as to how something works after seeing one example of
it has a 99% chance of being correct, and a 99% chance that you don't
even have a candidate second guess in mind.
Then by all means feel free to go and use those languages. Nobody
here will stop you.
It always this false choice with you. I have to completely throw out
my investment in learning this language because it makes a number of
idiotic decisions through nothing other than poor choices.
We're not even talking about what language I *USE* for whatever I am
doing. Remember, this thread started as a discussion about improving
to the standard, and as I understand it, has reached the level of
serious official proposal. Citing other languages ought to be a
standard part of such a discussion without you pulling out this tired
old canard all the time.
--
Paul Hsieh http://www.pobox.com/~qed/ http://bstring.sf.net/
SuperKoko wrote:
we******@gmail.com wrote:
Jonathan Leffler wrote:
we******@gmail.com wrote:
[...] (so strcat(p,p) leads
to UB even though it has a compelling intuitive meaning).
>
What's the compelling intuitive meaning? To me, it means copy
characters from the start of p over the null that used to mark the end
of p and keep going until you crash.
That's not an intuitive meaning. Its just an understanding of an
implementation anomoly. Perhaps for you, implementation details
changes your intuition.
Intuitive or not, that was not obvious for a beginner in C89, but that
should be obvious in C99, even for a beginner:
char* strcat (char * restrict, const char * restrict);
Thanks to "restrict", the function has a better documentation.
Yes, I am aware of this. So the documentation has moved into the
platform's header files. Anyways, are you aware of any university
program teaching C programming based on the C99 standard? Somehow I
doubt any significant percentage of novices are learning C via the C99
standard.
Andrew Poelstra:
IMHO, _intuitively_, there is no other way to implement strcat().
But there are other ways to implement it....
Borland C++ 5.0 and Digital Mars Compiler use alternative
implementations (and they behave weird too, but in another way).
Well same with the solaris compiler (without the weird behavior). But
who's counting actual modern stuff?
--
Paul Hsieh http://www.pobox.com/~qed/ http://bstring.sf.net/ we******@gmail.com wrote:
first-class or not, strcat *CAN* be implemented as aliasing safe, at
very little cost. The fact that it doesn't is a choice that was made;
its nothing more than that. Its certainly not a *property* of
low-level languages (in assembly language, for example, there is no
assertion or expection of being unable to deal with aliased "objects"),
or a property of the fact that its not a first class value (bstrlib is
the obvious counter-example of this.)
I agree.
In fact, I deem that functions should tend to abstract details.
The implementation details of strcat should not change artificially the
interface.
Making strcat work with aliasing would not cost much, and would
increase safety of C.
IMHO, it would improve the C standard with a quasi-zero cost:
1) Breaks no code
2) That's a library issue : Easy to implemented by any actual C
implementation.
The only tradeoff would be efficiency... But I think that it can be
implemented efficiently.
Andrew Poelstra <ap*******@poelstra01.lanwrites:
On 2006-07-29, Keith Thompson <ks***@mib.orgwrote:
>Andrew Poelstra <ap*******@poelstra01.lanwrites: [...]
>>It's clever, I admit. However, jumping through hoops to manage odd inputs which could be fixed with an assert (dest src + strlen(src) + 1); doesn't bode well to me.
That assert doesn't bode well. It invokes undefined behavior if dest and src don't point into the same object (or just past the end of it).
Let's see... What I meant was:
assert ((dest - src) 0 && (dest - src) < strlen (src));
Is that right?
No. If dest and src don't point into the same object, both "dst src"
and "dest - src" invoke undefined behavior.
Of course an implementation of a library function is free to use these
constructs if it knows how the compiler is going to treat them.
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
In article <sl**********************@poelstra01.lan>,
Andrew Poelstra <ap*******@poelstra01.lanwrote:
>Let's see... What I meant was:
assert ((dest - src) 0 && (dest - src) < strlen (src));
Is that right?
If pointers are not known to point to within the same object, you can
only compare them for equality. So the only way to achieve what you
want (within the letter of the law of the C standard) is to loop
through the addresses in the two objects, testing whether they are
equal. You could optimise that a bit and avoid testing all pairs.
-- Richard
Andrew Poelstra wrote:
On 2006-07-27, we******@gmail.com <we******@gmail.comwrote:
>Jonathan Leffler wrote:
>>we******@gmail.com wrote: [...] (so strcat(p,p) leads to UB even though it has a compelling intuitive meaning). What's the compelling intuitive meaning? To me, it means copy characters from the start of p over the null that used to mark the end of p and keep going until you crash.
That's not an intuitive meaning. Its just an understanding of an implementation anomoly. Perhaps for you, implementation details changes your intuition.
No, knowledge that C strings are null-terminated (which any C programmer
needs to know) suggests that intuitively. Either you calculate strlen(),
add a counter variable, and `for' your way through the string, or you
eliminate the counter and superfluous call to strlen(), and code it
efficiently.
It's more intuitive to use the more efficient, less code-intensive, and
easier-to-read version.
>Most people would intuitively think of this as simply replacing the string with a doubled version of itself -- i.e., its analogous to the C++ expression p += p for std::string's (and to be honest, I don't know if that's legal or not), or just p = p + p in most other programming languages.
"Most people" are not C programmers; if you know enough to use strcat(),
you should have an understanding of how C strings work. (And indeed, I've
never seen a C textbook that introduced strcat() prior to introcuding C-
style strings.) (Although I've heard of some pretty terrible textbooks on
this group that I was fortunate enough to avoid!)
>You only *know* that this is not the case, because you know that strcat is implemented as some variation of { d += strlen(d); while (*d++ = *s++); } instead of { size_t ld = strlen(d), ls = strlen(s); memmove (d+ld, s, ls); d[ld+ls] = '\0'; }. You know this because the first variation is going to be faster. This is not intuition -- its just a technical calculation.
IMHO, _intuitively_, there is no other way to implement strcat().
#include <string.h>
char *catstr(char *dst, char *src) {
if (dst == src) {
size_t s, siz = strlen(dst);
s = siz;
src += siz;
while (s <= siz) {
src[s] = dst[s];
--s;
}
} else {
strcat(dst, src);
}
return dst;
}
--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein --- we******@gmail.com wrote:
SuperKoko wrote:
we******@gmail.com wrote:
Jonathan Leffler wrote: we******@gmail.com wrote:
[...] (so strcat(p,p) leads
to UB even though it has a compelling intuitive meaning).
What's the compelling intuitive meaning? To me, it means copy
characters from the start of p over the null that used to mark the end
of p and keep going until you crash.
...
This is computer *science*, not "getting in Touch with Your Feelings
101". intuition only serves to guess at translating psuedo code to a
first pass at real code, looking up the function defs. in the process.
I use Python and Perl a lot, and I *always* keep a copy of their
function library definitions up when I code them. I don't rely on
intuition, and I have been programming since the 'dark ages'.
Imagination, inspiration, experience, research, experimentation, and
perhaps intuition as filler in the pseudo code until I can look it up.
Back in 1980 I wrote my own wrap-around for strcat() that checks sizes
and realloc() as needed. Obviously, not intuitively, I used it with
pointers as destinations, and for the few microseconds in computing
time that it cost me 20+ years ago I traded the security that
something untoward wouldn't have a customer calling me in the wee hours
of the morning. It has been in my personal library, along with a lot of
other string manipulation code, since then.
C acts as a portable assembly language extension. Keep that in mind and
save intuition for VB.
BTW, FreeBSD man page for strcat() offers:
...
The strcat() and strncat() functions append a copy of the
null-terminated
string append to the end of the null-terminated string s, then add
a ter-
minating `\0'. The string s must have sufficient space to hold
the
result.
The strncat() function appends not more than count characters from
append, and then adds a terminating `\0'.
....
The strcat() function is easily misused in a manner which enables
mali-
cious users to arbitrarily change a running program's
functionality
through a buffer overflow attack. (See the FSA.)
Avoid using strcat(). Instead, use strncat() or strlcat() and
ensure
that no more characters are copied to the destination buffer than
it can
hold.
Curtis W. Rendon
--
One OS to rule them all, One OS to find them,
One OS to bring them all and in the darkness bind them
In the Land of Redmond where the Shadows lie.
>Andrew Poelstra wrote:
>IMHO, _intuitively_, there is no other way to implement strcat()
[than the usual version that self-destructs when you do
char buf[100] = "apple";
strcat(buf, buf); /* desired: appleapple\0 */
or
strcat(buf, buf + 2); /* desired: appleple\0 */
]
In article <Z4******************************@comcast.com>
Joe Wright <jo********@comcast.netwrote:
>char *catstr(char *dst, char *src) {
if (dst == src) {
[rest snipped]
This handles the:
catstr(buf, buf);
case, but not the:
catstr(buf, buf + 2);
case. To handle both, perhaps something like:
/* returns strlen(result) */
size_t catstr(char *dst, const char *src) {
size_t dstlen = strlen(dst), srclen = strlen(src);
memmove(dst + dstlen, src, srclen + 1);
return dstlen + srclen;
}
would be better. (Untested.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Chris Torek wrote:
>Andrew Poelstra wrote:
>>IMHO, _intuitively_, there is no other way to implement strcat()
[than the usual version that self-destructs when you do
char buf[100] = "apple";
strcat(buf, buf); /* desired: appleapple\0 */
or
strcat(buf, buf + 2); /* desired: appleple\0 */
]
In article <Z4******************************@comcast.com>
Joe Wright <jo********@comcast.netwrote:
>char *catstr(char *dst, char *src) { if (dst == src) {
[rest snipped]
This handles the:
catstr(buf, buf);
case, but not the:
catstr(buf, buf + 2);
case. To handle both, perhaps something like:
/* returns strlen(result) */
size_t catstr(char *dst, const char *src) {
size_t dstlen = strlen(dst), srclen = strlen(src);
memmove(dst + dstlen, src, srclen + 1);
return dstlen + srclen;
}
would be better. (Untested.)
I wasn't aware that 'catstr(buf, buf + 2)' was at issue.
--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Andrew Poelstra wrote:
>IMHO, _intuitively_, there is no other way to implement strcat().
Paul Hsieh wrote:
>That is why you fail.
Tell me this. How does *your* intuition tell you how memmove() is implemented? Keep in mind that this guy actually is completely aliasing safe.
David R Tribble wrote:
>...because it's specified that way. And memcpy() is not specified that way. strcpy() is not specified that way, either.
Are you arguing for ignoring the function specifications?
Paul Hsieh wrote:
You, of course, see the word "intuition" constantly being cited in all
the sentences written above right?
Yeah. Okay, my intuition tells me that memcpy() is going to be
implemented in the most efficient way to copy a block of bytes
to another block and ignore any issues of overlapping blocks,
because that's the way the function is specified.
My intuition tells me that memmove() is going to be implemented
so that overlapping blocks are copied correctly with a possible
loss of efficiency, because that's the way the function is specified.
My intuition tells me that strcat() is going to be implemented
so that one string is appended to another, using the '\0' characters
to signal the end of the strings, and ignoring the possibility of
overlapping strings (e.g., strcat(p,p)), because that's the way
the function is specified:
7.21.3.1
[...]
The strcat function appends a copy of the string pointed to
by s2 (including the terminating null character) to the end of
the string pointed to by s1. The initial character of s2 overwrites
the null character at the end of s1. If copying takes place
between objects that overlap, the behavior is undefined.
The phrases "overwriting the terminating null character of s2"
and "if the objects overlap the behavior is undefined" are a
pretty clear indication that 'strcat(p,p)' will invoke u.b. and
probably corrupt the resulting string value of p. At least that's
what my intuition tells me.
-drt
David R Tribble wrote:
Yeah. Okay, my intuition tells me that memcpy() is going to be
implemented in the most efficient way to copy a block of bytes
to another block and ignore any issues of overlapping blocks,
because that's the way the function is specified.
My intuition tells me that memmove() is going to be implemented
so that overlapping blocks are copied correctly with a possible
loss of efficiency, because that's the way the function is specified.
My intuition tells me that strcat() is going to be implemented
so that one string is appended to another, using the '\0' characters
to signal the end of the strings, and ignoring the possibility of
overlapping strings (e.g., strcat(p,p)), because that's the way
the function is specified:
...
The phrases "overwriting the terminating null character of s2"
and "if the objects overlap the behavior is undefined" are a
pretty clear indication that 'strcat(p,p)' will invoke u.b. and
probably corrupt the resulting string value of p. At least that's
what my intuition tells me.
It comes down to expectations. If the programmer expects "char"
to mean "character" and "strcat" to mean "concatenate character
strings", then he is simply wrong. There is a relationship
between the concepts and the corresponding implementations, but
not an exact mapping between them, and it is the differences that
can cause trouble when the programmer's mental model is wrong.
C, C++, and many other languages do provide the *means* for a
programmer to create his own object types and support functions
that more closely fit whatever model he has. If the standard
library facility (which met legacy requirements sufficiently
well) doesn't meet your current requirements, don't (mis)use it;
provide your own implementation. (Be sure to choose new names.)
Jonathan Leffler wrote: we******@gmail.com wrote:
[...] (so strcat(p,p) leads
to UB even though it has a compelling intuitive meaning).
What's the compelling intuitive meaning? To me, it means copy
characters from the start of p over the null that used to mark the end
of p and keep going until you crash.
I am also not sure what the intuitive meaning was intended, but
thinking about memcpy vs. memmove, if string copying functions had
defined to copy the source string into an intermediate buffer before
putting into the destination, there would be no crash. I suspect
that's the compelling intuitive meaning he intended.
--
Jun, Woong (woong at icu.ac.kr)
Samsung Electronics Co., Ltd.
``All opinions are mine and do not represent any organization''
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Jonathan Leffler wrote:
we******@gmail.com wrote:
>[...] (so strcat(p,p) leads to UB even though it has a compelling intuitive meaning).
What's the compelling intuitive meaning? To me, it means copy
characters from the start of p over the null that used to mark the end
of p and keep going until you crash.
The simpler expectation from the interface is "append
a copy of the string *currently* pointed to by p to p",
i.e., append it to itself.
Other languages that support this via notation such
as s+=s; or s = s+s implement it this way.
If you think of strcat in terms of its implementation
then your expectation is natural.
-- James
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
James Dennett wrote:
Jonathan Leffler wrote:
we******@gmail.com wrote:
[...] (so strcat(p,p) leads
to UB even though it has a compelling intuitive meaning).
What's the compelling intuitive meaning? To me, it means copy
characters from the start of p over the null that used to mark the end
of p and keep going until you crash.
The simpler expectation from the interface is "append
a copy of the string *currently* pointed to by p to p",
i.e., append it to itself.
Other languages that support this via notation such
as s+=s; or s = s+s implement it this way.
If you think of strcat in terms of its implementation
or, in terms of it's specification by the standard,
then your expectation is natural.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Paul,
I did have a look at James Anthill's Vstr implementation and I discuss
it in the strings chapter of my book on "Secure Coding in C and C++"
which happens to be available online at: http://www.informit.com/articles/art...&seqNum=8&rl=1
I was not aware of your implementation, so I did not evaluate it.
Our goal in writing the managed string library was to define an API that
could be used to program more securely. To my mind, writing secure code
also encompasses eliminating defects in general so I believe this
library also addresses these concerns. You also commented that " the
API is somewhat cumbersome, which makes inline usage impossible". This
was an intentional decision on our part, as in-line usage typically
prevents/discourages a user from checking the return status of the function.
Performance was not a major objective for the reference implementation
of the API. The idea was to allow library vendors and other interested
parties such as yourself the opportunity to provide more efficient
implementations.
We should have a complete implementation of the API available shortly.
I'll post a further announcement to these news groups when it is ready.
Thanks,
rCs
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Robert Seacord wrote:
I did have a look at James Anthill's Vstr implementation and I discuss
it in the strings chapter of my book on "Secure Coding in C and C++"
which happens to be available online at:
http://www.informit.com/articles/art...&seqNum=8&rl=1
I was not aware of your implementation, so I did not evaluate it.
In James' own string library comparisons he makes mention of the Better
String Library, and its about the only one he doesn't evicerate in his
evaluation. Or you could have just searched for "string library" in
google (Bstrlib is currently hit #2).
Our goal in writing the managed string library was to define an API that
could be used to program more securely.
I think both James and I had this in mind when we were developing our
respective libraries as well. The main difference being that we both
also decided it was worthwhile to satisfty even more criteria. I was
more focussed on functionality and ease of use or "Software Crisis"
kind of problems, whereas James was clearly more focussed on ultimate
performance in networking or highly IO centric environments.
And I think you *missed* the crucial point about aliasing entirely.
This is a safety/security issue (at least it is as much as NULL
parameter detection is) and yet it appears to be unaddressed in your
library. (I have not evaluated Vstr deeply enough to know whether or
not he solved that issue, since it only compiles with the
gnu-toolchain).
Another security issue is the question of auditing. As you know, prior
to long term real world usage the only way you can have any sort of
assurance about the security of any system is by having security
experts audit the code. The Better String Library highly facilitates
this by its "security statement". This statement declares up front
exactly what Bstrlib's asserted functionality is with respect to
security. In this way an auditor can delineate his/her strategy by 1)
verifying that the library does what it says (by examining the source
code of Bstrlib) and 2) verifying that the facilities claimed are
sufficient to meet the security requirements of the rest of the
program. This delineation is important as it gives a bounded and well
defined way that the auditor can evaluate all this "extra code" that
Bstrlib provides that another developer has not written themselves.
With the managed string library being propoposed for the next C
standard, the auditor ends up having to "trust" the compiler if its a
closed source compiler, as well as trusting your design. But worse
yet, without any security statement, an auditor will have a harder time
knowing what exactly they should expect the managed library to deliver
from the point of view of security.
[...] To my mind, writing secure code
also encompasses eliminating defects in general so I believe this
library also addresses these concerns. You also commented that " the
API is somewhat cumbersome, which makes inline usage impossible". This
was an intentional decision on our part, as in-line usage typically
prevents/discourages a user from checking the return status of the function.
Some might say that it discourages users from using the library at all.
In Bstrlib I introduce the concept of "error propogation". Along with
supporting inline usage, errors are detected and passed through the
calls (error-in produces error-out.) This more closely matches the
"laziness" of users, in that they need not check each call, they only
need to check the last call in the chain of calls.
You might argue that this is just a different way to solve the same
problem, except that Bstrlib's method enjoys two huge advantages: 1) it
vastly simplifies error checking without compromising correctness,
which is important for dealing with unintentional leaks due to exiting
before freeing resources. 2) it allows one to continue to write code
very concisely which in most cases will lead to easier maintenance.
By *only* focussing on the problem from the very narrow point of view
of security, you are missing ideas like this. And you consequently
lose the potential to appeal to programmers for other reasons, which is
important if you want people to seriously adopt these new functions.
This is why there is such a thing as cherry flavored cough syrup, or
mint flavored toothpaste.
Performance was not a major objective for the reference implementation
of the API. The idea was to allow library vendors and other interested
parties such as yourself the opportunity to provide more efficient
implementations.
I have no idea how I would improve the efficiency of pervasive
character set filtering over the more obvious alternative of performing
the filtering just at the time that system() is called. The
alternative is different semantically -- but I believe that this
difference is what is called for. Charset filter is not a generally
useful feature *UNLESS* you are calling system (*and* under that
assumption that this is good enough for system call safety.) I.e., I
don't believe I *can* solve the performance problems of the managed
string design.
If you ignore perfomance to this degree, you will immediately create
resistance among developers who will shy away from using "managed
strings" because of some performance penalty they percieve. It sets up
a "false dichotomy" in the minds of developers that safety must come at
the expense of performance. A quick look at either Bstrlib or Vstr
shows that this dichotomy is not true. Both substantially out-perform
the standard C library functions (with Vstr, its kind of conditional on
the kind of code, but when it wins it usually wins big) and both also
deliver far more safety.
We should have a complete implementation of the API available shortly.
I'll post a further announcement to these news groups when it is ready.
Ok, but I think the major problem is with the design not any
implementation.
[comp.lang.c.moderated removed because posting there appears to delay
posts for weeks]
--
Paul Hsieh http://www.pobox.com/~qed/ http://bstring.sf.net/
Robert Seacord wrote:
>
I did have a look at James Anthill's Vstr implementation and I
discuss it in the strings chapter of my book on "Secure Coding in
C and C++" which happens to be available online at:
http://www.informit.com/articles/art...&seqNum=8&rl=1
I was not aware of your implementation, so I did not evaluate it.
And, due to the woeful lack of quotation and attribution, nobody
else is aware of it or anything else.
--
Chuck F (cb********@yahoo.com) (cb********@maineline.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.netUSE maineline address!
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry. ku****@wizard.net wrote:
James Dennett wrote:
>Jonathan Leffler wrote:
>>we******@gmail.com wrote: [...] (so strcat(p,p) leads to UB even though it has a compelling intuitive meaning). What's the compelling intuitive meaning? To me, it means copy characters from the start of p over the null that used to mark the end of p and keep going until you crash.
The simpler expectation from the interface is "append a copy of the string *currently* pointed to by p to p", i.e., append it to itself.
Other languages that support this via notation such as s+=s; or s = s+s implement it this way.
If you think of strcat in terms of its implementation
or, in terms of it's specification by the standard,
But the point was to think of the *intuitive* meaning of
strcat, not its formally specified meaning. The standard
doesn't capture the intuitive (or, if you prefer, naive)
expectation. Which is fine by me, as I don't expect that
intuition will be sufficient for robust programming.
-- James
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
"Robert Seacord" <rc*@sei.cmu.eduwrote in message
news:cl****************@plethora.net...
was an intentional decision on our part, as in-line usage typically
prevents/discourages a user from checking the return status of the
function.
My point of view is that requiring the programmer to explicitly test
for correctness is not appreciably better than the current situation,
and that usage errors (as opposed to expected "failures" such as
testing for the existence of a file by name) are best handled by
throwing an exception, so that *some* strategy for handling such
errors is *always* in place. With nested exception handlers, this
strategy can be established at the lowest feasible level for an
intelligent recovery procedure, or allowed to default to a higher-
level strategy that provides a "coarser grained" recovery. The
programmer still retains total control (if he wants to exert it), but
the exceptional-case handling does not clutter the main-line logic.
And yes, nested exception handling is certainly possible in
Standard C; there have been several implementations.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
James Dennett wrote:
ku****@wizard.net wrote:
James Dennett wrote:
....
If you think of strcat in terms of its implementation
or, in terms of it's specification by the standard,
But the point was to think of the *intuitive* meaning of
strcat, not its formally specified meaning. The standard
doesn't capture the intuitive (or, if you prefer, naive)
expectation. Which is fine by me, as I don't expect that
intuition will be sufficient for robust programming.
I think that was pretty much my point. I didn't have any intuition
about what strcat() would do when I first heard about it. I read its
specification, and expected it to operate as specified. For functions
with more generic names, such as "open", I do have some expectations
that should be met, though they're pretty vague expectations. But
"strcat"? I know it's short for "string catenate", but that's only
obvious after having read the specification. Anybody who would
abbreviate a name that way isn't giving me any intuitive expectations
about what they might have intended by the name. It's not quite as bad
as "grep", but it comes close.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
James Dennett wrote:
But the point was to think of the *intuitive* meaning of
strcat, not its formally specified meaning.
Since intuition is so subjective, more care is needed.
*String concatenation* is one thing, strcat is another.
The concatenation of "abc" with "efg" is "abcefg", but
when you're talking about the data accessed by strcat
there are also storage locations involved, not some
abstract value space. And it is not at all evident
that there is only one "right" way to handle that
storage in cases where there is overlap between input
and output.
From the point of view of run-time efficiency, if a
strcat-like function were required to produce well-
defined behavior of the kind that some seem to think
is desired, it would have to, for *every* invocation,
perform some additional testing to determine whether
there is overlap, or else it would have to use a
considerably less efficient method all the time. The
trade-off would not be acceptable to many users (who
currently don't have any problem using strcat properly).
We went through this with memcpy, and the result was
to provide a separate "better-defined" function memmove.
Note that the advent of memmove did not cause a mass
exodus away from using memcpy, because many programmers
are able to use both of them as appropriate, and cases
of potential overlap are relatively uncommon.
The standard
doesn't capture the intuitive (or, if you prefer, naive)
expectation. Which is fine by me, as I don't expect that
intuition will be sufficient for robust programming.
Indeed, we hear frequent demands that the C standard
ought to specify things so that programmers don't need
to know the specifications or think about what they're
doing. That approach to programming doesn't get one
very far before getting into trouble.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Douglas A. Gwyn wrote:
James Dennett wrote:
But the point was to think of the *intuitive* meaning of
strcat, not its formally specified meaning.
Since intuition is so subjective, more care is needed.
*String concatenation* is one thing, strcat is another.
The concatenation of "abc" with "efg" is "abcefg", but
when you're talking about the data accessed by strcat
there are also storage locations involved, not some
abstract value space. And it is not at all evident
that there is only one "right" way to handle that
storage in cases where there is overlap between input
and output.
So the correct answer is to twist your intuition to match the standard?
People's intuition do not easily map to definitionism such as this.
By creating this alternate explanation, you are directly acting against
people's intuition. And in the end you are working really hard to
defend something that doesn't have a justifiably solid defence.
From the point of view of run-time efficiency, if a
strcat-like function were required to produce well-
defined behavior of the kind that some seem to think
is desired, it would have to, for *every* invocation,
perform some additional testing to determine whether
there is overlap, or else it would have to use a
considerably less efficient method all the time.
This is utterly false on its face. I've given a solution *IN THIS
THREAD* that so obviously would run in equivalent time as the straight
forward typical non-safe method that is currently endorsed.
If such a thing were true, for example, Bstrlib would have a hard time
keeping up with the performance of the standard library (Bstrlib is
aliasing safe). Bstrlib annihilates the standard library on
performance across the board on many platforms and compilers that were
tested. This achievement does not come from nowhere of course -- just
doing a brief survey of the source code of most standard C compilers,
it is actually fairly straightfoward to outperform the standard library
on many functions, particularly string functions. I have on my
assembly examples web page a demonstration for hugely accelerating the
implementation of "strlen" over most x86 compilers -- its *much* faster
than either the expected implementation or nearly all implementations I
have actually encountered (Sun went ahead and implemented code similar
to mine for their Solaris compilers a few years ago). You cannot speak
of performance without speaking to implementation details.
You people who do not understand performance really should probably not
pretend to comment on it as if from a position of authority. In
particular you can't on the one hand claim that you can't characterize
performance of C in principle, then turn around and claim that some
change in specification will change performance, and of course,
ultimately just be plain wrong anyway.
[...] The
trade-off would not be acceptable to many users (who
currently don't have any problem using strcat properly).
Since there is no down side (except slightly increased code footprint)
there would be nothing to object to.
We went through this with memcpy, and the result was
to provide a separate "better-defined" function memmove.
That is because on hardware that existed at the time there was a
measurable difference on that function. On today's hardware, there is
no difference in performance between memmove and memcpy, BTW. This is
not true of strcat, however, which would never be slower.
Note that the advent of memmove did not cause a mass
exodus away from using memcpy, because many programmers
are able to use both of them as appropriate, and cases
of potential overlap are relatively uncommon.
That's only because it was overshadowed by the larger mass exodus
towards using Perl, Python, C++, Java, etc. People who still use C,
mostly buy into C's weaknesses and just live with it for whatever
reasons.
The standard
doesn't capture the intuitive (or, if you prefer, naive)
expectation. Which is fine by me, as I don't expect that
intuition will be sufficient for robust programming.
That's a truism that exists in a narrow field of programming languages.
My point is that it exists to a large extent in C (especially its
libraries) for no good reason.
Indeed, we hear frequent demands that the C standard
ought to specify things so that programmers don't need
to know the specifications or think about what they're
doing.
Actually what we often hear is over-generalized hyperbole from the
committee and committee apologists who feel that they don't need to
address any problems with the language.
[...] That approach to programming doesn't get one
very far before getting into trouble.
You, of course, have never attempted to program in the language
"Python".
You have also lost sight, completely, of the whole point of this
thread. The whole idea of secure programming is concerned with dealing
with programmer's inadvertent bugs. My claim, is that if you more
closely align the programming language with people's intuition and
expectation, then the number of bugs and security flaws will naturally
decrease.
TR 24731 misses this point completely, and instead just exposes the
flaws more explicitely. But you can always stuff RSIZE_MAX into the
extra length parameter, and basically gain no more security. Automated
tools can assist you in finding buffer overflow flaws, and potential
buffer overflow flaws based on old legacy code exactly as effectively
as trying to do so while porting to TR 24731. I.e., in real effect,
this proposal will actually do basically nothing. Richard Seacord has
clearly done much better by doing buffer management for you with his
proposed "managed strings" library, however, he has ignored the usage
and intuition impact.
C99 has not been widely adopted and it never will be, and its primarily
because it just doesn't offer anything that people really care about.
People care about performance, safety, scalability, and C99 offers
precious little on any those fronts, even though in this language there
is no shortage of fertile ground for expanding in all those areas. If
you want c0x to have any impact at all, you have to deliver something
on these fronts that you utter failed to do with C99. And imho neither
TR 24731, nor managed strings rise to that level which is what I'm
trying to point out.
Richard Seacord and the Microsofties simply does rise high enough to
meet the challenge, and the ANSI C committee are too blind to allow,
encourage or seek improvements anyways. The problem with these
proposals is that they don't go far enough to address the problem --
the committee reacts by saying that they go too far to solve a problem
that they don't believe exists.
--
Paul Hsieh http://www.pobox.com/~qed/ http://bstring.sf.net/ we******@gmail.com wrote:
>
.... snip ...
>
You have also lost sight, completely, of the whole point of this
thread. The whole idea of secure programming is concerned with
dealing with programmer's inadvertent bugs. My claim, is that if
you more closely align the programming language with people's
intuition and expectation, then the number of bugs and security
flaws will naturally decrease.
And you have lost track of the reasons for having different
languages in the first place. If you want secure programming,
there are quite adequate languages for the purpose, such as Ada and
Pascal. There is no need to destroy C.
--
"The most amazing achievement of the computer software industry
is its continuing cancellation of the steady and staggering
gains made by the computer hardware industry..." - Petroski
--
Posted via a free Usenet account from http://www.teranews.com
CBFalconer wrote:
And you have lost track of the reasons for having different
languages in the first place. If you want secure programming,
there are quite adequate languages for the purpose, such as Ada and
Pascal. There is no need to destroy C.
What makes you think that C will be destroyed if it included better
solutions (that is, solutions with a better cognitive fit for the
majority of users) than TR 24731 and managed strings?
--
mail1dotstofanetdotdk This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Bob Rock |
last post by:
Hello,
in the last few days I've made my first few attempts at creating mixed C++
managed-unmanaged assemblies and looking aftwerwards with ILDASM at what is
visible in those assemblies from a...
|
by: lolomgwtf |
last post by:
I have a managed C++ method that wraps unmanaged code and creates a
managed object holding data retrieved form an unmanged one. I want
create an instance of this managed class in C#, pass it to...
|
by: awk |
last post by:
Hi All
I have a com dll written in VB6 (it's a User Function Library for my crystal
reports - this allows me to write custom functions for Crystal
which can be applied in Crystal formulas - none...
|
by: Aaron Queenan |
last post by:
When I build a C++ library to .NET using the managed C++ compiler, I get the
following error message:
Linking...
LINK : error LNK2020: unresolved token (0A000005) _CrtDbgReport
LINK : error...
|
by: lolomgwtf |
last post by:
I have a managed C++ method that wraps unmanaged code and creates a
managed object holding data retrieved form an unmanged one. I want
create an instance of this managed class in C#, pass it to...
|
by: bor_kev |
last post by:
Hi,
First of all, i want to use the new managed class syntax and STL.NET
under Microsoft Visual (C++) Studio 2005 Beta.
I read in a Microsoft...
|
by: Maxwell |
last post by:
Hello,
I having having oodles of trouble using the std lib in my MC++ (VS.NET
2003) Class library. I figured out a simple sample to reproduce the
errors I am having. Create a MC++ (VS.NET 2003)...
|
by: Apu Nahasapeemapetilon |
last post by:
Hello and thank you in advance for your help.
Can anyone think of a reason why this code would work properly on one PC,
but not another?
I've got a System.Windows.Forms.UserControl that...
|
by: rCs |
last post by:
The SEI has published CMU/SEI-2006-TR-006 "Specifications for Managed
Strings" and released a "proof-of-concept" implementation of the
managed string library.
The specification, source code for...
|
by: Mushico |
last post by:
How to calculate date of retirement from date of birth
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 4 Oct 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM)
The start time is equivalent to 19:00 (7PM) in Central...
|
by: Aliciasmith |
last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
|
by: tracyyun |
last post by:
Hello everyone,
I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
|
by: giovanniandrean |
last post by:
The energy model is structured as follows and uses excel sheets to give input data:
1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
|
by: NeoPa |
last post by:
Hello everyone.
I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report).
I know it can be done by selecting :...
|
by: NeoPa |
last post by:
Introduction
For this article I'll be using a very simple database which has Form (clsForm) & Report (clsReport) classes that simply handle making the calling Form invisible until the Form, or all...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM)
Please note that the UK and Europe revert to winter time on...
|
by: NeoPa |
last post by:
Introduction
For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...
| |