You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is the result of the following byte-update VCC:
ptrs!0@1#4 == byte_update_little_endian(ptrs!0@1#3, 8l, &a!0@1, struct A { signed int x; } *)
Clearly sensible so far. However the byte-update-flattening logic (only used for VLAs) at flatten_byte_operators.cpp:191 has two problems for the case where the target array members are not bytes:
It loops over each byte in the value operand, but writes each one to the same target address.
When recursively using byte_update over scalar array members, it updates with respect to the original source operand, not any partially-updated array resulting from previous byte ops.
For example, if memory contained bytes {1,2,3,4} typed as an int[] and we tried to write (short){5,6} over the first two bytes, we would end up with intermediate result {5,6,3,4} but ultimate result {6,x,3,4} because the second overwrite doesn't use an appropriate shift+mask, hence parts of the address of a ending up in the less-significant bits of the target array and being reported as NULL + (void*)3
smowton@fd1bbd1 fixes the issue, but at the cost of introducing an overly large expression (quadratic in the number of bytes changed), as the intermediate result array must be referenced as both the byte_update operand and the with operand, and AFAIK it is illegal to introduce intermediate symbols at this stage.
I will have a go at producing a version of this patch that only touches each target array element once tomorrow morning.
The text was updated successfully, but these errors were encountered:
smowton@fa2666b implements a better algorithm, and smowton@9612165 adds the test-case given above plus various misaligned update tests.
The formulae produced for the case where elements have different sizes are still quite large, probably because of the if test introduced to allow byte-update of a scalar with a negative offset (i.e. overwriting only the least-significant bytes). This could be worked around by zero-padding and adding instead; I'll give this a go when more free time presents itself.
smowton@d962d79 cleans up a little, but the time consumption turns out to result mainly from array-constraint generation taking a long time, a problem which should probably be considered orthogonally from this one.
Therefore if you're happy with this solution I'll put them together into a branch against master.
Example test case:
Naturally we expect the assert to pass, since we've just assigned
a
on the previous line. However the trace shows not&a
as we might expect, but:This is the result of the following byte-update VCC:
Clearly sensible so far. However the byte-update-flattening logic (only used for VLAs) at
flatten_byte_operators.cpp:191
has two problems for the case where the target array members are not bytes:byte_update
over scalar array members, it updates with respect to the original source operand, not any partially-updated array resulting from previous byte ops.For example, if memory contained bytes
{1,2,3,4}
typed as anint[]
and we tried to write(short){5,6}
over the first two bytes, we would end up with intermediate result{5,6,3,4}
but ultimate result{6,x,3,4}
because the second overwrite doesn't use an appropriate shift+mask, hence parts of the address ofa
ending up in the less-significant bits of the target array and being reported asNULL + (void*)3
smowton@fd1bbd1 fixes the issue, but at the cost of introducing an overly large expression (quadratic in the number of bytes changed), as the intermediate result array must be referenced as both the
byte_update
operand and thewith
operand, and AFAIK it is illegal to introduce intermediate symbols at this stage.I will have a go at producing a version of this patch that only touches each target array element once tomorrow morning.
The text was updated successfully, but these errors were encountered: