https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116376

            Bug ID: 116376
           Summary: `genpreds` segmentation fault caused by dereferencing
                    null pointer in `gcc/hash_table.h`
           Product: gcc
           Version: 15.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: radek.barton at microsoft dot com
  Target Milestone: ---

While building native `aarch64-w64-mingw32` toolchain using
https://github.com/Windows-on-ARM-Experiments/MINGW-packages/blob/woarm64/mingw-w64-gcc/PKGBUILD#L230
MSYS2 recipe, I've encountered `genpreds.exe` segmentation fault crash
happening at
https://github.com/gcc-mirror/gcc/blob/edb2712936368e803fd67aa520323054b2a5c5e7/gcc/hash-table.h#L879
becase the `p` variable being dereferenced is NULL.

I've narrowed down the repro-case to:

```bash
echo "(define_register_constraint \"a\" \"b\" \"c\" \"d\")" > test.md
./genpreds.exe -h test.md
```

and then stepped down the `genpreds.exe`'s code using debugger. The issue seems
to be caused by the fact that `oentries` can be initialized to `NULL` at
https://github.com/gcc-mirror/gcc/blob/edb2712936368e803fd67aa520323054b2a5c5e7/gcc/hash-table.h#L837
as the `m_entries` can be `NULL` in general (due to lazy initialization). Then
`p` can be initialized to `NULL` at
https://github.com/gcc-mirror/gcc/blob/edb2712936368e803fd67aa520323054b2a5c5e7/gcc/hash-table.h#L874
leading to dereferencing `NULL` pointer thre lines further.

The following patch seems to be an ugly workaround:

```patch
diff --git a/gcc/hash-table.h b/gcc/hash-table.h
index 3a52a8b785c..9c809eca5e4 100644
--- a/gcc/hash-table.h
+++ b/gcc/hash-table.h
@@ -874,6 +874,9 @@ hash_table<Descriptor, Lazy, Allocator>::expand ()
   value_type *p = oentries;
   do
     {
+      if (!p)
+        break;
+
       value_type &x = *p;

       if (is_empty (x))
@@ -896,6 +899,9 @@ hash_table<Descriptor, Lazy, Allocator>::expand ()

   gcc_checking_assert (!n_elements && !n_deleted);

+  if (!oentries)
+    return;
+
   if (!m_ggc)
     Allocator <value_type> ::data_free (oentries);
   else
```

This issue seems to be very similar to
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100131 but the affected code is
dated to more than year earlier date.

Reply via email to