Hi Yang,

OK, forget about the line with the typedef. Replace it with
#include "csmith"
My next question is: is the example invalid for creduce, or do
you expect that the clang parser knows how to find csmith.h?

If the example is for creduce then that contradicts John's answer
where he says: "I reduce non-preprocessed C code routinely."

If the clang parser must be able to find csmith.h then there must be
a way to specify include directories. So far, I haven't found out how
to do that. Creduce has no -I option, does it?
-- Kees

On 29-07-13 16:40, Yang Chen wrote:
Hi Kees,

Clang-related passes rely on the AST constructed by Clang. When the type of uint32_t is unknown, the AST for the code is not fully constructed, e.g. there is no ArraySubscriptExpr node and hence VisitArraySubscriptExpr cannot be invoked. We will get the difference once we remove the comment on "typedef".

$ cat tmp1.c
//typedef unsigned int uint32_t;

uint32_t g_33[4];

int func_1 ()
{
    uint32_t *l_32 = &g_33[2];
    ++*l_32;
    return 0;
}
$ clang -cc1 -ast-dump tmp1.c
tmp1.c:3:1: error: unknown type name 'uint32_t'
uint32_t g_33[4];
^
tmp1.c:7:5: error: use of undeclared identifier 'uint32_t'
    uint32_t *l_32 = &g_33[2];
    ^
tmp1.c:7:15: error: use of undeclared identifier 'l_32'
    uint32_t *l_32 = &g_33[2];
              ^
tmp1.c:8:8: error: use of undeclared identifier 'l_32'
    ++*l_32;
       ^
TranslationUnitDecl 0x2ab0a40 <<invalid sloc>>
|-TypedefDecl 0x2ab0f40 <<invalid sloc>> __int128_t '__int128'
|-TypedefDecl 0x2ab0fa0 <<invalid sloc>> __uint128_t 'unsigned __int128'
|-TypedefDecl 0x2ab12f0 <<invalid sloc>> __builtin_va_list '__va_list_tag [1]'
|-VarDecl 0x2ab13d0 <tmp1.c:3:1, <invalid sloc>> g_33 'int [4]'
`-FunctionDecl 0x2ab1480 <line:5:1, line:10:1> func_1 'int ()'
  `-CompoundStmt 0x2ab1580 <line:6:1, line:10:1>
    `-ReturnStmt 0x2ab1560 <line:9:5, col:12>
      `-IntegerLiteral 0x2ab1540 <col:12> 'int' 0
4 errors generated.

- Yang

On 7/29/13 8:11 AM, Kees Bakker wrote:
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

Reply via email to