The attached patch fixes an uninitialized read from memory in `union_memsize`.

The summary of how the bug happens is:

1. union_memsize gets called with a pointer to uninitialized `dummy`.
```
static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs,
                                    type_t *type, unsigned int *tfsoff)
{
    [...]
    unsigned int dummy;
    [...]
    size = union_memsize(fields, &dummy);
```

2. `union_memsize` reads `pmaxa` (which points to dummy) to set the
initial value of align.

```
static unsigned int union_memsize(const var_list_t *fields, unsigned
int *pmaxa) {
    unsigned int size, maxs = 0;
    unsigned int align = *pmaxa;
    const var_t *v;

    if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
    {
        /* we could have an empty default field with NULL type */
        if (v->declspec.type)
        {
            size = type_memsize_and_alignment(v->declspec.type, &align);
            if (maxs < size) maxs = size;
            if (*pmaxa < align) *pmaxa = align;
        }
    }
```

The rest of the code in `type_memsize_and_alignment` works with that
unitialized alignment value. If the uninitialized memory happens to
represent a larger uint than the actual max size of the union, then
that value is printed in the result.

Thanks!
- Raphael Isemann
diff --git a/mingw-w64-tools/widl/src/typegen.c b/mingw-w64-tools/widl/src/typegen.c
index b2d9ab5d1..eb0fa5e06 100644
--- a/mingw-w64-tools/widl/src/typegen.c
+++ b/mingw-w64-tools/widl/src/typegen.c
@@ -3310,41 +3310,41 @@ static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
             short reloff = t->typestring_offset - *tfsoff;
             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %d (%d) */\n",
                        reloff, reloff, t->typestring_offset);
         }
         else
             error("write_branch_type: type unimplemented %d\n", type_get_type(t));
     }
 
     *tfsoff += 2;
 }
 
 static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs,
                                     type_t *type, unsigned int *tfsoff)
 {
     unsigned int start_offset;
     unsigned int size;
     var_list_t *fields;
     unsigned int nbranch = 0;
     type_t *deftype = NULL;
     short nodeftype = 0xffff;
-    unsigned int dummy;
+    unsigned int dummy = 0;
     var_t *f;
 
     if (processed(type) &&
         (type_get_type(type) == TYPE_ENCAPSULATED_UNION || !is_attr(type->attrs, ATTR_SWITCHTYPE)))
         return type->typestring_offset;
 
     guard_rec(type);
 
     fields = type_union_get_cases(type);
 
     size = union_memsize(fields, &dummy);
 
     if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
     {
         expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
         if (cases)
             nbranch += list_count(cases);
         if (f->declspec.type)
             write_embedded_types(file, f->attrs, f->declspec.type, f->name, TRUE, tfsoff);
     }
_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to