Listing the most dangerous parts of C

K

Keith Thompson

Skarmander said:
Exactly. Garbage collection is for people who are stupid or lazy or
both. Everyone knows that keeping track of memory yourself is better
and cleaner. Keeps the mind in shape and your programs fast.

Or something like that, at least.

Right. Mnemonic identifiers are also a crutch for the weak-minded.
Objects should be identified by serial numbers, preferably in
hexadecimal. I mean, we can't very well trust computers to keep track
of things like this; most of them are prorammed by lazy people.
 
D

Dave Vandervies

I am looking for a wish list of things which should be removed from
the C (C99) - due to feature's bad security track record

Side effects.

If you don't allow anything that can have side effects, then nothing
can cause problems.


dave
 
C

CBFalconer

qed said:
.... snip ...

I am not sure why you want to get rid of srand() or rand(). Its true
they suck as PRNGs, and race conditions mess them up in ways that can be
worse than you think (and RAND_MAX is generally pathetically small), but
I don't think people generally abuse them to that degree of detriment in
the real world. Again, if you had a *substitute*, that would be fine.
The problem is that I am not aware of any good portable PRNGs -- are you
(hence supporting the idea that C is not a portable language)? As for
non-portable ones, there are plenty (such as Mersenne Twister, or any of
the Marsaglia generators.) So as long as we are stuck with *something*
-- they still can serve a role as a quick and dirty PRNG. (The right
answer here is to demand that the standard change how it works --
however a quick perusal of their guiding principles, indicates there is
no mechanism by which you could reasonably do this.)

Why do you consider the MT non-portable? I took one implementation
and removed the portability problems, by and large, except that I
was not sure that it would function correctly when a long was
larger that 32 bits. So my source creates an error for that
situation, leaving it up to someone else to decipher.

You can find my modification of it within the hashlib package,
where it is used to control regression testing.

<http://cbfalconer.home.att.net/download/hashlib.zip>

--
Some informative links:
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html
 
C

CBFalconer

Ben said:
I am unaware of a limitation on calling ungetc() at the beginning
of a file. I scanned the definition of ungetc() in C99 and
didn't see such a limitation--did I miss something?

ungetc is absolutely essential to provide one char look ahead
operation. Without it it is impossible to properly connect
divergent parsing modules. The only case known to me where the one
char limitation creates a problem is in parsing floats with an
invalid exponential part.

--
Some informative links:
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html
 
K

Keith Thompson

Keith Thompson said:
Right. Mnemonic identifiers are also a crutch for the weak-minded.
Objects should be identified by serial numbers, preferably in
hexadecimal. I mean, we can't very well trust computers to keep track
of things like this; most of them are prorammed by lazy people.

In particular, some of them are "prorammed" by people who are too lazy
to proofread before posting.
 
Q

qed

Ben said:
I am unaware of a limitation on calling ungetc() at the beginning
of a file. I scanned the definition of ungetc() in C99 and
didn't see such a limitation--did I miss something?

"For a binary stream, its file position indicator is decremented by each
successful acll to the ungetc function; if its value was zero before a
call, its indeterminate after the call".

Whatever, if you are thinking about it from an implementators point of
view, its obvious what's wrong with this whole idea. Its stupid in
exactly the same way that fgets ignoring '\0' in its input stream is
stupid. Its the only function that behaves like that in a nest of other
functions that want things to behave differently.
 
C

Christopher Benson-Manica

Rod Pemberton said:
1) 15 C functions suffer buffer overflow problems:
gets() cuserid() scanf() fscanf() sscanf() vscanf() vsscanf() vfscanf()
sprintf() strcat() strcpy() streadd() strecpy() vsprintf() strtrns()

However, of those functions that are standard C functions, only one,
gets(), is *intrinsically* vulnerable to buffer overruns. Using the
other functions correctly is part of what separates a programmer from
a monkey banging on a keyboard.
If you really want to get crazy with C, do some of these:
1) eliminate pointers in main

