asn1c
compiler has the following code (it's C
code, not C++
):
return asn1c_make_identifier(
AMI_MASK_ONLY_SPACES | AMI_NODELIMITER,
0, ((!stdname || (arg->flags & A1C_INCLUDES_QUOTED))
? "\"" : "<"),
exprid ? exprid->Identifier : typename,
((!stdname || (arg->flags & A1C_INCLUDES_QUOTED))
? ".h\"" : ".h>"), 0);
For simplicity I could write the following (it doesn't affect the bug):
return asn1c_make_identifier(
AMI_MASK_ONLY_SPACES | AMI_NODELIMITER,
0, "str1",
"str2",
"str3", 0);
The function asn1c_make_identifier
has the following definition char * asn1c_make_identifier(enum ami_flags_e flags, asn1p_expr_t *expr, ...)
and standart va_list
processing loop:
va_start(ap, expr);
while((str = va_arg(ap, char *)))
size += 1 + strlen(str);
va_end(ap);
So, we get 3 strings and one zero. Everything seems to be good (and it works in Linux), but in cygwin I get the fourth iteration with non zero str. As a result segmentation fault happens. But if I write (char*)
before 0
the code works as it should. Is it a real bug of cygwin or is it a bug in the source code? It's not my code and it contains a number of similiar zeros.
P.S. About gcc
version
gcc --version
gcc (GCC) 4.8.3
The problem is that 0
is being interpreted as an integer, not as a pointer. Since the compiler cannot know what the types of variadic arguments are supposed to be, it can't convert to the type you intend.
So, when the compiler sees the expression 0
as an argument, it interprets it as an expression of type int
, not of type void *
(or char *
, or any other pointer).
Because you're compiling for x64, sizeof(int)
is 4 and sizeof(char *)
is 8, so va_arg
is reading more data from the stack than what's passed to it.
Instead, you should pass the constant NULL
, which is of type void *
, or for maximum portability, pass the expression (char *)NULL
.