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

Re: [PATCH 3/6] hash.h: introduce `unsafe_hash_algo()`

From
brian m. carlson <sandals@crustytoothpaste.net>
Date
Nov 22, 2024, 00:39 UTC
Message-ID
<Zz_SwuEw-KYM9xJl@tapette.crustytoothpaste.net>
In-Reply-To
<20241121093731.GD602681@coredump.intra.peff.net>
On 2024-11-21 at 09:37:31, Jeff King wrote:
Show 54 quoted lines
> On Wed, Nov 20, 2024 at 02:13:50PM -0500, Taylor Blau wrote:
> 
> > +static const struct git_hash_algo sha1_unsafe_algo = {
> > +	.name = "sha1",
> > +	.format_id = GIT_SHA1_FORMAT_ID,
> > +	.rawsz = GIT_SHA1_RAWSZ,
> > +	.hexsz = GIT_SHA1_HEXSZ,
> > +	.blksz = GIT_SHA1_BLKSZ,
> > +	.init_fn = git_hash_sha1_init_unsafe,
> > +	.clone_fn = git_hash_sha1_clone_unsafe,
> > +	.update_fn = git_hash_sha1_update_unsafe,
> > +	.final_fn = git_hash_sha1_final_unsafe,
> > +	.final_oid_fn = git_hash_sha1_final_oid_unsafe,
> > +	.empty_tree = &empty_tree_oid,
> > +	.empty_blob = &empty_blob_oid,
> > +	.null_oid = &null_oid_sha1,
> > +};
> 
> All of the non-function fields here naturally must match the ones in the
> parent algo struct, or chaos ensues. That's a little fragile, but it's
> not like we're adding new algorithm variants a lot. The biggest risk, I
> guess, would be adding a new field to git_hash_algo which defaults to
> zero-initialization here. But again, there are only three total and they
> are defined near each other here, so I don't think it's a big risk
> overall.
> 
> I think this struct is a potential landmine for hash_algo_by_ptr():
> 
>   static inline int hash_algo_by_ptr(const struct git_hash_algo *p)
>   {
>           return p - hash_algos;
>   }
> 
> It's undefined behavior to pass in sha1_unsafe_algo to this function
> (but the compiler would not complain since the types are the same). I
> don't find it incredibly likely that somebody would want to do that on
> an unsafe variant, but I'm not thrilled about leaving that wart for
> somebody to find.
> 
> If we don't care about the speed of this function, then an
> implementation like:
> 
>   for (i = 0; i < GIT_HASH_NALGOS; i++) {
> 	if (p == &hash_algos[i] || p == hash_algos[i]->unsafe)
> 		return i;
>   }
>   return GIT_HASH_UNKNOWN;
> 
> would work. I'm not sure if that would be measurable. I was surprised at
> the number of places that hash_algo_by_ptr() is called. Many low-level
> oid functions need it because we store the integer id there rather than
> a direct pointer (so oidread(), oidclr(), oid_object_info_extended(),
> and so on). But I'd also expect the loop above to be pretty fast. So I
> dunno.

Yeah, I'm also a little nervous about this change with hash_algo_by_ptr. I think we had discussed in the other thread about doing something like this:

struct git_hash_algo_fns {
	/* The hash initialization function. */
	git_hash_init_fn init_fn;
	/* The hash context cloning function. */
	git_hash_clone_fn clone_fn;
	/* The hash update function. */
	git_hash_update_fn update_fn;
	/* The hash finalization function. */
	git_hash_final_fn final_fn;
	/* The hash finalization function for object IDs. */
	git_hash_final_oid_fn final_oid_fn;
};
and then doing this:
struct git_hash_algo {
	[...]
  struct git_hash_algo_fns fns;
  struct git_hash_algo_fns unsafe_fns;
  [...]
};

That would mean that we'd have to deal with two pointers in your first patch, but I don't really think that's too terrible. And, since this approach doesn't result in an extra struct git_hash_algo, it's impossible to misuse hash_algo_by_ptr.

I'm not a hard no on the current approach, but I think the above would probably be a little safer and harder to misuse. It would require extra patches to convert existing callers, though, but they aren't hugely numerous, and the conversion could probably be mostly automated.

