)]}'
{
  "commit": "8d596ea8e77711ab0109e301f71da0929bca6582",
  "tree": "b0b08ac591ff4b3510428832dedaf4c987e553e2",
  "parents": [
    "4c32d2259b1342abcdd1a6927e0869da374d02a9"
  ],
  "author": {
    "name": "Patrick Steinhardt",
    "email": "ps@pks.im",
    "time": "Tue Oct 06 12:20:15 2026 +0200"
  },
  "committer": {
    "name": "Junio C Hamano",
    "email": "gitster@pobox.com",
    "time": "Tue Oct 06 09:04:24 2026 -0700"
  },
  "message": "packfile: fix corruption due to stale delta base cache entries\n\nThe delta base cache is a process-global hashmap that is keyed by the\naddress of the `struct packed_git` plus the offset of the base object\nwithin that pack. Entries part of the cache are never removed when a\npack is closed, and neither when the pack is subsequently freed. As a\nconsequence, the cache may contain stale entries.\n\nFor a long time, the worst consequence of this leaking cache was that we\nheld on to memory that we could\u0027ve released. But the reason for this was\nthat we didn\u0027t even free the packfiles, either. That has changed in\n6f1e9394e2 (object: fix leaking packfiles when closing object store,\n2024-08-08), where we plugged that leak.\n\nNow that we free them, a new packfile may be allocated using the exact\nsame address as a previously allocated one. And if the new packfile has\nboth the same address and a similar layout, it may happen that a\npreexisting entry from a previously-allocated in the delta base cache\nwould have the exact same key.\n\nAll of this sounds very theoretical, but we can actually trigger this\nbug somewhat reliably! When doing a merge in a repository with lots of\nsubmodules that have similar-looking packfiles we end up opening and\nthen closing the object databases of each of the submodules in sequence.\nBecause of the above mentioned commit we would close and free each of\nthe packfiles part of the respective databases, but we wouldn\u0027t evict\ntheir delta base entries from the cache.\n\nWhen using glibc, one of the packfiles will eventually get the exact\nsame address, and that will then cause Git to read the wrong entry from\nthe cache. Git detects this and aborts with an error:\n\n    $ git merge branch-b\n    error: Could not read 584ef938be4a749bfa13f68d5ac5545bc029e529\n    error: could not parse commit 584ef938be4a749bfa13f68d5ac5545bc029e529\n    error: failed to merge submodule G (repository corrupt)\n\nNow in this case we\u0027re lucky that Git detects this error because we try\nto read a commit from a different submodule via an object database that\ndoesn\u0027t have it. But potentially, in an even more contrived scenario, we\nmight even silently yield wrong data from the cache.\n\nFix this bug by evicting cache entries that belong to a specific pack\nwhen closing it.\n\nNote that the added test reliably reproduces the above bug on my machine\nthat uses NixOS at c59305bab206 (cosmic-applets: add missing runtime\ndependency (#566040), 2026-10-01) with glibc 2.44-25. But as we rely on\nspecific allocation behaviour of glibc it is very likely that the test\nwill not work on other platforms.\n\nReported-by: Guillaume Chauvel \u003cguillaume.chauvel@gmail.com\u003e\nHelped-by: Philippe Blain \u003clevraiphilippeblain@gmail.com\u003e\nSigned-off-by: Patrick Steinhardt \u003cps@pks.im\u003e\nSigned-off-by: Junio C Hamano \u003cgitster@pobox.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "af1b837974e73c6b8bfafb9dd3c5fe239085408c",
      "old_mode": 33188,
      "old_path": "packfile.c",
      "new_id": "365c54c7dcbbcaea4f492a0696040d03b85450bf",
      "new_mode": 33188,
      "new_path": "packfile.c"
    },
    {
      "type": "modify",
      "old_id": "1546d5f773396af9274eb658c0c7c32856ec8285",
      "old_mode": 33261,
      "old_path": "t/t6437-submodule-merge.sh",
      "new_id": "0ee3684206f1b0166ae79803023d45a6b0056118",
      "new_mode": 33261,
      "new_path": "t/t6437-submodule-merge.sh"
    }
  ]
}
