ZGC: Out-of-bounds access in relocation set partition array

XMLWordPrintable

    • Type: Bug
    • Resolution: Unresolved
    • Priority: P2
    • 26
    • Affects Version/s: 23
    • Component/s: hotspot
    • gc

      An out-of-bounds access has been reported on the mailing list:
      https://mail.openjdk.org/pipermail/zgc-dev/2025-December/001383.html

      YiFan Zhang reports:
      ---
      I looked into the VM source code and found that this appears to be an array out-of-bounds error.

      Detailed problem description :

           In function `ZRelocationSetSelectorGroup::semi_sort()` , an array partitions[npartitions] is allocated. Under the heap’s default settings, its size is 2048 (meaning indices 0 through 2047 are valid).

           However, the subsequent index used for access is determined by right-shifting each page’s live byte count, which may lead to accessing index 2048.

           Based on this, I made the following changes to the function `semi_sort()`, add a conditional branch to print corresponding information when an out-of-bounds access may occur. :

           ```

             int partitions[npartitions] = { /* zero initialize */ };

             // Calculate partition slots
             ZArrayIterator<ZPage*> iter1(&_live_pages);
             for (ZPage* page; iter1.next(&page);) {
               const size_t index = page->live_bytes() >> partition_size_shift;
               if (index >= npartitions) {
                 log_info(gc, heap)("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                 log_info(gc, heap)("Size of partition array : %zu", npartitions);
                 log_info(gc, heap)("partition_size = _page_size >> npartitions_shift : %zu = %zu >> %zu", partition_size, _page_size, npartitions_shift);
                 log_info(gc, heap)("partition_size_shift = exact_log2(partition_size) : %zu", partition_size_shift);
                 log_info(gc, heap)("Index will be visited (page->live_bytes() >> partition_size_shift): %zu", index);
                 log_info(gc, heap)("Page lived bytes: %zu", page->live_bytes());
                 log_info(gc, heap)("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
               }
               partitions[index]++;
             }

           ```
            Here is the information I obtained:
      [4.779s][info][gc,heap] !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      [4.779s][info][gc,heap] Size of partition array : 2048
      [4.779s][info][gc,heap] partition_size = _page_size >> npartitions_shift : 1024 = 2097152 >> 11
      [4.779s][info][gc,heap] partition_size_shift = exact_log2(partition_size) : 10
      [4.779s][info][gc,heap] Index will be visited (page->live_bytes() >> partition_size_shift): 2048
      [4.779s][info][gc,heap] Page lived bytes: 2097152
      [4.779s][info][gc,heap] !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      ---

            Assignee:
            Unassigned
            Reporter:
            Stefan Karlsson
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: