)]}'
{
  "commit": "42ed0468663dd493c0a0e00edc83b668369157d6",
  "tree": "03e94fe988521035448251d69296e7dc79023528",
  "parents": [
    "c44beea485f0f2feaf460e2ac87fdd5608d63cf0"
  ],
  "author": {
    "name": "Jeff King",
    "email": "peff@peff.net",
    "time": "Tue Nov 11 17:36:47 2025 -0500"
  },
  "committer": {
    "name": "Junio C Hamano",
    "email": "gitster@pobox.com",
    "time": "Wed Nov 12 10:30:04 2025 -0800"
  },
  "message": "attr: avoid recursion when expanding attribute macros\n\nGiven a set of attribute macros like:\n\n   [attr]a1 a2\n   [attr]a2 a3\n   ...\n   [attr]a300000 -text\n   file a1\n\nexpanding the attributes for \"file\" requires expanding \"a1\" to \"a2\",\n\"a2\" to \"a3\", and so on until hitting a non-macro expansion (\"-text\", in\nthis case). We implement this via recursion: fill_one() calls\nmacroexpand_one(), which then recurses back to fill_one(). As a result,\nvery deep macro chains like the one above can run out of stack space and\ncause us to segfault.\n\nThe required stack space is fairly small; I needed on the order of\n200,000 entries to get a segfault on Linux. So it\u0027s unlikely anybody\nwould hit this accidentally, leaving only malicious inputs. There you\ncan easily construct a repo which will segfault on clone (we look at\nattributes during the checkout step, but you\u0027d see the same trying to do\nother operations, like diff in a bare repo). It\u0027s mostly harmless, since\nanybody constructing such a repo is only preventing victims from cloning\ntheir evil garbage, but it could be a nuisance for hosting sites.\n\nOne option to prevent this is to limit the depth of recursion we\u0027ll\nallow. This is conceptually easy to implement, but it raises other\nquestions: what should the limit be, and do we need a configuration knob\nfor it?\n\nThe recursion here is simple enough that we can avoid those questions by\njust converting it to iteration instead. Rather than iterate over the\nstates of a match_attr in fill_one(), we\u0027ll put them all in a queue, and\nthe expansion of each can add to the queue rather than recursing. Note\nthat this is a LIFO queue in order to keep the same depth-first order we\ndid with the recursive implementation. I\u0027ve avoided using the word\n\"stack\" in the code because the term is already heavily used to refer to\nthe stack of .gitattribute files that matches the tree structure of the\nrepository.\n\nThe test uses a limited stack size so we can trigger the problem with a\nmuch smaller input than the one shown above. The value here (3000) is\nenough to trigger the issue on my x86_64 Linux machine.\n\nReported-by: Ben Stav \u003cbenstav@miggo.io\u003e\nSigned-off-by: Jeff King \u003cpeff@peff.net\u003e\nSigned-off-by: Junio C Hamano \u003cgitster@pobox.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "d1daeb0b4d90a6a289e3582f455212cbf20123ac",
      "old_mode": 33188,
      "old_path": "attr.c",
      "new_id": "4999b7e09da930f7701e6fbd22306531c6f67ca8",
      "new_mode": 33188,
      "new_path": "attr.c"
    },
    {
      "type": "modify",
      "old_id": "3c98b622f25b760138ed8a938c104ea017d0f408",
      "old_mode": 33261,
      "old_path": "t/t0003-attributes.sh",
      "new_id": "582e207aa12eb1aac774941137400889ddffdb46",
      "new_mode": 33261,
      "new_path": "t/t0003-attributes.sh"
    }
  ]
}