Why not just eliminate pointers altogether? There's a language that
does that for you, it's called Java. Otherwise, eliminating pointers
in some arbitrary function (be it main() or anything else) only
deprives you of a tool C gives you to write good, effective code for
no good reason.
3) eliminate malloc, add dynamic allocation and garbage collection

Again, Java does this for you. Perhaps a different language is
desired?
4) change C to pass by reference

Why, so you can have special tricks for passing by value?
6) give up now, and try Walter Bright's D language...

Or Java :)
 
C

Christopher Benson-Manica

Richard Heathfield said:
Okay, drop gets(), scanf(), and strncpy() - ironically, this is unsafe
chiefly because people think it's safe and so they feel free to use it in a
rather cavalier way!

Alternatively, strncpy() could just work in the way we expect :) I
always have to resort to a reference to remind myself that strncpy is,
in fact, a bit of a charlatan.
 
Q

qed

Rod said:
I read a security oriented pdf (sorry, don't know where anymore) which said:

1) 15 C functions suffer buffer overflow problems:
gets() cuserid() scanf() fscanf() sscanf() vscanf() vsscanf() vfscanf()
sprintf() strcat() strcpy() streadd() strecpy() vsprintf() strtrns()

2) 8 C functions suffer from format string vulnerabilities
printf() fprintf() sprintf() snprintf() vprintf() vfprintf() vsprintf()
vsnprintf()

Summary of pdf: Because many C implementations use the same stack for
string data and flow control information (like addresses), the above
functions can modify the flow control information on the stack thereby
allowing authorized code to execute.

That's only one kind of catastrophic failure. Personally, I would be
more focused on the fact that the failures happen in the first place.
If you really want to get crazy with C, do some of these:
1) eliminate pointers in main

Huh? I probably need some elaboration here. Do you literally mean that
you shouldn't have local variables in main that are passed by reference
to other functions? Or ... what *do* you mean?
2) make pointers be associated with a variable before use, not with a data
type

Huh? You mean that building linked lists and similar data structures
should take an additional operation (first assign the new node malloc to
a variable) or do you mean that making such things should be impossible?
3) eliminate malloc, add dynamic allocation and garbage collection

Ok, but then you are no longer programming in C. C is a language that
allows you to understand the *performance* of your application very
clearly. Java is a language allows you to understand what it *does*
very clearly. The two languages are differentiated by this difference
in philosophy. Making C more like Java is just as easily achieved by
throwing it out and starting with Java.

However, I understand the motivation. Why not instead ask for *more*
from the C universe? There are many ways of *extending* the whole
malloc/etc paradigm to make it safer, *faster* and more powerful.
4) change C to pass by reference

Ok, no. Adding refs (the & thingy from C++) I agree with, because
passing pointers tends to more dangerous in general (more likely to pass
in NULL, or garbage/uninitialized pointers) for some cases. However to
be general, you must support *both* semantics, and C does this by
allowing you to pass a pointer in lieu of references. But don't take
away call by value from the language.
5) require separation of string (and other) data and flow control
information

You mean don't throw growable data types into non-growable arrays on a
stack? I agree. Bstrlib makes exactly this distinction (there is no
sane way to put a non-constant bstring on the stack). Perhaps only
allowing bounds protected enforced types into auto variables.
6) give up now, and try Walter Bright's D language...

Because "C++++" would have been too tacky. You could instead look at
languages like Python, Lua, and Java and ask yourself, what would it
take to design a language that was as easy to use as Python/Lua, and
safe and predictable as Java, with the speed of C?
 
J

Jordan Abel

ungetc is absolutely essential to provide one char look ahead
operation. Without it it is impossible to properly connect
divergent parsing modules. The only case known to me where the one
char limitation creates a problem is in parsing floats with an
invalid exponential part.

Which is why C does the "preprocessor numbers" thing

(0xE+5 parses to a single token which is an invalid number, rather than
0xE + 5)
 
J

Jordan Abel