-- 
brian m. carlson (they/them or he/him)
Toronto, Ontario, CA
Previous: Jeff KingNext: Jeff King
Message 7 of 60 in “hash: introduce unsafe_hash_algo(), drop unsafe_ variants”
  1. 0/6 hash: introduce unsafe_hash_algo(), drop unsafe_ variantsTaylor Blau, Nov 20, 2024
  2. 1/6 csum-file: store the hash algorithm as a struct fieldTaylor Blau, Nov 20, 2024
  3. Jeff KingNov 21, 2024
  4. 2/6 csum-file.c: extract algop from hashfile_checksum_valid()Taylor Blau, Nov 20, 2024
  5. 3/6 hash.h: introduce `unsafe_hash_algo()`Taylor Blau, Nov 20, 2024
  6. Jeff KingNov 21, 2024
  7. brian m. carlsonNov 22, 2024
  8. Jeff KingNov 22, 2024
  9. brian m. carlsonNov 22, 2024
  10. Taylor BlauJan 10, 2025
  11. Jeff KingJan 11, 2025
  12. 4/6 csum-file.c: use unsafe_hash_algo()Taylor Blau, Nov 20, 2024
  13. 5/6 t/helper/test-hash.c: use unsafe_hash_algo()Taylor Blau, Nov 20, 2024
  14. 6/6 hash.h: drop unsafe_ function variantsTaylor Blau, Nov 20, 2024
  15. Jeff KingNov 21, 2024
  16. 0/8 hash: introduce unsafe_hash_algo(), drop unsafe_ variantsTaylor Blau, Jan 8, 2025
  17. 1/8 t/helper/test-tool: implement sha1-unsafe helperTaylor Blau, Jan 8, 2025
  18. 2/8 csum-file: store the hash algorithm as a struct fieldTaylor Blau, Jan 8, 2025
  19. Patrick SteinhardtJan 16, 2025
  20. Taylor BlauJan 17, 2025
  21. 3/8 csum-file.c: extract algop from hashfile_checksum_valid()Taylor Blau, Jan 8, 2025
  22. 4/8 hash.h: introduce `unsafe_hash_algo()`Taylor Blau, Jan 8, 2025
  23. Patrick SteinhardtJan 16, 2025
  24. Taylor BlauJan 17, 2025
  25. 5/8 csum-file.c: use unsafe_hash_algo()Taylor Blau, Jan 8, 2025
  26. 6/8 t/helper/test-hash.c: use unsafe_hash_algo()Taylor Blau, Jan 8, 2025
  27. 7/8 csum-file: introduce hashfile_checkpoint_init()Taylor Blau, Jan 8, 2025
  28. Jeff KingJan 10, 2025
  29. Taylor BlauJan 10, 2025
  30. Taylor BlauJan 17, 2025
  31. Jeff KingJan 18, 2025
  32. 8/8 hash.h: drop unsafe_ function variantsTaylor Blau, Jan 8, 2025
  33. Jeff KingJan 10, 2025
  34. Taylor BlauJan 10, 2025
  35. Jeff KingJan 11, 2025
  36. Junio C HamanoJan 11, 2025
  37. Taylor BlauJan 11, 2025
  38. 0/8 hash: introduce unsafe_hash_algo(), drop unsafe_ variantsTaylor Blau, Jan 17, 2025
  39. 1/8 t/helper/test-tool: implement sha1-unsafe helperTaylor Blau, Jan 17, 2025
  40. 2/8 csum-file: store the hash algorithm as a struct fieldTaylor Blau, Jan 17, 2025
  41. 3/8 csum-file.c: extract algop from hashfile_checksum_valid()Taylor Blau, Jan 17, 2025
  42. 4/8 hash.h: introduce `unsafe_hash_algo()`Taylor Blau, Jan 17, 2025
  43. 5/8 csum-file.c: use unsafe_hash_algo()Taylor Blau, Jan 17, 2025
  44. 6/8 t/helper/test-hash.c: use unsafe_hash_algo()Taylor Blau, Jan 17, 2025
  45. 7/8 csum-file: introduce hashfile_checkpoint_init()Taylor Blau, Jan 17, 2025
  46. 8/8 hash.h: drop unsafe_ function variantsTaylor Blau, Jan 17, 2025
  47. Jeff KingJan 18, 2025
  48. Jeff KingJan 18, 2025
  49. Junio C HamanoJan 22, 2025
  50. 0/8 hash: introduce unsafe_hash_algo(), drop unsafe_ variantsTaylor Blau, Jan 23, 2025
  51. 1/8 t/helper/test-tool: implement sha1-unsafe helperTaylor Blau, Jan 23, 2025
  52. 2/8 csum-file: store the hash algorithm as a struct fieldTaylor Blau, Jan 23, 2025
  53. 3/8 csum-file.c: extract algop from hashfile_checksum_valid()Taylor Blau, Jan 23, 2025
  54. 4/8 hash.h: introduce `unsafe_hash_algo()`Taylor Blau, Jan 23, 2025
  55. 5/8 csum-file.c: use unsafe_hash_algo()Taylor Blau, Jan 23, 2025
  56. 6/8 t/helper/test-hash.c: use unsafe_hash_algo()Taylor Blau, Jan 23, 2025
  57. 7/8 csum-file: introduce hashfile_checkpoint_init()Taylor Blau, Jan 23, 2025
  58. 8/8 hash.h: drop unsafe_ function variantsTaylor Blau, Jan 23, 2025
  59. Junio C HamanoJan 23, 2025
  60. Jeff KingJan 23, 2025

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.