cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: Not passing "long" to varargs (was Re: curl_easy_setopt and typeof)

From: Jamie Lokier <jamie_at_shareable.org>
Date: Mon, 14 Apr 2008 10:27:11 +0100

David Shaw wrote:
> On Apr 13, 2008, at 12:04 PM, Jamie Lokier wrote:
> >The second line of output isn't guaranteed to be the same with every
> >compiler: it has undefined behaviour, because an int argument is
> >passed to a varargs function expecting long. It could even crash on
> >some systems.
>
> Following that logic, wouldn't that mean that this:
>
> curl_easy_setopt( curl, CURLOPT_MAXREDIRS, -1 );
>
> is incorrect?
>
> After all, as you say, curl_easy_setopt is documented to take a long,
> but without a cast, that bare -1 is going to go over as an int.

That's right.

> printf(" -1 == %ld\n",-1);
> printf("(long)-1 == %ld\n",(long)-1);
> }
>
> $ gcc bar.c -m64
> $ ./a.out
> int is 4 bytes and long is 8 bytes
> -1 == 4294967295
> (long)-1 == -1

And your example proves it... bet nobody took that seriously before!

> There is probably a heck of a lot of code using libcurl that doesn't
> cast constants to long...

Fortunately, the new type checker would catch them if it complained
about "int" arguments.

Or maybe it can even generate the cast?

Portable way to do that might be:

#define curl_easy_setopt(handle, cmd, arg) \
  curl_easy_setopt(handle, cmd, curl_easy_setopt_cast(cmd) (arg))

#define curl_easy_setopt_cast(cmd) curl_easy_setopt_cast_2(cmd)
#define curl_easy_setopt_cast_2(cmd) curl_easy_setopt_cast_##cmd

#define curl_easy_setopt_cast_CURLOPT_MAXREDIRS (long)
// ... one macro for each option

-- Jamie
Received on 2008-04-14