Alternatively, strncpy() could just work in the way we expect :) I
always have to resort to a reference to remind myself that strncpy is,
in fact, a bit of a charlatan.

Changing it will create problems for code that _does_ use it for what
it's intended to do.
 
Q

qed

CBFalconer said:
ungetc is absolutely essential to provide one char look ahead
operation. Without it it is impossible to properly connect
divergent parsing modules.

This makes no sense. If you need ungetc semantics, you can create your
own file stream wrapper. Chances are you will allow more than a single
character of unreading, and you will not support things like fgetpos()
(or fseek, though I don't recommend the use of that function in general)
in your wrapper.

Because it only supports one character, it becomes stupid semantically,
much like strtok() is. You cannot call it twice in a row, mean that
once again, nestable parsing that uses this technique becomes ill
defined (just like strtok.)

There is nothing *essential* about it. And its a stupid wart you don't
want to pay for anyways.
> [...] The only case known to me where the one
char limitation creates a problem is in parsing floats with an
invalid exponential part.

I don't even know what you are talking about. Parsing of files should
not rely on the ability to scan backwards and forwards through a file,
but if you really wanted to do that, why wouldn't you use
fgetpos/fsetpos instead?
 
R

Richard Heathfield

Christopher Benson-Manica said:
Why not just eliminate pointers altogether? There's a language that
does that for you, it's called Java.

Ha, ha, ha.

Oh, yeah - ha.

(For those who don't know - in Java, *everything* is a pointer.)
 
R

Richard Bos

You might want to read the JF entry on Turing Tar Pit.

Snigger. Yah, right. See before buying.

Stupid analogy.
I read a security oriented pdf (sorry, don't know where anymore) which said:

1) 15 C functions suffer buffer overflow problems:
gets() cuserid() scanf() fscanf() sscanf() vscanf() vsscanf() vfscanf()
sprintf() strcat() strcpy() streadd() strecpy() vsprintf() strtrns()

That list should tell you all you need to know about this document.
If you really want to get crazy with C, do some of these:
1) eliminate pointers in main
2) make pointers be associated with a variable before use, not with a data
type
3) eliminate malloc, add dynamic allocation and garbage collection
4) change C to pass by reference
5) require separation of string (and other) data and flow control
information
6) give up now, and try Walter Bright's D language...

Alternatively, if you want C++ (or MS Sheesh!) you know where to find
it.

Richard
 
R

Robert Latest

On Wed, 10 May 2006 16:25:42 +0000,
in Msg. said:
Okay, drop gets()

I know that C99 had to be designed in such a way that all C89 code would
still compile without error, but gets() really should have been banned.
That would have nugded code maintainers towards removing gets() from
existing code, a trivial task.

OTOH all the "should haves" with respect to compatibility with old code
are moot anyway. Since every compiler in existence (and even new ones)
will have a "C89" compatibility mode, people maintaining pre-C99 code
will continue to use it (and I will continue to use it whenever I can
because I think much of C99 stinks).

robert
 
R

Richard Heathfield

Robert Latest said:
Since every compiler in existence (and even new ones)
will have a "C89" compatibility mode, people maintaining pre-C99 code
will continue to use it (and I will continue to use it whenever I can
because I think much of C99 stinks).

The reason that some bits of C99 don't stink is simply that they haven't yet
been implemented.
 
R

Robert Latest

On 11 May 2006 03:58:29 GMT,
in Msg. said:
Changing it will create problems for code that _does_ use it for what
it's intended to do.

Can you think of a meaningful piece of code that would break if
strncpy() were made safe, and where strncpy could not trivially be
replaced by memcpy? I think it is a design flaw that a str* function can
return illegal data upon being passed valid parameters ("illegal"
meaning an array of char that is not a valid C string)

robert
 
R

Robert Latest

On Wed, 10 May 2006 23:13:45 +0300,
in Msg. said:
I have a dream, I don't know if it is realizable but I try donate
the t3d language to one of the major charity organization

I'm sure they'll appreciate that.

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,157
Latest member
MercedesE4
Top