git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v2 10/10] tag: don't misreport type of tagged objects in errors

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Mar 31, 2021, 20:46 UTC
Message-ID
<87eefvkq5d.fsf@evledraar.gmail.com>
In-Reply-To
<YGTGgFI19fS7Uv6I@coredump.intra.peff.net>
On Wed, Mar 31 2021, Jeff King wrote:
Show 72 quoted lines
> On Wed, Mar 31, 2021 at 08:31:16PM +0200, Ævar Arnfjörð Bjarmason wrote:
>
>> > Ævar's patch tries to improve the case where we might _know_ which is
>> > correct (because we're actually parsing the object contents), but of
>> > course it covers only a fraction of cases. I'm not really opposed to
>> > that per se, but I probably wouldn't bother myself.
>> 
>> What fraction of cases? As far as I can tell it covers all cases where
>> we get this error.
>> 
>> If there is a case like what you're describing I haven't found it.
>
> It would happen any time somebody calls lookup_foo() because they saw an
> object referenced, but _doesn't_ parse it. And then somebody later calls
> lookup_bar() in the same way. Neither of them consulted the actual
> object database.
>
> Try this with your patches:
>
> -- >8 --
> git init repo
> cd repo
>
> # just for making things deterministic
> export GIT_COMMITTER_NAME='A U Thor'
> export GIT_COMMITTER_EMAIL='author@example.com'
> export GIT_COMMITTER_DATE='@1234567890 +0000'
>
> blob=$(echo foo | git hash-object -w --stdin)
> git tag -m 'tag of blob' tag-of-blob $blob
> git update-ref refs/tags/tag-of-commit $(
>   git cat-file tag tag-of-blob |
>   sed s/blob/commit/g |
>   git hash-object -w --stdin -t tag
> )
> git update-ref refs/tags/tag-of-tree $(
>   git cat-file tag tag-of-blob |
>   sed s/blob/tree/g |
>   git hash-object -w --stdin -t tag
> )
>
> git fsck
> -- >8 --
>
> That fsck produces (257cc5642 is the blob):
>
>   error: object 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 is a blob, not a commit
>   error: 257cc5642cb1a054f08cc83f2d943e56fd3ebe99: object could not be parsed: .git/objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99
>   error: object 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 is a commit, not a tree
>   error: bad tag pointer to 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 in aaff0d42df150e1a734f6a8516878b2ea315ee0a
>   error: aaff0d42df150e1a734f6a8516878b2ea315ee0a: object could not be parsed: .git/objects/aa/ff0d42df150e1a734f6a8516878b2ea315ee0a
>   error: object 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 is a commit, not a blob
>   error: bad tag pointer to 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 in bbd2b7077cd91ee6175cdc0e4c477c25c230cdc7
>   error: bbd2b7077cd91ee6175cdc0e4c477c25c230cdc7: object could not be parsed: .git/objects/bb/d2b7077cd91ee6175cdc0e4c477c25c230cdc7
>
> So we claim "is X, not Y" in multiple directions for the same object.
>
> It might just be that there are spots in the fsck code that need to be
> adjusted to use your new function (if they are indeed parsing the
> referred-to object). But there are lots of places that don't actually
> parse the object at the moment they're parsing the tag. E.g.:
>
>   $ git for-each-ref --format='%(*objectname)'
>   error: object 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 is a commit, not a tree
>   error: bad tag pointer to 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 in aaff0d42df150e1a734f6a8516878b2ea315ee0a
>   Segmentation fault
>
> Neither of those types is the correct one. And the segfault is just a
> bonus! :)
>
> I'd expect similar cases with parsing commit parents and tree pointers.
> And probably tree entries whose modes are wrong.

So the segfault happens without my patches, but the change is that before we'd always get it wrong and say "commit, not a tree", but now we'll get it right some of the time. Patching the relevant object.c code to emit different messages from the various functions shows that it's the oid_is_type*() functions that get it right, but object_as_type() is wrong as before.

So that's certainly something I missed.

But are there any cases where it makes things worse? Or is it just that it's not a full fix in all cases, but only a partial one?

