)]}'
{
  "commit": "cf73936ddf4ba56b34ea03cce1657efa5fa3decc",
  "tree": "ef38995d1d12bfe5b2ee1190aeefa5e61d257a1c",
  "parents": [
    "1343c893138e63e35b38324387ea790aba77a49f"
  ],
  "author": {
    "name": "Taylor Blau",
    "email": "me@ttaylorr.com",
    "time": "Tue Jun 25 13:39:16 2024 -0400"
  },
  "committer": {
    "name": "Junio C Hamano",
    "email": "gitster@pobox.com",
    "time": "Tue Jun 25 13:52:05 2024 -0700"
  },
  "message": "commit-graph: ensure Bloom filters are read with consistent settings\n\nThe changed-path Bloom filter mechanism is parameterized by a couple of\nvariables, notably the number of bits per hash (typically \"m\" in Bloom\nfilter literature) and the number of hashes themselves (typically \"k\").\n\nIt is critically important that filters are read with the Bloom filter\nsettings that they were written with. Failing to do so would mean that\neach query is liable to compute different fingerprints, meaning that the\nfilter itself could return a false negative. This goes against a basic\nassumption of using Bloom filters (that they may return false positives,\nbut never false negatives) and can lead to incorrect results.\n\nWe have some existing logic to carry forward existing Bloom filter\nsettings from one layer to the next. In `write_commit_graph()`, we have\nsomething like:\n\n    if (!(flags \u0026 COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS)) {\n        struct commit_graph *g \u003d ctx-\u003er-\u003eobjects-\u003ecommit_graph;\n\n        /* We have changed-paths already. Keep them in the next graph */\n        if (g \u0026\u0026 g-\u003echunk_bloom_data) {\n            ctx-\u003echanged_paths \u003d 1;\n            ctx-\u003ebloom_settings \u003d g-\u003ebloom_filter_settings;\n        }\n    }\n\n, which drags forward Bloom filter settings across adjacent layers.\n\nThis doesn\u0027t quite address all cases, however, since it is possible for\nintermediate layers to contain no Bloom filters at all. For example,\nsuppose we have two layers in a commit-graph chain, say, {G1, G2}. If G1\ncontains Bloom filters, but G2 doesn\u0027t, a new G3 (whose base graph is\nG2) may be written with arbitrary Bloom filter settings, because we only\ncheck the immediately adjacent layer\u0027s settings for compatibility.\n\nThis behavior has existed since the introduction of changed-path Bloom\nfilters. But in practice, this is not such a big deal, since the only\nway up until this point to modify the Bloom filter settings at write\ntime is with the undocumented environment variables:\n\n  - GIT_TEST_BLOOM_SETTINGS_BITS_PER_ENTRY\n  - GIT_TEST_BLOOM_SETTINGS_NUM_HASHES\n  - GIT_TEST_BLOOM_SETTINGS_MAX_CHANGED_PATHS\n\n(it is still possible to tweak MAX_CHANGED_PATHS between layers, but\nthis does not affect reads, so is allowed to differ across multiple\ngraph layers).\n\nBut in future commits, we will introduce another parameter to change the\nhash algorithm used to compute Bloom fingerprints itself. This will be\nexposed via a configuration setting, making this foot-gun easier to use.\n\nTo prevent this potential issue, validate that all layers of a split\ncommit-graph have compatible settings with the newest layer which\ncontains Bloom filters.\n\nReported-by: SZEDER Gábor \u003cszeder.dev@gmail.com\u003e\nOriginal-test-by: SZEDER Gábor \u003cszeder.dev@gmail.com\u003e\nSigned-off-by: Taylor Blau \u003cme@ttaylorr.com\u003e\nSigned-off-by: Junio C Hamano \u003cgitster@pobox.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "bba316913cc9c270e061092000c605014dc97904",
      "old_mode": 33188,
      "old_path": "commit-graph.c",
      "new_id": "00113b0f62b83daddbdd0ee632966ee4bc1b342e",
      "new_mode": 33188,
      "new_path": "commit-graph.c"
    },
    {
      "type": "modify",
      "old_id": "cc6ebc8140e2e0b91126dff1704f582b7d7ee465",
      "old_mode": 33261,
      "old_path": "t/t4216-log-bloom.sh",
      "new_id": "c1977961d01c5a26cc26a9414cef38fb7d461a8a",
      "new_mode": 33261,
      "new_path": "t/t4216-log-bloom.sh"
    }
  ]
}
