)]}'
{
  "commit": "7ec85185b197ce1cd28721a6f4415fb9db5cd42f",
  "tree": "67e0b5b9b0fbd00025d78712868293d3f5bbe3c9",
  "parents": [
    "705114772e0a0741c3288329bd9ac4e11e38db9a"
  ],
  "author": {
    "name": "Patrick Steinhardt",
    "email": "ps@pks.im",
    "time": "Thu Oct 23 09:16:20 2025 +0200"
  },
  "committer": {
    "name": "Junio C Hamano",
    "email": "gitster@pobox.com",
    "time": "Tue Nov 04 07:32:25 2025 -0800"
  },
  "message": "object: add flag to `peel_object()` to verify object type\n\nWhen peeling a tag to a non-tag object we repeatedly call\n`parse_object()` on the tagged object until we find the first object\nthat isn\u0027t a tag. While this feels sensible at first, there is a big\ncatch here: `parse_object()` doesn\u0027t actually verify the type of the\ntagged object.\n\nThe relevant code path here eventually ends up in `parse_tag_buffer()`.\nHere, we parse the various fields of the tag, including the \"type\". Once\nwe\u0027ve figured out the type and the tagged object ID, we call one of the\n`lookup_${type}()` functions for whatever type we have found. There is\ntwo possible outcomes in the successful case:\n\n  1. The object is already part of our cached objects. In that case we\n     double-check whether the type we\u0027re trying to look up matches the\n     type that was cached.\n\n  2. The object is _not_ part of our cached objects. In that case, we\n     simply create a new object with the expected type, but we don\u0027t\n     parse that object.\n\nIn the first case we might notice type mismatches, but only in the case\nwhere our cache has the object with the correct type. In the second\ncase, we\u0027ll blindly assume that the type is correct and then go with it.\nWe\u0027ll only notice that the type might be wrong when we try to parse the\nobject at a later point.\n\nNow arguably, we could change `parse_tag_buffer()` to verify the tagged\nobject\u0027s type for us. But that would have the effect that such a tag\ncannot be parsed at all anymore, and we have a small bunch of tests for\nexactly this case that assert we still can open such tags. So this\nchange does not feel like something we can retroactively tighten, even\nthough one shouldn\u0027t ever hit such corrupted tags.\n\nInstead, add a new `flags` field to `peel_object()` that allows the\ncaller to opt in to strict object verification. This will be wired up at\na subset of callsites over the next few commits.\n\nNote that this change also inlines `deref_tag_noverify()`. There\u0027s only\nbeen two callsites of that function, the one we\u0027re changing and one in\nour test helpers. The latter callsite can trivially use `deref_tag()`\ninstead, so by inlining the function we avoid having to pass down the\nflag.\n\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": "986114a6dba843ea412123dc9035bf67693a6afd",
      "old_mode": 33188,
      "old_path": "object.c",
      "new_id": "e72b0ed4360e67e40d661aca8beb7bc3887d84b0",
      "new_mode": 33188,
      "new_path": "object.c"
    },
    {
      "type": "modify",
      "old_id": "8c3c1c46e1bf04e8e51d7b72c88bc352077c54d0",
      "old_mode": 33188,
      "old_path": "object.h",
      "new_id": "1499f63d507c32c5c1c2b1d0244beb584439c7d4",
      "new_mode": 33188,
      "new_path": "object.h"
    },
    {
      "type": "modify",
      "old_id": "7fd8babec8f5bdf7d50da0f88d7989672b6309be",
      "old_mode": 33188,
      "old_path": "ref-filter.c",
      "new_id": "9a8ed8c8fc1f3b6bccb4ff8fe5a9123e43c1d9db",
      "new_mode": 33188,
      "new_path": "ref-filter.c"
    },
    {
      "type": "modify",
      "old_id": "9d8f0a9ca4a3a63114d4a76202952d9444c7176c",
      "old_mode": 33188,
      "old_path": "refs.c",
      "new_id": "a41a94ae55bb43444015949e0871aeed42001694",
      "new_mode": 33188,
      "new_path": "refs.c"
    },
    {
      "type": "modify",
      "old_id": "6fa229edd0ffad6b9777f65e1512a36d27a0e2c1",
      "old_mode": 33188,
      "old_path": "refs/packed-backend.c",
      "new_id": "4752d3f3981fe3de645e6bd6bce95e487639b481",
      "new_mode": 33188,
      "new_path": "refs/packed-backend.c"
    },
    {
      "type": "modify",
      "old_id": "e329d4a423abdb2ae49b47c57ad38cca5a52aa96",
      "old_mode": 33188,
      "old_path": "refs/reftable-backend.c",
      "new_id": "9febb2322c3b24ba024a85a8fda5ac5af7c24047",
      "new_mode": 33188,
      "new_path": "refs/reftable-backend.c"
    },
    {
      "type": "modify",
      "old_id": "028ec0030678284eba844e121c6eff88abdd3139",
      "old_mode": 33188,
      "old_path": "t/helper/test-reach.c",
      "new_id": "c58c93800f32320eb83ea192196776a9cc4223f1",
      "new_mode": 33188,
      "new_path": "t/helper/test-reach.c"
    },
    {
      "type": "modify",
      "old_id": "1d52686ee105f2ac168e9728716bc3f70c30cd57",
      "old_mode": 33188,
      "old_path": "tag.c",
      "new_id": "f5c232d2f1f36cecad575a612d5bb4bbf27ddffc",
      "new_mode": 33188,
      "new_path": "tag.c"
    },
    {
      "type": "modify",
      "old_id": "c49d7c19ad3c9087e8a115a7a0edcd0c14062520",
      "old_mode": 33188,
      "old_path": "tag.h",
      "new_id": "ef12a610372063aff01b78285a2b161a23675614",
      "new_mode": 33188,
      "new_path": "tag.h"
    }
  ]
}
