Fix GC heap corruption on ARM. (#1389)
authorAnton Lapounov <antonl@microsoft.com>
Wed, 8 Jan 2020 10:12:25 +0000 (02:12 -0800)
committerGitHub <noreply@github.com>
Wed, 8 Jan 2020 10:12:25 +0000 (02:12 -0800)
The allocate_in_free code path in allocate_in_expanded_heap incorrectly calculated the large (double) alignment padding size when limiting the plug size (SHORT_PLUGS) if set_padding_on_saved_p was true:

    set_padding_in_expand (old_loc, set_padding_on_saved_p, pinned_plug_entry); // Sets the padding flag on the saved plug
    ...
    pad += switch_alignment_size (is_plug_padded (old_loc)); // Reads the padding flag from the old (different!) plug

That caused access violation during a later heap walk since the g_gc_pFreeObjectMethodTable pointer marking the gap was not placed at the right address.

src/coreclr/src/gc/gc.cpp

index c79e1de..db717b1 100644 (file)
@@ -15186,7 +15186,7 @@ allocate_in_free:
 #else // FEATURE_STRUCTALIGN
         if (!((old_loc == 0) || same_large_alignment_p (old_loc, result+pad)))
         {
-            pad += switch_alignment_size (is_plug_padded (old_loc));
+            pad += switch_alignment_size (pad != 0);
             set_node_realigned (old_loc);
             dprintf (3, ("Allocation realignment old_loc: %Ix, new_loc:%Ix",
                          (size_t)old_loc, (size_t)(result+pad)));