[64-bit] curl: fix -i option (include headers)

Corinna Vinschen corinna-cygwin@cygwin.com
Mon Aug 12 10:49:00 GMT 2013

On Aug 11 22:36, Andreas Winkelbauer wrote:
> Hi,
> recently I stumbled across a bug in curl for 64-bit Cygwin regarding the
> -i option. This bug has already been discussed in April 2013:
> http://cygwin.1069669.n5.nabble.com/Difference-in-32-64-bit-curl-td98083.html
> (I can't reply directly since I was not subscribed to this mailinglist
> back then.)
> The problem is that the current version of curl always includes the
> protocol headers in the output (no matter if -i or --include or
> --no-include are used or not). This bug breaks scripts which use curl
> and expect it to not include the headers in the output.
> After some debugging I found out that the cause of the problem is a
> missing cast of the third argument of my_setopt in tool_operate.c:886
> (line numbers from curl 7.29.0)
> my_setopt(curl, CURLOPT_HEADER, config->include_headers);
> Here, config->include_headers is of type bool (1 byte) and my_setopt is
> a macro which calls curl_easy_setopt() and is defined in tool_setopt.h
> as follows:
> #define my_setopt(x,y,z) \
>   SETOPT_CHECK(tool_setopt(x, FALSE, config, #y, y, z))
> tool_setopt() is implemented in tool_setopt.c and uses va_arg(arg, long)
> to get the value of its sixth argument (which is
> config->include_headers). However, sizeof(long) == 8, but sizeof(bool)
> == 1 and thus va_arg(arg, long) returns a value != 0 even if
> config->include_headers == 0.
> I am not sure why there is no problem with other boolean configuration
> options like CURLOPT_FAILONERROR (corresponding to -f or --fail) which
> are processed in exactly the same way, e.g., in tool_operate.c:930
> my_setopt(curl, CURLOPT_FAILONERROR, config->failonerror);
> Also, there is no problem in 32-bit Cygwin and in 32/64-bit Linux. Maybe
> the bug is triggered by some missing or incorrect (alignment related)
> compiler switches?

Just FYI, this is very likely a bug which is only triggered on 64 bit
Cygwin due to the different way arguments are passed to functions.
The 1 byte bool value is sign extended to int (4 byte) and not to long
(8 byte).  This doesn't matter if the arg is passed in a register since
AMD64 always zero's the high 4 byte of a register when you store a 
4 byte value in it.  But it matters as soon as the argument is passed
on the stack.

The difference between Cygwin and Linux is the calling convention.
Linux uses the SYSV ABI, with the first 6 args in registers before
subsequent regs are spilled on the stack.  Cygwin uses the MS ABI, with
only the first four args in registers.

So, type problems int vs. long in function args only start showing with
the 7th arg on Linux, but already with the 5th arg on Cygwin.


Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://cygwin.com/pipermail/cygwin/attachments/20130812/78bce05e/attachment.sig>

More information about the Cygwin mailing list