D
Dan Pop
In said:The domain of strlen is the set of non-empty strings. Hence, EDOM
is a correct indicator.
Since when is "" outside the domain of strlen?
Dan
In said:The domain of strlen is the set of non-empty strings. Hence, EDOM
is a correct indicator.
jacob navia said:Should return zero and set errno to EDOM. Zero would make NULL
identical to the empty string, what is consistent with the
usage many applications make of NULL.
The domain of strlen is the set of non-empty strings. Hence, EDOM
is a correct indicator.
The behavior now (just undefined) allows for the above implementation,
Specifying this would make the library more consistent.
The problem is made worst when the standard publishes code
like
char buffer[26];
Why did they specify asctime with all this detail?
There are many other functions where code would have been useful.
No, they had to publish code that overflows and crashes at
the slightest error.
I strive in my programs to write code as bulletproof as possible.
This can be done in C.
If C is to be understood as a language where "anything goes", we
have to reach the conclusion that C is to be avoided at all
costs in any serious application.
Defensive programming and error analysis are part of a system
design, and it has to be done. C is no exception: programs
should be robust and handle gracefully incorrect inputs
without blowing up.
The discussion in comp.std.c didn't lead to anything.
The gets function is still there, trigraphs are still there,
the general attitude is that C should avoid any change
and go into obsolescence.
Most of the people in comp.std.c and here think that
C++ is the way to go, hence, C should stay where it is
and disappear.
jacob navia said:Should return zero and set errno to EDOM. Zero would make NULL
identical to the empty string,
what is consistent with the
usage many applications make of NULL.
The domain of strlen is the set of non-empty strings. Hence, EDOM
is a correct indicator.
While I do think this bug is stupid, I don't think it's that stupid.Dan said:Old said:On Sat, 09 Oct 2004 01:35:49 +0200, in comp.lang.c, jacob navia wrote:
This, is reflected in the standards comitee too: I discovered a buffer
overflow in the code of the asctime function, printed in the standard.
Where's the error? I checked N869, and it looks fine to me; it supplies
a buffer 'char result[26]' for holding a 25-character string plus null
terminator. Unless Jacob is thinking that it'll stop working correctly in
the year 10000; but that's not a reasonable complaint in my book.
So, what's the deal here?
A local attacker could set the clock to the year 10000,
causing undefined behaviour (which could be a root exploit).
So there is a small amount of seriousness.
There is no need to set the clock.
Just call asctime with a year of 10000
You fill a structure tm, with say year 10000, month 665, etc, and call
asctime.
No need to set the clock.
You missed the point. The idea is not to compromise *your* program, but
another program, running with root privileges, whose code you cannot
control. If that program uses the asctime function with the current date
as an argument, you can compromise it by setting the system date to
year 10k. If you have enough information about a lot of things,
you may be able to control the actual behaviour of the program to
your advantage. In theory, at least.
I have pointed out elsethread the flaw in the reasoning.
In said:I (sorta) agree that UB is difficult to live with. Maybe UB
should be done away with and replaced with "Will Crash The Program",
or even have a global bool UB indicater, like errno, which will get
set whenever UB occurs, so we can read it and shut down?
In said:While I do think this bug is stupid, I don't think it's that stupid.Dan said:Old Wolf wrote:
On Sat, 09 Oct 2004 01:35:49 +0200, in comp.lang.c, jacob navia wrote:
This, is reflected in the standards comitee too: I discovered a buffer
overflow in the code of the asctime function, printed in the standard.
Where's the error? I checked N869, and it looks fine to me; it supplies
a buffer 'char result[26]' for holding a 25-character string plus null
terminator. Unless Jacob is thinking that it'll stop working correctly in
the year 10000; but that's not a reasonable complaint in my book.
So, what's the deal here?
A local attacker could set the clock to the year 10000,
causing undefined behaviour (which could be a root exploit).
So there is a small amount of seriousness.
There is no need to set the clock.
Just call asctime with a year of 10000
You fill a structure tm, with say year 10000, month 665, etc, and call
asctime.
No need to set the clock.
You missed the point. The idea is not to compromise *your* program, but
another program, running with root privileges, whose code you cannot
control. If that program uses the asctime function with the current date
as an argument, you can compromise it by setting the system date to
year 10k. If you have enough information about a lot of things,
you may be able to control the actual behaviour of the program to
your advantage. In theory, at least.
I have pointed out elsethread the flaw in the reasoning.
Imagine code which accepts input from a user which it will pass to
asctime. Now I would expect that I'd have to check for some things
myself (like months<12, check the number of days is approriate) else bad
things might happen. However I might not expect that I have to also
check year<10000 (and there are applications where year>10000 is not
entirely stupid).
goose said:Like I said, I'm perfectly happy with learning not to
cause UB. But, to the new C programmer (which I'm seeing
less these days),
UB is a hard concept to *get through*
Calling a <time.h> function with a date that cannot be represented by
time_t invokes undefined behaviour.
Dan said:It can't be done. Far too many instances of UB are both harmless
and undetectable. Others are too expensive to detect and trying
to detect them would slow down correct programs for no redeeming
benefits.
chris said:.... snip ...
While I do think this bug is stupid, I don't think it's that stupid.
Imagine code which accepts input from a user which it will pass to
asctime. Now I would expect that I'd have to check for some things
myself (like months<12, check the number of days is approriate) else
bad things might happen. However I might not expect that I have to
also check year<10000 (and there are applications where year>10000
is not entirely stupid).
Dan said:It can't be done. Far too many instances of UB are both harmless and
undetectable. Others are too expensive to detect and trying to detect
them would slow down correct programs for no redeeming benefits.
Purify provides a good example of the overheads incurred by the attempt
to detect as many memory access related instances of UB as possible.
I'm happy enough with the Unix systems that unconditionally crash the
program at any attempt of dereferencing a null pointer. And I hate the
ones that make null pointers behave like empty strings (page zero
mapped in the process address space and filled with zeroes).
Keith Thompson wrote:
The discussion in comp.std.c didn't lead to anything.
Most of the people in comp.std.c and here think that
C++ is the way to go, hence, C should stay where it is
and disappear.
The gets function is still there, trigraphs are still there,
jacob navia said:The atmosphere in this forum, the whole attitude towards data
processing concepts like using higher level data-structures,
etc. All this contributes to make C obsolete slowly but surely.
It will die a natural death when the programmers that now
know it retire.
Concepts such as security, defensive programming, avoiding
buffer overflows, etc, is shunned from the discussion.
The answers I get are significative:
"There is so much UB in the library that is hopeless to even start
trying to fix it"
No. You do not want it?
Do not include
#include <stdlist.h>
<snip> If you do not use the floating
point library (math.h) you just do not write:
#include <math.h>
and all names are still available to you and it is a legal
program.
That's true, since it uses a different name than the standard one. YouYou can then write:
myfloat mysin(myfloat arg);
and you can code the sinus function using only integer operations
and table lookups.
In said:(e-mail address removed) (Dan Pop) writes:
[...]Calling a <time.h> function with a date that cannot be represented by
time_t invokes undefined behaviour.
That's not true for asctime(). The algorithm, which is presented in
the standard (and is admittedly flawed) makes no reference to time_t.
On a system where time_t overflows in, say, 2038, actime() must still
work properly for a date in the year 2100.
On a system where time_t
can represent years after 9999, asctime still invokes undefined
behavior given an argument representing a time in the year 11000.
In said:(e-mail address removed) (Dan Pop) writes:
[...]Calling a <time.h> function with a date that cannot be represented by
time_t invokes undefined behaviour.
That's not true for asctime(). The algorithm, which is presented in
the standard (and is admittedly flawed) makes no reference to time_t.
It doesn't have to. If you're passing asctime() a value out of range
for the <time.h> implementation, you're invoking undefined behaviour.
Admittedly, the standard fails to say so, leaving the algorithm to
define when an asctime call invokes undefined behaviour.
It is this requirement that I consider the real bug in the standard.
asctime() must be seen as part of a package, rather than as an
independently defined entity.
From a realistic point of view, it makes no sense to fill a tm struct
with values by hand and then pass it to asctime.
In said:[email protected] (Dan Pop) said:In said:(e-mail address removed) (Dan Pop) writes:
[...]
Calling a <time.h> function with a date that cannot be represented by
time_t invokes undefined behaviour.
That's not true for asctime(). The algorithm, which is presented in
the standard (and is admittedly flawed) makes no reference to time_t.
It doesn't have to. If you're passing asctime() a value out of range
for the <time.h> implementation, you're invoking undefined behaviour.
Admittedly, the standard fails to say so, leaving the algorithm to
define when an asctime call invokes undefined behaviour.
So you're arguing that time_t is the fundamental type on which
everything in <time.h> is based, and that a struct tm value that
represents a time outside the range of time_t is invalid. As you
admit, the standard doesn't actually say this, so I don't understand
how you came to this conclusion.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Why?
It's not a "bug", it's just something that you don't like.
[...]
From a realistic point of view, it makes no sense to fill a tm struct
with values by hand and then pass it to asctime.
Sure it does. The standard says that this is allowed (unless you can
point to explicit wording that says otherwise).
In said:(e-mail address removed) (Dan Pop) writes: [...]^^^^^^^^^^^^^^^^^^^^^^^^^^^^It is this requirement that I consider the real bug in the standard.
asctime() must be seen as part of a package, rather than as an ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
independently defined entity.
Why?
Reading impaired? The answer was just above your question, readily
available for your perusal.
I hope you didn't ask why asctime() must be seen as part of a package,
because the answer should be obvious.
Reading impaired? I didn't say it's a bug, I said "I consider the real
bug" which strongly implies a personal judgment, i.e. it's just something
that I don't like.
In said:[email protected] (Dan Pop) said:In said:(e-mail address removed) (Dan Pop) writes: [...]
It is this requirement that I consider the real bug in the standard.
asctime() must be seen as part of a package, rather than as an ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
independently defined entity.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Why?
Reading impaired? The answer was just above your question, readily
available for your perusal.
I see only a blatant assertion which you've chosen not to justify.
No, I'm not reading impaired, but thank you for your kind concern.
I'm reading the actual standard. I don't know what you're reading.
Ok, so you don't like what the standard actually says. That's fine;
you might consider discussing it in comp.std.c.
What the standard actually *says* is internally consistent (if a bit
odd), and your interpretation of it is no more than wishful thinking.
Try this, Dan. Pretend that I've asserted that "Calling a <time.h>
function with a date that cannot be represented by time_t invokes
undefined behaviour." I'm sure you wouldn't have any trouble arguing
that I'm wrong.
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.