K
Keith Thompson
Tom St Denis said:My point more so was that as an instantiation of an environment in
which C may be used it's not always so fubared or dramatic. Ideally,
if the spec says the output can only be 26 chars the Sun platform
should return an appropriate error condition instead of crashing. And
that's THEIR fault for so blindly copying it.
No, it's your fault for calling asctime with an argument for which its
behavior is undefined. It's a more understandable error than
char s[5];
strcpy(s, "hello, world");
because the valid inputs for asctime() are harder to figure out than
the valid input for strcpy(). But it's still the case that your
program's behavior is undefined, and can blow up on a conforming
implementation.
As it turns out, Sun *didn't* blindly copy the implementation in the
standard. Here's a modified version of your program:
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
struct tm t;
char *p;
memset(&t, 0, sizeof t);
t.tm_year = 10000;
p = asctime(&t);
if (p == NULL) {
puts("asctime returned NULL");
}
else {
printf("asctime returned %p --> \"%s\"\n", (void*)p, p);
}
return 0;
}
and its output on Solaris 9:
asctime returned NULL
The standard doesn't specify that asctime returns a null pointer on
error, but it's a reasonable convention -- and it would have helped
you catch your error more quickly than on a glibc-based
implementation.
[...]
I just read the C99 spec for asctime. Nowhere does it say the buffer
can only be 26 bytes. It describes what the output format must look
like, but never mentions the length. The C code happens to mention
the length in passing but I really consider the C code an example [a
poor one] that produces the desired output format.
No, the C code is not just an example. It is the definition of the
algorithm.
I haven't read anywhere that says you can't have a year of 11900.
Read the algorithm in the standard. Trace through it, and see what
happens if you pass it a year of 11900. It's not stated explicitly
(which is unfortunate), but it's still right there in black and white.
I
also don't consider the C code in the spec to define how the algorithm
that produces the output must be written.
No, but whatever algorithm is used must be equivalent to the one
presented.
To me the definition of
asctime() is
---
The asctime function converts the broken-down time in the structure
pointed to by timeptr into a string in the form
Sun Sep 16 01:03:52 1973\n\0
---
Only if you stop reading there. The rest of that section isn't
decorative; it means something.
[...]
Well I think that's the bigger point here, these C functions have
explicit/implicit assumptions of the inputs.
Yes.
I haven't read anywhere that explicitly states you can't pass memcpy()
[section 7.21.2.1] NULL as one of the pointers. We just "know" that
because dereferencing a NULL pointer leads to undefined behaviour.
C99 7.1.4, Use of library functions:
Each of the following statements applies unless explicitly
stated otherwise in the detailed descriptions that follow:
If an argument to a function has an invalid value (such as
a value outside the domain of the function, or a pointer
outside the address space of the program, or a null pointer,
or a pointer to non-modifiable storage when the corresponding
parameter is not const-qualified) or a type (after promotion)
not expected by a function with variable number of arguments,
the behavior is undefined.
Similarly, by reading the code, assuming you assume that that is the
way your function is implemented it's obvious that you can't have a 5+
digit year. That's an implicit assumption based on the behaviour of
the function based on the description.
And really that's the point. We have people who are not strong
software developers bitching about the fact that they have to sanitize
and properly test their inputs. They'd rather hack together whatever
they can as fast and as incoherently as possible and are pissed that
software development is ACTUALLY REALLY HARD WORK.
jacob has strongly criticized the standard's definition of asctime().
Some of his criticisms are overstated; some I actually agree with.
I don't think we can reasonably assume he dislikes asctime()
because using it is "REALLY HARD WORK". Perhaps you were talking
about developers other than jacob, but I don't recall anyone else
complaining about asctime() (well, I have).