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

[PATCH 4/7] reftable: avoid writing empty keys at the block layer

From
Han-Wen Nienhuys via GitGitGadget <gitgitgadget@gmail.com>
Date
Jan 12, 2022, 18:07 UTC
Message-ID
<e4c1cc58265ca7ae7b32b9faf41324883011d1a6.1642010868.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.1185.git.git.1642010868.gitgitgadget@gmail.com>
From: Han-Wen Nienhuys <hanwen@google.com>

The public interface (reftable_writer) already ensures that keys are written in strictly increasing order, and an empty key by definition fails this check.

However, by also enforcing this at the block layer, it is easier to verify that records (which are written into blocks) never have to consider the possibility of empty keys.

Signed-off-by: Han-Wen Nienhuys <hanwen@google.com>
---
 reftable/block.c      | 27 +++++++++++++++++----------
 reftable/block_test.c |  5 +++++
 reftable/writer.c     |  3 +--
 3 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/reftable/block.c b/reftable/block.c
index 855e3f5c947..8725eaaf64f 100644
--- a/reftable/block.c
+++ b/reftable/block.c
@@ -88,8 +88,9 @@ uint8_t block_writer_type(struct block_writer *bw)
 	return bw->buf[bw->header_off];
 }
 
-/* adds the reftable_record to the block. Returns -1 if it does not fit, 0 on
-   success */
+/* Adds the reftable_record to the block. Returns -1 if it does not fit, 0 on
+   success. Returns REFTABLE_API_ERROR if attempting to write a record with
+   empty key. */
 int block_writer_add(struct block_writer *w, struct reftable_record *rec)
 {
 	struct strbuf empty = STRBUF_INIT;
@@ -105,8 +106,14 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)
 	int is_restart = 0;
 	struct strbuf key = STRBUF_INIT;
 	int n = 0;
+	int err = -1;
 
 	reftable_record_key(rec, &key);
+	if (!key.len) {
+		err = REFTABLE_API_ERROR;
+		goto done;
+	}
+
 	n = reftable_encode_key(&is_restart, out, last, key,
 				reftable_record_val_type(rec));
 	if (n < 0)
@@ -118,16 +125,11 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec)
 		goto done;
 	string_view_consume(&out, n);
 
-	if (block_writer_register_restart(w, start.len - out.len, is_restart,
-					  &key) < 0)
-		goto done;
-
-	strbuf_release(&key);
-	return 0;
-
+	err = block_writer_register_restart(w, start.len - out.len, is_restart,
+					    &key);
 done:
 	strbuf_release(&key);
-	return -1;
+	return err;
 }
 
 int block_writer_finish(struct block_writer *w)
@@ -324,6 +326,9 @@ int block_iter_next(struct block_iter *it, struct reftable_record *rec)
 	if (n < 0)
 		return -1;
 
+	if (!key.len)
+		return REFTABLE_FORMAT_ERROR;
+
 	string_view_consume(&in, n);
 	n = reftable_record_decode(rec, key, extra, in, it->br->hash_size);
 	if (n < 0)
@@ -350,6 +355,8 @@ int block_reader_first_key(struct block_reader *br, struct strbuf *key)
 	int n = reftable_decode_key(key, &extra, empty, in);
 	if (n < 0)
 		return n;
+	if (!key->len)
+		return -1;
 
 	return 0;
 }
diff --git a/reftable/block_test.c b/reftable/block_test.c
index 4b3ea262dcb..5112ddbf468 100644
--- a/reftable/block_test.c
+++ b/reftable/block_test.c
@@ -42,6 +42,11 @@ static void test_block_read_write(void)
 			  header_off, hash_size(GIT_SHA1_FORMAT_ID));
 	reftable_record_from_ref(&rec, &ref);
 
