Finally, adding one more bit of instrumentation shows that TCC can crash 
because of the uninitialized variable being discussed in this thread.

On 08 Mar 2019, at 20:06, Pascal Cuoq 
<[email protected]<mailto:[email protected]>> wrote:

the simplest way to make this problem visible is to instrument the functions 
type_decl and post_type:

diff --git a/tccgen.c b/tccgen.c
index 87ec798..7fa6c72 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -4374,7 +4374,7 @@ static int post_type(CType *type, AttributeDef *ad, int 
storage, int td)
     Sym **plast, *s, *first;
     AttributeDef ad1;
     CType pt;
-
+    n = 0xf00f0011;
     if (tok == '(') {
         /* function type, or recursive declarator (return if so) */
         next();
@@ -4410,6 +4410,7 @@ static int post_type(CType *type, AttributeDef *ad, int 
storage, int td)
                 }
                 convert_parameter_type(&pt);
                 arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE;
+                if (n == 0xf00f0011) printf("using n uninitialized\n");
                 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
                 *plast = s;
                 plast = &s->next;
@@ -4583,7 +4584,7 @@ static CType *type_decl(CType *type, AttributeDef *ad, 
int *v, int td)
            parse_attribute(ad);
            post = type_decl(type, ad, v, td);
            skip(')');
-       }
+       } else printf("*v left uninitialized\n");
     } else if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
        /* type identifier */
        *v = tok;


The function post_type declares an automatic variable n and does not initialize 
it. Setting it to 0xf00f0011 allows to see that it has not been assigned when 
it is used later in this function (ored with SYM_FIELD and passed as argument 
to the function sym_push). When “using n uninitialized” is printed in the 
instrumented version of TCC, it means that n would have been used uninitialized 
in the uninstrumented version of the compiler.

To understand the crash, add the following patch to the instrumentation that 
was already discussed:

diff --git a/tccgen.c b/tccgen.c
index 87ec798..ee5a838 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -588,6 +588,10 @@ ST_FUNC Sym *sym_push(int v, CType *type, int r, int c)
     /* XXX: simplify */
     if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
         /* record symbol in token array */
+        if (v == 0xd00f0011) {
+          printf("v < 0, this will not go well\n");
+          fflush(stdout);
+        }
         ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
         if (v & SYM_STRUCT)
             ps = &ts->sym_struct;


This patch shows that the value 0xf00f0011, that was been chosen as the value 
of the uninitialized variable n in the function type_decl, can for some inputs 
be propagated until it is used to compute an address.

$ cat c.i
int f(int ()) {
  return 0;
}
$ ./tcc -c c.i
*v left uninitialized
using n uninitialized
v < 0, this will not go well
Segmentation fault

The crash may be more difficult to observe without the first part of the 
instrumentation, but regardless the root cause for it, when it happens, is the 
fact that the automatic variable n from the function type_decl is sometimes 
incorporated into computations without having been set beforehand.

Pascal

_______________________________________________
Tinycc-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

Reply via email to