)]}'
{
  "commit": "44c7e1a7e08c0863c4156869364cb5751a23784e",
  "tree": "a0e8f23bd18a49bfe9a92421dc5de8bb6df20afd",
  "parents": [
    "a762c8c1e1e5b6352f027db80be4ca1c0077403d"
  ],
  "author": {
    "name": "Elijah Newren",
    "email": "newren@gmail.com",
    "time": "Sat Aug 15 17:37:56 2020 +0000"
  },
  "committer": {
    "name": "Junio C Hamano",
    "email": "gitster@pobox.com",
    "time": "Tue Aug 18 12:16:06 2020 -0700"
  },
  "message": "mem-pool: use more standard initialization and finalization\n\nA typical memory type, such as strbuf, hashmap, or string_list can be\nstored on the stack or embedded within another structure.  mem_pool\ncannot be, because of how mem_pool_init() and mem_pool_discard() are\nwritten.  mem_pool_init() does essentially the following (simplified\nfor purposes of explanation here):\n\n    void mem_pool_init(struct mem_pool **pool...)\n    {\n        *pool \u003d xcalloc(1, sizeof(*pool));\n\nIt seems weird to require that mem_pools can only be accessed through a\npointer.  It also seems slightly dangerous: unlike strbuf_release() or\nstrbuf_reset() or string_list_clear(), all of which put the data\nstructure into a state where it can be re-used after the call,\nmem_pool_discard(pool) will leave pool pointing at free\u0027d memory.\nread-cache (and split-index) are the only current users of mem_pools,\nand they haven\u0027t fallen into a use-after-free mistake here, but it seems\nlikely to be problematic for future users especially since several of\nthe current callers of mem_pool_init() will only call it when the\nmem_pool* is not already allocated (i.e. is NULL).\n\nThis type of mechanism also prevents finding synchronization\npoints where one can free existing memory and then resume more\noperations.  It would be natural at such points to run something like\n    mem_pool_discard(pool...);\nand, if necessary,\n    mem_pool_init(\u0026pool...);\nand then carry on continuing to use the pool.  However, this fails badly\nif several objects had a copy of the value of pool from before these\ncommands; in such a case, those objects won\u0027t get the updated value of\npool that mem_pool_init() overwrites pool with and they\u0027ll all instead\nbe reading and writing from free\u0027d memory.\n\nModify mem_pool_init()/mem_pool_discard() to behave more like\n   strbuf_init()/strbuf_release()\nor\n   string_list_init()/string_list_clear()\nIn particular: (1) make mem_pool_init() just take a mem_pool* and have\nit only worry about allocating struct mp_blocks, not the struct mem_pool\nitself, (2) make mem_pool_discard() free the memory that the pool was\nresponsible for, but leave it in a state where it can be used to\nallocate more memory afterward (without the need to call mem_pool_init()\nagain).\n\nSigned-off-by: Elijah Newren \u003cnewren@gmail.com\u003e\nSigned-off-by: Junio C Hamano \u003cgitster@pobox.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "020b51e0c5623585df4d9c2f14bb44db1c311f01",
      "old_mode": 33188,
      "old_path": "mem-pool.c",
      "new_id": "7659919ab2c6251de26b550983be3d50305f182c",
      "new_mode": 33188,
      "new_path": "mem-pool.c"
    },
    {
      "type": "modify",
      "old_id": "ca062c9070b9bb612182e39b00b1dfad9cbebf01",
      "old_mode": 33188,
      "old_path": "mem-pool.h",
      "new_id": "870161ab4445b53fcf72dbc51c8ea78645ea05c2",
      "new_mode": 33188,
      "new_path": "mem-pool.h"
    },
    {
      "type": "modify",
      "old_id": "8ed1c29b541121214ab50b21a2f262edc406c807",
      "old_mode": 33188,
      "old_path": "read-cache.c",
      "new_id": "fa291cdbee0bb435122194c3e0fa8efdb750c47e",
      "new_mode": 33188,
      "new_path": "read-cache.c"
    },
    {
      "type": "modify",
      "old_id": "e6154e4ea9552cfc2b868453f017ba786cd24a2f",
      "old_mode": 33188,
      "old_path": "split-index.c",
      "new_id": "c0e8ad670d0a17a28fd049b6814d8e77c7654dc2",
      "new_mode": 33188,
      "new_path": "split-index.c"
    }
  ]
}