+	ref.refname = "";
+	ref.value_type = REFTABLE_REF_DELETION;
+	n = block_writer_add(&bw, &rec);
+	EXPECT(n == REFTABLE_API_ERROR);
+
 	for (i = 0; i < N; i++) {
 		char name[100];
 		uint8_t hash[GIT_SHA1_RAWSZ];
diff --git a/reftable/writer.c b/reftable/writer.c
index 35c8649c9b7..e3c042b9d84 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -238,14 +238,13 @@ static int writer_add_record(struct reftable_writer *w,
 
 	writer_reinit_block_writer(w, reftable_record_type(rec));
 	err = block_writer_add(w->block_writer, rec);
-	if (err < 0) {
+	if (err == -1) {
 		/* we are writing into memory, so an error can only mean it
 		 * doesn't fit. */
 		err = REFTABLE_ENTRY_TOO_BIG_ERROR;
 		goto done;
 	}
 
-	err = 0;
 done:
 	strbuf_release(&key);
 	return err;
-- 
gitgitgadget
Previous: Han-Wen Nienhuys via GitGitGadgetNext: Junio C Hamano
Message 5 of 33 in “reftable: avoid reading and writing empty keys”
  1. 0/7 reftable: avoid reading and writing empty keysHan-Wen Nienhuys via GitGitGadget, Jan 12, 2022
  2. 1/7 Documentation: object_id_len goes up to 31Han-Wen Nienhuys via GitGitGadget, Jan 12, 2022
  3. 2/7 reftable: reject 0 object_id_lenHan-Wen Nienhuys via GitGitGadget, Jan 12, 2022
  4. 3/7 reftable: add a test that verifies that writing empty keys failsHan-Wen Nienhuys via GitGitGadget, Jan 12, 2022
  5. 4/7 reftable: avoid writing empty keys at the block layerHan-Wen Nienhuys via GitGitGadget, Jan 12, 2022
  6. Junio C HamanoJan 14, 2022
  7. Han-Wen NienhuysJan 17, 2022
  8. Junio C HamanoJan 17, 2022
  9. 5/7 reftable: ensure that obj_id_len is >= 2 on writingHan-Wen Nienhuys via GitGitGadget, Jan 12, 2022
  10. 6/7 reftable: add test for length of disambiguating prefixHan-Wen Nienhuys via GitGitGadget, Jan 12, 2022
  11. 7/7 reftable: rename writer_stats to reftable_writer_statsHan-Wen Nienhuys via GitGitGadget, Jan 12, 2022
  12. 0/7 reftable: avoid reading and writing empty keysHan-Wen Nienhuys via GitGitGadget, Feb 17, 2022
  13. 1/7 Documentation: object_id_len goes up to 31Han-Wen Nienhuys via GitGitGadget, Feb 17, 2022
  14. 2/7 reftable: reject 0 object_id_lenHan-Wen Nienhuys via GitGitGadget, Feb 17, 2022
  15. Junio C HamanoFeb 18, 2022
  16. 3/7 reftable: add a test that verifies that writing empty keys failsHan-Wen Nienhuys via GitGitGadget, Feb 17, 2022
  17. 4/7 reftable: avoid writing empty keys at the block layerHan-Wen Nienhuys via GitGitGadget, Feb 17, 2022
  18. Junio C HamanoFeb 17, 2022
  19. Han-Wen NienhuysFeb 21, 2022
  20. 5/7 reftable: ensure that obj_id_len is >= 2 on writingHan-Wen Nienhuys via GitGitGadget, Feb 17, 2022
  21. Junio C HamanoFeb 18, 2022
  22. 6/7 reftable: add test for length of disambiguating prefixHan-Wen Nienhuys via GitGitGadget, Feb 17, 2022
  23. 7/7 reftable: rename writer_stats to reftable_writer_statsHan-Wen Nienhuys via GitGitGadget, Feb 17, 2022
  24. Junio C HamanoFeb 18, 2022
  25. 0/7 reftable: avoid reading and writing empty keysHan-Wen Nienhuys via GitGitGadget, Feb 21, 2022
  26. 2/7 reftable: reject 0 object_id_lenHan-Wen Nienhuys via GitGitGadget, Feb 21, 2022
  27. 1/7 Documentation: object_id_len goes up to 31Han-Wen Nienhuys via GitGitGadget, Feb 21, 2022
  28. 4/7 reftable: avoid writing empty keys at the block layerHan-Wen Nienhuys via GitGitGadget, Feb 21, 2022
  29. 3/7 reftable: add a test that verifies that writing empty keys failsHan-Wen Nienhuys via GitGitGadget, Feb 21, 2022
  30. 5/7 reftable: ensure that obj_id_len is >= 2 on writingHan-Wen Nienhuys via GitGitGadget, Feb 21, 2022
  31. 6/7 reftable: add test for length of disambiguating prefixHan-Wen Nienhuys via GitGitGadget, Feb 21, 2022
  32. 7/7 reftable: rename writer_stats to reftable_writer_statsHan-Wen Nienhuys via GitGitGadget, Feb 21, 2022
  33. Junio C HamanoFeb 23, 2022

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.