On Mon, Jan 07, 2013 at 03:50:01PM +0000, Petr Pisar wrote:
> yap-6.2.2-4.fc18.src.rpm
> similar to getdata bug:
> LAST_FLAG = 23
> ...
> #define NUMBER_OF_YAP_FLAGS LAST_FLAG
> ...
> #define yap_flags Yap_heap_regs->yap_flags_field
> ...
> Int yap_flags_field[NUMBER_OF_YAP_FLAGS];
> ...
> /* This must be done before initialising predicates */
> for (i = 0; i <= LAST_FLAG; i++) {
> yap_flags[i] = 0;
> }
>
What's wrong with assigning 0 that fits into any intenger? C99 says:
6.3.1.3 Signed and unsigned integers
1 When a value with integer type is converted to another integer type
other than _Bool, if the value can be represented by the new type,
it is unchanged.
The pre-precessed code is:
for (i = 0; i <= LAST_FLAG; i++) {
((all_heap_codes *)(0x10000000))->yap_flags_field[i] = 0;
}
Type of yap_flags_field is int[].
That's not correct, type of yap_flags_field is int[NUMBER_OF_YAP_FLAGS]
aka int[LAST_FLAG]. The undefined behavior happens in the last iteration,
where you do
((all_heap_codes *)(0x10000000))->yap_flags_field[LAST_FLAG] = 0;
ISO C99 6.5.2.1 says that this is equivalent to:
(*((((all_heap_codes *)(0x10000000))->yap_flags_field)+(LAST_FLAG))) = 0;
and then 6.5.6/8 (last sentence) applies:
"If the result points one past the last element of the array object, it
shall not be used as the operand of a unary * operator that is evaluated."
Note the array is in a middle of a structure, not at the end, where is the
only place where flexible array members could be present and as an extension
GCC allows even non-flexible arrays to be treated similarly to flexible
arrays (case where people use say struct S { ...; int a[1]; }; as some kind
of pre-C99 flexible array members).
Jakub