OK Here is what goes wrong. (At least it is something that comes
as a surprise to me.) C code that is not fully preprocessed
cannot be properly reduced (at least not with reduce-array-size)
If I try this example I get a nice reduction
typedef unsigned int uint32_t;
uint32_t g_33[4];
void func_1 ()
{
uint32_t *l_32 = &g_33[2];
++*l_32;
return 0;
}
$ clang_delta --transformation=reduce-array-size --counter=1 /tmp/bug5.c|diff
/tmp/bug5.c -
4c4
< uint32_t g_33[4];
---
> uint32_t g_33[3];
But if I leave out the typedef (or perhaps have #include "csmith.h") I get this
$ clang_delta --transformation=reduce-array-size --counter=1 /tmp/bug5.c | diff
/tmp/bug5.c -
4c4
< uint32_t g_33[4];
---
> uint32_t g_33[1];
In other words, the method
ReduceArraySizeCollectionVisitor::VisitArraySubscriptExpr
is never called and thus no information is collected about the used array
indices for
g_33[].
Perhaps you'll now say "Of course you have to preprocess first". But that
doesn't work for me
because in my reduction script I want to use several compilers (host and cross)
and
these have totally different preprocess needs. If I preprocess with gcc I get
output which
I cannot compiler with my own compiler and vice versa.
-- Kees
On 29-07-13 09:47, Yang Chen wrote:
Not all C-Reduce's passes know the C semantics, for example, the simple pass I
mentioned before. Here is my guess about what happened:
(1) the simple pass replaced "10" with "0", and we got tmp1.c;
(2) maybe the replacement made the bug-behavior disappear, so the tmp1.c was
discarded;
(3) the simple pass replaced "10" with "1", and we got tmp1.c where we had UB g_33[1]. Because there was no external UB-checker, and this UB could make the test script believe that the bug was
triggered by tmp1.c, then tmp1.c were saved as the current test case for the future reduction.
I agree that in most cases C-Reduce needs to avoid generating code like g_33[1] in this example, but it requires to replace existing perl transformations with corresponding Clang ones. Some are on
our TODO list.
- Yang
On 7/29/13 1:10 AM, Kees Bakker wrote:
Well, it should be replaced with &g_33[0].
On 26-07-13 17:44, Yang Chen wrote:
No, I think it's not a reduce-array-size bug. Some other pass running before
reduce-array-size could simply replace an expression with 0 or 1. In this case,
that pass could just turn
"uint32_t *l_32 = &g_33[10];"
into
"uint32_t *l_32 = &g_33[1];"
- Yang
On 7/26/13 8:51 AM, Kees Bakker wrote:
Could this be a bug with reduce-array-size?
If I step through the clang_delta code I don't see
it visit ReduceArraySizeCollectionVisitor::VisitArraySubscriptExpr
And that may be the reason why the resulting dimension is alway 1.
Just guessing.
On 26-07-13 13:49, Kees Bakker wrote:
Hi,
Does anyone have suggestions how to avoid reduction that
reads/writes outside an array.
The reason I ask, after creduce is finished I get this code
uint32_t g_33[1]; // <====
uint32_t g_202[4];
int8_t
func_1 ()
{
uint32_t *l_32 = &g_33[1]; // <===
uint32_t *l_972 = &g_202[0];
++*l_32, *l_972 = g_708.f1;
return 0;
}
This fails because the program writes outside the g_33 array.
My own compiler tools have boundary checks, but this is a cross
compiler and I'm using a simulator to run the result. It's doable
but slow.
So far, with clang, gcc, valgrind I couldn't find a method to detect
array boundary violations.
(( BTW I'm not sure if this is a creduce bug. ))
--
Kees