Show 19 quoted lines
>> I.e. it happens when we have an un-parsed "struct object" whose type is
>> inferred, and parse it to find out it's not what we expected.
>> 
>> It's not ambigious at all what the object actually is. It's just that
>> the previous code was leaking the *assumption* about the type at the
>> time of emitting the error, due to an apparent oversight with parsed
>> v.s. non-parsed.
>> 
>> Or in other words, we're leaking the implementation detail that we
>> pre-allocated an object struct of a given type in anticipation of
>> holding a parsed version of that object soon.
>
> Right. In the case that you are indeed parsing the object later, you can
> say definitively "it is X in the odb, but seen as Y previously". But we
> do not always hit the "is X, not Y" error when parsing the object. It
> might be caused by two of these "pre-allocations" (though really I think
> it is not just an implementation detail; the pre-allocation happened
> because some other object referred to us as a given type, so it really
> is a corruption in the repository. Just not in the object we mention).

Indeed, the goal is to emit a sensible message on-the-fly when we see that corruption.

Show 48 quoted lines
>> > @@ -169,10 +169,16 @@ void *object_as_type(struct object *obj, enum object_type type, int quiet)
>> >  		return obj;
>> >  	}
>> >  	else {
>> > -		if (!quiet)
>> > -			error(_("object %s is a %s, not a %s"),
>> > -			      oid_to_hex(&obj->oid),
>> > -			      type_name(obj->type), type_name(type));
>> > +		if (!(flags & OBJECT_AS_TYPE_QUIET)) {
>> > +			if (flags & OBJECT_AS_TYPE_EXPECT_PARSED)
>> > +				error(_("object %s is a %s, but was referred to as a %s"),
>> > +				      oid_to_hex(&obj->oid), type_name(obj->type),
>> > +				      type_name(type));
>> > +			else
>> > +				error(_("object %s referred to as both a %s and a %s"),
>> > +				      oid_to_hex(&obj->oid),
>> > +				      type_name(obj->type), type_name(type));
>> > +		}
>> >  		return NULL;
>> >  	}
>> >  }
>> 
>> Per the above I don't understand how you think there's any uncertainty
>> here.
>> 
>> If I'm right and there isn't then first of all I don't see how we could
>> emit 1/2 of those errors. The whole problem here is that we don't know
>> the type of the un-parsed object (and presumably don't want to eagerly
>> know, it would mean hitting the object store).
>
> Forgetting for a moment how to trigger it with actual Git commands, the
> root of the problem is that:
>
>   lookup_tree(&oid);
>   lookup_blob(&oid);
>
> is going to produce an error message. But we cannot know which object
> type is wrong and which is right (if any). So we'd want to produce the
> "referred to as both" message.
>
> _If_ the caller happens to know that it has just parsed the object
> contents and got a tree, then it would call lookup_parsed_tree(&oid),
> which would pass along OBJECT_AS_TYPE_EXPECT_PARSED, and produce the
> other message.
>
> In practice, of course those two lookup_foo() calls are not right next
> to each other. But they may be triggered on an identical oid by two
> references from different objects.
[...]
Show 9 quoted lines
>> But when we do know why would we beat around the bush and say "was
>> referred to as X and Y" once we know what it is. 
>> 
>> AFAICT there's no more reason to think that parse_object_buffer() will
>> be wrong about the type than "git cat-file -t" will be. They both use
>> the same underlying functions to get that information.
>
> My point is that we are not always coming from parse_object_buffer()
> when we see these error messages.

If my solution of relying on the parsed v.s. non-parsed shouldn't we just devolve to a full object info lookup when emitting the error? It's more expensive, but we're emitting an error anyway...

