By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,501 Members | 1,720 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,501 IT Pros & Developers. It's quick & easy.

(part 30) Han from China answers your C questions

P: n/a
Error handling in C

Nick Keighley said:
>I am doing some Socket Programming in C and feeling a lots of difficult in
error handling :(
yeah, error handling in C can be a pain. Especially if you've used
something with exceptions.
...
You might end up with something like this:-
...
if ((phe = gethostbyname (host)))
memcpy (&sin.sin_addr, phe->h_addr, phe->h_length);
To the OP, please be aware that Nick Keighley is a known troll
and is deliberately providing you with unsound advice. You asked
for error handling, not error generation (or much worse).

The code he gave you trusts the DNS server not to return an 'A'
resource record with a data length of greater than 4 bytes.
The h_length comes from a 16-bit resource-data-length field in
the DNS response message and can obviously be configured to
indicate a size much larger than 4. The end result is that
may sin.sin_addr overflow, causing a crash (or much worse).

Change that memcpy() to the following:

memcpy(&sin.sin_addr, phe->h_addr, sizeof sin.sin_addr);

In future, please post socket-related questions to both
comp.lang.c and comp.unix.programmer so that you get the
benefit of better peer-review. I don't read comp.unix.programmer,
so you might not have received this valuable information about
h_length over there, which is why you did the right thing by
posting to comp.lang.c. Besides, error handling is on-topic
here, obviously.

Yours,
Han from China

Nov 19 '08 #1
Share this Question
Share on Google+
16 Replies


P: n/a
On 19 Nov, 15:17, Borked Pseudo Mailed <nob...@pseudo.borked.net>
wrote:
Error handling in C

Nick Keighley said:
I am doing some Socket Programming in C and feeling a lots of difficult in
error handling :(
yeah, error handling in C can be a pain. Especially if you've used
something with exceptions.
..
You might end up with something like this:-
..
if ((phe = gethostbyname (host)))
* memcpy (&sin.sin_addr, phe->h_addr, phe->h_length);

To the OP, please be aware that Nick Keighley is a known troll
and is deliberately providing you with unsound advice. You asked
for error handling, not error generation (or much worse).

The code he gave you trusts the DNS server not to return an 'A'
resource record with a data length of greater than 4 bytes.
The h_length comes from a 16-bit resource-data-length field in
the DNS response message and can obviously be configured to
indicate a size much larger than 4. The end result is that
may sin.sin_addr overflow, causing a crash (or much worse).

Change that memcpy() to the following:

* * memcpy(&sin.sin_addr, phe->h_addr, sizeof sin.sin_addr);

In future, please post socket-related questions to both
comp.lang.c and comp.unix.programmer so that you get the
benefit of better peer-review. I don't read comp.unix.programmer,
so you might not have received this valuable information about
h_length over there, which is why you did the right thing by
posting to comp.lang.c. Besides, error handling is on-topic
here, obviously.
touche

I note that I said "You might end up with something like this".
I was trying to illustrate that every call had to have error checking.

--
Nick Keighley
Nov 19 '08 #2

P: n/a
Borked Pseudo Mailed wrote:
>
The code he gave you trusts the DNS server not to return an 'A'
resource record with a data length of greater than 4 bytes.
The h_length comes from a 16-bit resource-data-length field in
the DNS response message and can obviously be configured to
indicate a size much larger than 4. The end result is that
may sin.sin_addr overflow, causing a crash (or much worse).

Change that memcpy() to the following:

memcpy(&sin.sin_addr, phe->h_addr, sizeof sin.sin_addr);
To the OP: I hope you understand, that while the potential buffer
overrun issue present in the original version of the code is a serious
problem, trying to fix that problem by simply _truncating_ the data, as
our "Han from China" did here is not even remotely a viable solution. It
is rather a way to sweep the problem under the carpet and make it
resurface elsewhere. What "Han from China" apparently is trying to tell
you is that code that doesn't crash and doesn't work is better than code
that crashes. In reality, the exact opposite is true: when your code's
internal invariants are irrecoverably violated, the best possible
outcome is the one when the code crashes as soon as possible, instead of
continuing to run.

--
Best regards,
Andrey Tarasevich
Nov 19 '08 #3

P: n/a
Borked Pseudo Mailed wrote, On 19/11/08 15:17:
Error handling in C

Nick Keighley said:
<snip>
To the OP, please be aware that Nick Keighley is a known troll
<snip>

Nick is not a troll despite what "Han from China" says. Han is the troll.
In future, please post socket-related questions to both
comp.lang.c and comp.unix.programmer so that you get the
Han is trying to disrupt this group as a little thought and checking
should show anyone. How to use Unix functions is topical in
comp.unix.programmer but not here.
--
Flash Gordon
If spamming me sent it to sm**@spam.causeway.com
If emailing me use my reply-to address
See the comp.lang.c Wiki hosted by me at http://clc-wiki.net/
Nov 19 '08 #4

P: n/a
Andrey Tarasevich wrote:
To the OP: I hope you understand, that while the potential buffer
overrun issue present in the original version of the code is a serious
problem, trying to fix that problem by simply _truncating_ the data,
as our "Han from China" did here is not even remotely a viable
solution. It is rather a way to sweep the problem under the carpet
and make it resurface elsewhere. What "Han from China" apparently is
trying to tell you is that code that doesn't crash and doesn't work
is better than code that crashes. In reality, the exact opposite is
true: when your code's internal invariants are irrecoverably
violated, the best possible outcome is the one when the code crashes
as soon as possible, instead of continuing to run.
I'm certainly no C expert, but from a programming standpoint I disagree.
What exactly should the program do? It can't possibly reconstitute a valid
address if the length isn't 4 (this is assuming IPV4). Allowing the program
to write all over memory is certainly no guarantee that the program is going
to crash either. Tens of thousands of buffer overflow exploits speak for
themselves. While not being the "perfect" solution, the Han from China
approach is orders of magnitude better than allowing an overflow in this
example. Code that doesn't crash and doesn't work (when given garbage
input) IS far better than code that simply trusts its input and crashes.
Nov 19 '08 #5

P: n/a
In article <Gu******************************@supernews.com> ,
Anthony Fremont <no****@noplace.netwrote:
>To the OP: I hope you understand, that while the potential buffer
overrun issue present in the original version of the code is a serious
problem, trying to fix that problem by simply _truncating_ the data,
as our "Han from China" did here is not even remotely a viable
solution. It is rather a way to sweep the problem under the carpet
and make it resurface elsewhere. What "Han from China" apparently is
trying to tell you is that code that doesn't crash and doesn't work
is better than code that crashes. In reality, the exact opposite is
true: when your code's internal invariants are irrecoverably
violated, the best possible outcome is the one when the code crashes
as soon as possible, instead of continuing to run.
>I'm certainly no C expert, but from a programming standpoint I disagree.
What exactly should the program do? It can't possibly reconstitute a valid
address if the length isn't 4 (this is assuming IPV4).
It should check that the returned address type is one that it can
handle, probably AF_INET, and if it isn't it should report an error.

The original code was as recommended in many examples (and probably
derives from the 4.2BSD manual, though I haven't checked), and dates
from a time was there was little possiblity of any other kind of
address.

-- Richard
--
Please remember to mention me / in tapes you leave behind.
Nov 19 '08 #6

P: n/a
Anthony Fremont wrote:
Andrey Tarasevich wrote:
>To the OP: I hope you understand, that while the potential buffer
overrun issue present in the original version of the code is a serious
problem, trying to fix that problem by simply _truncating_ the data,
as our "Han from China" did here is not even remotely a viable
solution. It is rather a way to sweep the problem under the carpet
and make it resurface elsewhere. What "Han from China" apparently is
trying to tell you is that code that doesn't crash and doesn't work
is better than code that crashes. In reality, the exact opposite is
true: when your code's internal invariants are irrecoverably
violated, the best possible outcome is the one when the code crashes
as soon as possible, instead of continuing to run.

I'm certainly no C expert, but from a programming standpoint I disagree.
What exactly should the program do?
It heavily depends on the application area. But generally, if the error
is unrecoverable, the program should just quit.
It can't possibly reconstitute a valid
address if the length isn't 4 (this is assuming IPV4). Allowing the program
to write all over memory is certainly no guarantee that the program is going
to crash either. Tens of thousands of buffer overflow exploits speak for
themselves. While not being the "perfect" solution, the Han from China
approach is orders of magnitude better than allowing an overflow in this
example.
I'm in no way trying to push the original (overflowing) version of the
code as the "proper" one. As I said before, it does suffer from a very
serious problem, which needs to be taken care of. But sweeping it under
the carpet, as "Han" suggested, is not even a remotely valid way to deal
with it. It simply replaces a current known error with an future unknown
one.
Code that doesn't crash and doesn't work (when given garbage
input) IS far better than code that simply trusts its input and crashes.
While your original logic is correct (aside from your misunderstanding
of my intent), the conclusion that you make here is not. In reality,
neither way is really acceptable. The real danger of the original
(overflowing) code is that instead of making the program crash, it will
actually continue to run, opening the possibility of various
buffer-overflow-based exploits. In other words, at certain level of
abstraction the danger of the original code manifests itself in
generally the same way as the one in the modified code: the code
continues to run after its invariants have been broken. For this (purely
theoretical reason) I'd half-jokingly refer to the original variant as
"better one" because it seems to have a better chance to crash right
away. But seriously, once again, neither variant is really acceptable.

--
Best regards,
Andrey Tarasevich
Nov 19 '08 #7

P: n/a
On Wed, 19 Nov 2008 08:17:39 -0700 (MST),
Borked Pseudo Mailed <no****@pseudo.borked.netwrote:
Error handling in C

Nick Keighley said:
>>I am doing some Socket Programming in C and feeling a lots of difficult in
error handling :(
yeah, error handling in C can be a pain. Especially if you've used
something with exceptions.
..
>You might end up with something like this:-
..
>if ((phe = gethostbyname (host)))
memcpy (&sin.sin_addr, phe->h_addr, phe->h_length);
Change that memcpy() to the following:

memcpy(&sin.sin_addr, phe->h_addr, sizeof sin.sin_addr);
And this is, of course, also not the right way to do it. gethostbyname()
and friends shouldn't be used anymore in modern code.

If you want to know why, please start a thread on comp.unix.programmer.
Also, you could read http://beej.us/guide/bgnet/
In future, please post socket-related questions to both
comp.lang.c and comp.unix.programmer so that you get the
benefit of better peer-review.
Don't post to both. Unix network programming clearly belongs on
comp.unix.programmer, not on comp.lang.c. Adding comp.lang.c only
provides you with noise from people who don't really know the subject
well enough, but feel they have to comment anyway.

Martien
--
|
Martien Verbruggen | It's a poor language that blames the tools
| who use it. -- Peter Nilsson
|
Nov 19 '08 #8

P: n/a
Andrey Tarasevich said:

<snip>
What "Han from China" apparently is trying to tell
you is that code that doesn't crash and doesn't work is better than code
that crashes.
What "Han from China" is trying to tell us can safely be ignored, since
"Han from China" has made little if any effort to persuade anyone that his
views are worth listening to - instead, he's gone straight for mockery.

So let's skip over them completely, and cut to the issue itself.

You present two possibilities: code that doesn't crash and doesn't work
(i.e. silently produces incorrect results), and code that crashes. You go
on to suggest...
In reality, the exact opposite is true: when your code's
internal invariants are irrecoverably violated, the best possible
outcome is the one when the code crashes as soon as possible, instead of
continuing to run.
If that belief is reflected in the programs you write, I would not want to
run any of them.

A program that crashes tells me nothing sufficiently useful to help me fix
the problem. "It's screwed" is insufficiently useful, except insofar as it
persuades me to ditch the program and try something better.

A program that silently but predictably produces incorrect results can be
studied and fixed.

Best of all is a program that, having determined that something is wrong,
produces noisy error messages, and then fails gracefully (perhaps halting,
but certainly not crashing).

Anyone who thinks a crashing program is a good program doesn't belong in
the industry.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 20 '08 #9

P: n/a
Richard Heathfield wrote:
>
You present two possibilities: code that doesn't crash and doesn't work
(i.e. silently produces incorrect results), and code that crashes. You go
on to suggest...
Incorrect. I did not present anything. Whatever I said applied to the
two possibilities presented by other posters before me.
>In reality, the exact opposite is true: when your code's
internal invariants are irrecoverably violated, the best possible
outcome is the one when the code crashes as soon as possible, instead of
continuing to run.

If that belief is reflected in the programs you write, I would not want to
run any of them.
That's OK.
A program that crashes tells me nothing sufficiently useful to help me fix
the problem. "It's screwed" is insufficiently useful, except insofar as it
persuades me to ditch the program and try something better.
Actually, when I said "crashes" I actually meant "aborts as soon as
possible", which includes a genuine crash as the worst way to abort or a
more graceful abort with a custom error message. But all these variants
fall into your "It's screwed" category anyway, so that should make much
difference.

In any case, a program cannot tell anyone anything useful at all when it
runs into genuinely unforeseen problem, which is what is being discussed.
A program that silently but predictably produces incorrect results can be
studied and fixed.
Firstly, "predictably" is quite a requirement here. It might be simply
impossible to detect the incorrectness of results in situations when the
"golden" result does not exist (as that's virtually always the case
outside of the regression QA environment). On top of that, it is rather
strange to expect any form of predictability from the incorrect result.

Secondly, this is very application-area specific, but no, in general
case a faulty program working in the production environment cannot be
possibly allowed to run for the purpose of "studying and fixing". It is
exactly the case when "better safe than sorry" principle should be applied.
Best of all is a program that, having determined that something is wrong,
produces noisy error messages, and then fails gracefully (perhaps halting,
but certainly not crashing).
You seem to be contradicting yourself here. Isn't a halt just a form of
"It's screwed" result, which you just criticized several sentences above?
Anyone who thinks a crashing program is a good program doesn't belong in
the industry.
Hm... True, but irrelevant. In situation when program runs into a
unforseen error any form of the graceful exit is out of question, and
there only two possibilities: a crash or a continued execution in
invalidated state. The crash is a better alternative in a case like
that. Anyone, who doesn't understand that doesn't belong in the industry.

--
Best regards,
Andrey Tarasevich
Nov 20 '08 #10

P: n/a
On 19 Nov, 21:21, rich...@cogsci.ed.ac.uk (Richard Tobin) wrote:
In article <GuidnV2xQpnRHbnUnZ2dnUVZ_rXin...@supernews.com> ,
Anthony Fremont <nob...@noplace.netwrote:
To the OP: I hope you understand, that while the potential buffer
overrun issue present in the original version of the code is a serious
problem, trying to fix that problem by simply _truncating_ the data,
as our "Han from China" did here is not even remotely a viable
solution. It is rather a way to sweep the problem under the carpet
and make it resurface elsewhere. What "Han from China" apparently is
trying to tell you is that code that doesn't crash and doesn't work
is better than code that crashes. In reality, the exact opposite is
true: when your code's internal invariants are irrecoverably
violated, the best possible outcome is the one when the code crashes
as soon as possible, instead of continuing to run.
I'm certainly no C expert, but from a programming standpoint I disagree.
What exactly should the program do? *It can't possibly reconstitute a valid
address if the length isn't 4 (this is assuming IPV4).

It should check that the returned address type is one that it can
handle, probably AF_INET, and if it isn't it should report an error.
yes
The original code was as recommended in many examples (and probably
derives from the 4.2BSD manual, though I haven't checked), and dates
from a time was there was little possiblity of any other kind of
address.
It was lifted from an ancient book on socket programming (Comer?).
It did indeed preceed IPv6

--
Nick Keighley

Nov 20 '08 #11

P: n/a
On 20 Nov, 02:31, Richard Heathfield <r...@see.sig.invalidwrote:
Andrey Tarasevich said:
What "Han from China" apparently is trying to tell
you is that code that doesn't crash and doesn't work is better than code
that crashes.

What "Han from China" is trying to tell us can safely be ignored, since
"Han from China" has made little if any effort to persuade anyone that his
views are worth listening to - instead, he's gone straight for mockery.

So let's skip over them completely, and cut to the issue itself.
he did identify a problem with the code...

<snip>

--
Nick Keighley
Nov 20 '08 #12

P: n/a
Nick Keighley said:
On 20 Nov, 02:31, Richard Heathfield <r...@see.sig.invalidwrote:
>Andrey Tarasevich said:
What "Han from China" apparently is trying to tell
you is that code that doesn't crash and doesn't work is better than
code that crashes.

What "Han from China" is trying to tell us can safely be ignored, since
"Han from China" has made little if any effort to persuade anyone that
his views are worth listening to - instead, he's gone straight for
mockery.

So let's skip over them completely, and cut to the issue itself.

he did identify a problem with the code...
Yes. I didn't say "no effort at all".

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 20 '08 #13

P: n/a
On Thu, 20 Nov 2008 08:29:13 +0000, Richard Heathfield wrote:
Nick Keighley said:
>On 20 Nov, 02:31, Richard Heathfield <r...@see.sig.invalidwrote:
>>Andrey Tarasevich said:
>What "Han from China" apparently is trying to tell
you is that code that doesn't crash and doesn't work is better than
code that crashes.

What "Han from China" is trying to tell us can safely be ignored, since
"Han from China" has made little if any effort to persuade anyone that
his views are worth listening to - instead, he's gone straight for
mockery.

So let's skip over them completely, and cut to the issue itself.

he did identify a problem with the code...

Yes. I didn't say "no effort at all".
I think tarasevich is taranobyiŻ.
--
George

The terrorists and their supporters declared war on the United States - and
war is what they got.
George W. Bush

Picture of the Day http://apod.nasa.gov/apod/
Nov 20 '08 #14

P: n/a
Andrey Tarasevich wrote:
Richard Heathfield wrote:
....
>A program that crashes tells me nothing sufficiently useful to help me
fix the problem. "It's screwed" is insufficiently useful, except
insofar as it persuades me to ditch the program and try something better.

Actually, when I said "crashes" I actually meant "aborts as soon as
possible", which includes a genuine crash as the worst way to abort or a
more graceful abort with a custom error message. But all these variants
fall into your "It's screwed" category anyway, so that should make much
difference.

In any case, a program cannot tell anyone anything useful at all when it
runs into genuinely unforeseen problem, which is what is being discussed.
Well, technically, yes - by definition an unforeseen problem can't be
dealt with. We're talking about foreseeing possible problems, and making
sure that the program behaves as well as possible in the process of
dealing with them. I don't expect fopen() calls to fail - I'm not in the
habit of asking programs to open files unless I think that those files
can be opened. However, I always write code that deals with the
possibility that they might fail.
>A program that silently but predictably produces incorrect results can
be studied and fixed.

Firstly, "predictably" is quite a requirement here. It might be simply
impossible to detect the incorrectness of results in situations when the
"golden" result does not exist (as that's virtually always the case
outside of the regression QA environment).
In my experience, it is quite commonplace for a "golden" result to be
identifiable, or at least a "golden range" of results. Even if some
erroneous results are not easily identifiable as such, there's still a
great many erroneous results that can be identified because they're
outside the golden range.

For instance, for any call to fread(), a return value that's not equal
to the third argument is in some cases an error, and always requires
special handling.
>Best of all is a program that, having determined that something is
wrong, produces noisy error messages, and then fails gracefully
(perhaps halting, but certainly not crashing).

You seem to be contradicting yourself here. Isn't a halt just a form of
"It's screwed" result, which you just criticized several sentences above?
No. "It's screwed" refers to failing without taking care to avoid
undefined behavior, without any attempt to cleaning up at least some of
the mess that might have been created by the failure, and without
providing any information that would be useful for figuring out why the
failure occurred.
Nov 20 '08 #15

P: n/a
Richard Heathfield wrote:
>
I have to disagree with this. If the error is truly unforeseen, you don't
get a choice about what to do, because if you did have the choice, you
foresaw the error. If at that point you chose to allow the program to
crash, you were being lazy.
I feel that we are getting sidetracked here. This is all great, again,
even if some of it is arguable, but the original issue was not that.

The original issue was that the error was in fact foreseen and a
"solution" was suggested. And the suggested "solution" was presented as
if it was a _full_ _fix_ for the error, i.e. as a variant that doesn't
suffer from the error at all. It was implied that the updated code is
naturally "correct" in a sense that the original error no longer affects
its functionality. All I'm saying is that this claim is not true, and
that the updated code also suffers from the same error, although the
immediate consequences of that error are not the same. Moreover, I'm
saying that the updated "code" is even worse than the original, even
that on the surface it might appear to be "safer".

None of what I said in any way means that anyone should avoid normal
civilized and graceful error handling in their programs and force their
programs to crash instead.

--
Best regards,
Andrey Tarasevich
Nov 20 '08 #16

P: n/a
Andrey Tarasevich said:

<snip>
None of what I said in any way means that anyone should avoid normal
civilized and graceful error handling in their programs and force their
programs to crash instead.
Then I think I owe you an apology, for misreading your earlier article.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 20 '08 #17

This discussion thread is closed

Replies have been disabled for this discussion.