J
Jordan Abel
Jeff said:Jordan said:boa wrote:
Jordan Abel wrote:
In the function below, can size ever be 0 (zero)?
I've never heard of the "clc string lib" - where can i find it?
http://libclc.sf.net
char *clc_strdup(const char * CLC_RESTRICT s)
{
size_t size;
char *p;
clc_assert_not_null(clc_strdup, s);
No idea how this would work in a way that needs the function pointer as
its first argument. Is it a macro that stringizes its first argument to
print an error?
size = strlen(s) + 1;
The result of this assignment cannot be zero.
if (size == 0)
p = NULL;
hold on - i take that back. size can be 0 if strlen returns SIZE_MAX.
size can never be SIZE_MAX as size doesn't include '\0'. A valid string
always has the '\0' and the max size of a buffer containing a string is
SIZE_MAX.
boa
One more try: strlen() can never return SIZE_MAX. A valid string
always has the '\0' and the max size of a buffer containing a string is
SIZE_MAX, so the max value strlen() can return is SIZE_MAX - 1.
boa
take SIZE_MAX 65535
char * foo = calloc(256,256);
memset(foo,"x",SIZE_MAX);
strlen(foo) == SIZE_MAX;
I don't think there's an explicit requirement in the standard that there
never be an object smaller than SIZE_MAX. There may, however, be a
requirement that the product of the arguments to calloc be less than
SIZE_MAX. [that, i don't know.]
That's my point below. You can't allocate more than SIZE_MAX so the
strlen would be SIZE_MAX -1, so in the example above, size could not be
0 (zero). I may be missing something, but the check 'if (size == 0)'
seems pointless.
See my other post, the standard does not forbid Jordan's code as far as
I can see. So if the call to calloc succeeds you have *legally* created
an object larger than SIZE_MAX.
Yeah - it's not particularly _likely_ to succeed on any reasonable
implementation [relevant code from my implementation: if (size != 0 &&
SIZE_T_MAX / size < num) { errno = ENOMEM; return (NULL); }], but if it
does succeed, there's nothing wrong with the rest of the code, and
strlen()+1 will be 0. [with some work, it would be possible to make a
strdup that uses the same trickery to successfully duplicate such an
object]
Note that this strdup does have another problem with implementations
that allow an object larger than SIZE_MAX.
/* SIZE_MAX 65535 */
char *p = calloc(256,257)
memset(p,'a',256);
memset(p+256,'a',SIZE_MAX);
char *q = clc_strdup(p);
if everything succeeds (and strlen does what can reasonably be expected
- it's unclear, and thus probaby undefined, what passing a string longer
than SIZE_MAX to strlen actually will result in), q points to an array
of 256 chars, each set to 'a', and not null-terminated.
Attempting to catch a corner case like a string that is exactly SIZE_MAX
long seems pointless when it ignores the possibility of a string longer
than SIZE_MAX.