Previous: Jeff KingNext: Jeff King
Message 26 of 142 in “Pull objects of various types”
  1. 0/2 Pull objects of various typesDaniel Barkalow, Jun 22, 2005
  2. 1/2 Parse tags for absent objectsDaniel Barkalow, Jun 22, 2005
  3. 2/7 object.c: make type_from_string() return "enum object_type"Ævar Arnfjörð Bjarmason, Mar 8, 2021
  4. Taylor BlauMar 8, 2021
  5. Junio C HamanoMar 8, 2021
  6. 0/7 improve reporting of unexpected objectsÆvar Arnfjörð Bjarmason, Mar 8, 2021
  7. 00/10 improve reporting of unexpected objectsÆvar Arnfjörð Bjarmason, Mar 28, 2021
  8. 03/10 object.c: make type_from_string() return "enum object_type"Ævar Arnfjörð Bjarmason, Mar 28, 2021
  9. 01/10 object.c: stop supporting len == -1 in type_from_string_gently()Ævar Arnfjörð Bjarmason, Mar 28, 2021
  10. Junio C HamanoMar 28, 2021
  11. Ævar Arnfjörð BjarmasonMar 28, 2021
  12. Junio C HamanoMar 28, 2021
  13. Felipe ContrerasApr 22, 2021
  14. 04/10 object-file.c: make oid_object_info() return "enum object_type"Ævar Arnfjörð Bjarmason, Mar 28, 2021
  15. 06/10 tree.c: fix misindentation in parse_tree_gently()Ævar Arnfjörð Bjarmason, Mar 28, 2021
  16. 05/10 object-name.c: make dependency on object_type order more obviousÆvar Arnfjörð Bjarmason, Mar 28, 2021
  17. 07/10 object.c: add a utility function for "expected type X, got Y"Ævar Arnfjörð Bjarmason, Mar 28, 2021
  18. 02/10 object.c: refactor type_from_string_gently()Ævar Arnfjörð Bjarmason, Mar 28, 2021
  19. 08/10 object.c: add and use oid_is_type_or_die_msg() functionÆvar Arnfjörð Bjarmason, Mar 28, 2021
  20. 10/10 tag: don't misreport type of tagged objects in errorsÆvar Arnfjörð Bjarmason, Mar 28, 2021
  21. Junio C HamanoMar 30, 2021
  22. Jeff KingMar 31, 2021
  23. Junio C HamanoMar 31, 2021
  24. Ævar Arnfjörð BjarmasonMar 31, 2021
  25. Jeff KingMar 31, 2021
  26. Ævar Arnfjörð BjarmasonMar 31, 2021
  27. Jeff KingApr 1, 2021
  28. ref-filter: fix NULL check for parse object failureJeff King, Apr 1, 2021
  29. 0/5 mktag tests & fix for-each-ref segfaultÆvar Arnfjörð Bjarmason, Apr 1, 2021
  30. 5/5 ref-filter: fix NULL check for parse object failureÆvar Arnfjörð Bjarmason, Apr 1, 2021
  31. Ramsay JonesApr 1, 2021
  32. 4/5 mktag tests: test for maybe segfaulting for-each-refÆvar Arnfjörð Bjarmason, Apr 1, 2021
  33. 2/5 mktag tests: invert --no-strict testÆvar Arnfjörð Bjarmason, Apr 1, 2021
  34. 1/5 mktag tests: parse out options in helperÆvar Arnfjörð Bjarmason, Apr 1, 2021
  35. 3/5 mktag tests: do fsck on failureÆvar Arnfjörð Bjarmason, Apr 1, 2021
  36. Junio C HamanoApr 1, 2021
  37. Ævar Arnfjörð BjarmasonApr 2, 2021
  38. Junio C HamanoApr 2, 2021
  39. Junio C HamanoApr 1, 2021
  40. Junio C HamanoMar 31, 2021
  41. Jeff KingMar 31, 2021
  42. 09/10 object tests: add test for unexpected objects in tagsÆvar Arnfjörð Bjarmason, Mar 28, 2021
  43. Jeff KingMar 28, 2021
  44. Ævar Arnfjörð BjarmasonMar 29, 2021
  45. Jeff KingMar 31, 2021
  46. 0/2 blob/object.c: trivial readability improvementsÆvar Arnfjörð Bjarmason, Apr 9, 2021
  47. 1/2 blob.c: remove buffer & size arguments to parse_blob_buffer()Ævar Arnfjörð Bjarmason, Apr 9, 2021
  48. Jeff KingApr 9, 2021
  49. Junio C HamanoApr 9, 2021
  50. Ævar Arnfjörð BjarmasonApr 10, 2021
  51. Ævar Arnfjörð BjarmasonApr 10, 2021
  52. Jeff KingApr 13, 2021
  53. 2/2 object.c: initialize automatic variable in lookup_object()Ævar Arnfjörð Bjarmason, Apr 9, 2021
  54. Jeff KingApr 9, 2021
  55. Junio C HamanoApr 9, 2021
  56. 0/6 {tag,object}*.c: refactorings + prep for a larger changeÆvar Arnfjörð Bjarmason, Apr 9, 2021
  57. 1/6 object.c: stop supporting len == -1 in type_from_string_gently()Ævar Arnfjörð Bjarmason, Apr 9, 2021
  58. Jeff KingApr 9, 2021
  59. Jeff KingApr 9, 2021
  60. 3/6 object.c: make type_from_string() return "enum object_type"Ævar Arnfjörð Bjarmason, Apr 9, 2021
  61. Jeff KingApr 9, 2021
  62. Ævar Arnfjörð BjarmasonApr 9, 2021
  63. Jeff KingApr 9, 2021
  64. 2/6 object.c: remove "gently" argument to type_from_string_gently()Ævar Arnfjörð Bjarmason, Apr 9, 2021
  65. Jeff KingApr 9, 2021
  66. 4/6 object-file.c: make oid_object_info() return "enum object_type"Ævar Arnfjörð Bjarmason, Apr 9, 2021
  67. Jeff KingApr 9, 2021
  68. 6/6 tag.c: use type_from_string_gently() when parsing tagsÆvar Arnfjörð Bjarmason, Apr 9, 2021
  69. Jeff KingApr 9, 2021
  70. 5/6 object-name.c: make dependency on object_type order more obviousÆvar Arnfjörð Bjarmason, Apr 9, 2021
  71. Jeff KingApr 9, 2021
  72. 0/7 object.c: add and use "is expected" utility function + object_as_type() useÆvar Arnfjörð Bjarmason, Apr 9, 2021
  73. 2/7 object.c: add a utility function for "expected type X, got Y"Ævar Arnfjörð Bjarmason, Apr 9, 2021
  74. 1/7 tree.c: fix misindentation in parse_tree_gently()Ævar Arnfjörð Bjarmason, Apr 9, 2021
  75. 3/7 object.c: add and use oid_is_type_or_die_msg() functionÆvar Arnfjörð Bjarmason, Apr 9, 2021
  76. 4/7 commit-graph: use obj->type, not object_as_type()Ævar Arnfjörð Bjarmason, Apr 9, 2021
  77. 5/7 commit.c: don't use deref_tag() -> object_as_type()Ævar Arnfjörð Bjarmason, Apr 9, 2021
  78. 6/7 object.c: normalize brace style in object_as_type()Ævar Arnfjörð Bjarmason, Apr 9, 2021
  79. 7/7 object.c: remove "quiet" parameter from object_as_type()Ævar Arnfjörð Bjarmason, Apr 9, 2021
  80. 0/8 object.c: add and use "is expected" utility function + object_as_type() useÆvar Arnfjörð Bjarmason, Apr 20, 2021
  81. 1/8 tree.c: fix misindentation in parse_tree_gently()Ævar Arnfjörð Bjarmason, Apr 20, 2021
  82. 2/8 object.c: add a utility function for "expected type X, got Y"Ævar Arnfjörð Bjarmason, Apr 20, 2021
  83. Jonathan TanApr 21, 2021
  84. Ævar Arnfjörð BjarmasonApr 22, 2021
  85. 3/8 object.c: add and use oid_is_type_or_die_msg() functionÆvar Arnfjörð Bjarmason, Apr 20, 2021
  86. Jonathan TanApr 21, 2021
  87. Josh SteadmonApr 21, 2021
  88. Junio C HamanoApr 28, 2021
  89. 4/8 commit-graph: use obj->type, not object_as_type()Ævar Arnfjörð Bjarmason, Apr 20, 2021
  90. 5/8 branch tests: assert lookup_commit_reference_gently() errorÆvar Arnfjörð Bjarmason, Apr 20, 2021
  91. 6/8 commit.c: don't use deref_tag() -> object_as_type()Ævar Arnfjörð Bjarmason, Apr 20, 2021
  92. Jonathan TanApr 21, 2021
  93. 7/8 object.c: normalize brace style in object_as_type()Ævar Arnfjörð Bjarmason, Apr 20, 2021
  94. 8/8 object.c: remove "quiet" parameter from object_as_type()Ævar Arnfjörð Bjarmason, Apr 20, 2021
  95. 00/10 {tag,object}*.c: refactorings + prep for a larger changeÆvar Arnfjörð Bjarmason, Apr 20, 2021
  96. 01/10 object.c: stop supporting len == -1 in type_from_string_gently()Ævar Arnfjörð Bjarmason, Apr 20, 2021
  97. 02/10 object.c: remove "gently" argument to type_from_string_gently()Ævar Arnfjörð Bjarmason, Apr 20, 2021
  98. 03/10 object.c: make type_from_string() return "enum object_type"Ævar Arnfjörð Bjarmason, Apr 20, 2021
  99. 04/10 object-file.c: make oid_object_info() return "enum object_type"Ævar Arnfjörð Bjarmason, Apr 20, 2021
  100. 05/10 object-name.c: make dependency on object_type order more obviousÆvar Arnfjörð Bjarmason, Apr 20, 2021
  101. 06/10 tag.c: use type_from_string_gently() when parsing tagsÆvar Arnfjörð Bjarmason, Apr 20, 2021
  102. 07/10 hash-object: pass along type length to object.cÆvar Arnfjörð Bjarmason, Apr 20, 2021
  103. 09/10 hash-object: show usage on invalid --typeÆvar Arnfjörð Bjarmason, Apr 20, 2021
  104. 08/10 hash-object: refactor nested else/if/if into else if/else ifÆvar Arnfjörð Bjarmason, Apr 20, 2021
  105. 10/10 object.c: move type_from_string() code to its last userÆvar Arnfjörð Bjarmason, Apr 20, 2021
  106. 00/10 object.c et al: tests, small bug fixes etc.Ævar Arnfjörð Bjarmason, Apr 20, 2021
  107. 01/10 cat-file tests: test for bogus type name handlingÆvar Arnfjörð Bjarmason, Apr 20, 2021
  108. Junio C HamanoApr 29, 2021
  109. 03/10 mktree tests: add test for invalid object typeÆvar Arnfjörð Bjarmason, Apr 20, 2021
  110. 04/10 object-file.c: take type id, not string, in read_object_with_reference()Ævar Arnfjörð Bjarmason, Apr 20, 2021
  111. Junio C HamanoApr 29, 2021
  112. 05/10 {commit,tree,blob,tag}.c: add a create_{commit,tree,blob,tag}()Ævar Arnfjörð Bjarmason, Apr 20, 2021
  113. Junio C HamanoApr 29, 2021
  114. Ævar Arnfjörð BjarmasonApr 29, 2021
  115. 02/10 hash-object tests: more detailed test for invalid typeÆvar Arnfjörð Bjarmason, Apr 20, 2021
  116. 06/10 blob.c: remove parse_blob_buffer()Ævar Arnfjörð Bjarmason, Apr 20, 2021
  117. Junio C HamanoApr 29, 2021
  118. 08/10 object.c: don't go past "len" under die() in type_from_string_gently()Ævar Arnfjörð Bjarmason, Apr 20, 2021
  119. Junio C HamanoApr 29, 2021
  120. 07/10 object.c: simplify return semantic of parse_object_buffer()Ævar Arnfjörð Bjarmason, Apr 20, 2021
  121. 09/10 mktree: stop setting *ntr++ to NILÆvar Arnfjörð Bjarmason, Apr 20, 2021
  122. Junio C HamanoApr 29, 2021
  123. 10/10 mktree: emit a more detailed error when the <type> is invalidÆvar Arnfjörð Bjarmason, Apr 20, 2021
  124. 3/7 oid_object_info(): return "enum object_type"Ævar Arnfjörð Bjarmason, Mar 8, 2021
  125. Junio C HamanoMar 8, 2021
  126. Junio C HamanoMar 8, 2021
  127. Jeff KingMar 9, 2021
  128. 4/7 tree.c: fix misindentation in parse_tree_gently()Ævar Arnfjörð Bjarmason, Mar 8, 2021
  129. 5/7 object.c: add a utility function for "expected type X, got Y"Ævar Arnfjörð Bjarmason, Mar 8, 2021
  130. Taylor BlauMar 8, 2021
  131. Junio C HamanoMar 8, 2021
  132. 1/7 object.c: refactor type_from_string_gently()Ævar Arnfjörð Bjarmason, Mar 8, 2021
  133. Taylor BlauMar 8, 2021
  134. Jeff KingMar 9, 2021
  135. 6/7 object tests: add test for unexpected objects in tagsÆvar Arnfjörð Bjarmason, Mar 8, 2021
  136. Jeff KingMar 9, 2021
  137. Ævar Arnfjörð BjarmasonMar 28, 2021
  138. Jeff KingMar 28, 2021
  139. Ævar Arnfjörð BjarmasonMar 28, 2021
  140. Jeff KingMar 29, 2021
  141. 7/7 tag: don't misreport type of tagged objects in errorsÆvar Arnfjörð Bjarmason, Mar 8, 2021
  142. 2/2 Pull misc objectsDaniel Barkalow, Jun 22, 2005

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.