Hi John,
I have no problem with the fact that C-Reduce can introduce undefined behaviour.
But in this case, reduce-array-size becomes useless pretty quickly if the input
hasn't been preprocessed. And, as I mentioned before, it is often hard to detect
out of boundary array accesses.
I will experiment a bit with disabling reduce-array-size.
-- Kees
On 29-07-13 15:48, John Regehr wrote:
Hi Kees,
C-Reduce is definitely intended for use with either preprocessed or
not-preprocessed C code. I reduce non-preprocessed C code routinely.
On the other hand, C-Reduce is simply not designed to avoid introducing undefined behaviors. If there are some very easy things we can do to avoid introducing undefined behaviors, we might make
those changes. However, in general avoiding those problems is a non-goal for us.
John
On 7/29/13 9:42 AM, Kees Bakker wrote:
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