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

[RFC PATCH 10/15] reftable: don't have reader_get_block() confuse -fanalyzer

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Jun 3, 2022, 18:37 UTC
Message-ID
<RFC-patch-10.15-b50558d3b24-20220603T183608Z-avarab@gmail.com>
In-Reply-To
<RFC-cover-00.15-00000000000-20220603T183608Z-avarab@gmail.com>

Change the control flow in reftable code add in 46bc0e731a7 (reftable: read reftable files, 2021-10-07) to work around a false positive spotted by GCC's -fanalyzer option[1]. The code was added in 46bc0e731a7 (reftable: read reftable files, 2021-10-07).

Usually we'd just leave such false positives alone, but having looked at it the control flow was also odd and confusing to humans, so let's change it.

What -fanalyzer complained about was:
	|......
	|  294 |         if (next_off >= r_size)
	|      |            ~
	|      |            |
	|      |            (24) following ‘false’ branch (when ‘next_off < r_size’)...
	|......
	|  294 |         if (next_off >= r_size)
	|      |            ~
	|      |            |
	|      |            (24) following ‘false’ branch (when ‘next_off < r_size’)...
	|......
	|  297 |         err = reader_get_block(r, &block, next_off, guess_block_size, r->size);
	|      |               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	|      |               |
	|      |               (25) ...to here
	|      |               (26) calling ‘reader_get_block’ from ‘reader_init_block_reader’
	|
	+--> ‘reader_get_block’: events 27-29
	       |
	       |   59 | static int reader_get_block(struct reftable_reader *r,
	       |      |            ^~~~~~~~~~~~~~~~
	       |      |            |
	       |      |            (27) entry to ‘reader_get_block’
	       |......
	       |   63 |         if (off >= r_size)
	       |      |            ~
	       |      |            |
	       |      |            (28) following ‘true’ branch (when ‘off >= r_size’)...
	       |   64 |                 return 0;
	       |      |                        ~
	       |      |                        |
	       |      |                        (29) ...to here
	       [...]
	       |  275 |         *typ = data[0];
	       |      |                ~~~~~~~
	       |      |                    |
	       |      |                    (37) ...to here
	       |      |                    (38) dereference of NULL ‘data’

I.e. it thought that we could take the "return 0" in reader_get_block() due to "(off >= r->size)", which followed the identical "(next_off >= r_size)" check in reader_init_block_reader() just before reader_get_block() was called.

But whatever GCC's -fanalyzer thinks it's confusing that we're checking this twice, and making it look as though these parameters might change within the reader_init_block_reader() function, but they won't. So let's just do the check once early, and use "const" types to assert that they'll be constant throughout.

1. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105285
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 reftable/reader.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/reftable/reader.c b/reftable/reader.c
index 54b4025105c..e1649929b30 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -58,9 +58,9 @@ reader_offsets_for(struct reftable_reader *r, uint8_t typ)
 
 static int reader_get_block(struct reftable_reader *r,
 			    struct reftable_block *dest, uint64_t off,
-			    uint32_t sz)
+			    uint32_t sz, uint64_t r_size)
 {
-	if (off >= r->size)
+	if (off >= r_size)
 		return 0;
 
 	if (off + sz > r->size) {
@@ -281,6 +281,7 @@ static int32_t extract_block_size(uint8_t *data, uint8_t *typ, uint64_t off,
 int reader_init_block_reader(struct reftable_reader *r, struct block_reader *br,
 			     uint64_t next_off, uint8_t want_typ)
 {
+	const uint64_t r_size = r->size;
 	int32_t guess_block_size = r->block_size ? r->block_size :
 							 DEFAULT_BLOCK_SIZE;
 	struct reftable_block block = { NULL };
@@ -289,10 +290,10 @@ int reader_init_block_reader(struct reftable_reader *r, struct block_reader *br,
 	uint32_t header_off = next_off ? 0 : header_size(r->version);
 	int32_t block_size = 0;
 
-	if (next_off >= r->size)
+	if (next_off >= r_size)
 		return 1;
 
-	err = reader_get_block(r, &block, next_off, guess_block_size);
+	err = reader_get_block(r, &block, next_off, guess_block_size, r_size);
 	if (err < 0)
 		goto done;
 
@@ -309,7 +310,7 @@ int reader_init_block_reader(struct reftable_reader *r, struct block_reader *br,
 
 	if (block_size > guess_block_size) {
 		reftable_block_done(&block);
-		err = reader_get_block(r, &block, next_off, block_size);
+		err = reader_get_block(r, &block, next_off, block_size, r_size);
 		if (err < 0) {
 			goto done;
 		}
-- 
2.36.1.1124.g577fa9c2ebd
Previous: Phillip WoodNext: Ævar Arnfjörð Bjarmason
Message 36 of 51 in “Fix GCC -fanalyzer warnings & add -fanalyzer DEVOPTS mode”
  1. 00/15 Fix GCC -fanalyzer warnings & add -fanalyzer DEVOPTS modeÆvar Arnfjörð Bjarmason, Jun 3, 2022
  2. 01/15 remote.c: don't dereference NULL in freeing loopÆvar Arnfjörð Bjarmason, Jun 3, 2022
  3. René ScharfeJun 3, 2022
  4. Junio C HamanoJun 3, 2022
  5. Glen ChooJun 3, 2022
  6. Phillip WoodJun 4, 2022
  7. Ævar Arnfjörð BjarmasonJun 4, 2022
  8. 02/15 pull.c: don't feed NULL to strcmp() on get_rebase_fork_point() pathÆvar Arnfjörð Bjarmason, Jun 3, 2022
  9. René ScharfeJun 3, 2022
  10. 03/15 reftable: don't memset() a NULL from failed malloc()Ævar Arnfjörð Bjarmason, Jun 3, 2022
  11. René ScharfeJun 3, 2022
  12. Ævar Arnfjörð BjarmasonJun 4, 2022
  13. René ScharfeJun 4, 2022
  14. Ævar Arnfjörð BjarmasonJun 4, 2022
  15. René ScharfeJun 4, 2022
  16. Junio C HamanoJun 6, 2022
  17. Ævar Arnfjörð BjarmasonJun 6, 2022
  18. Junio C HamanoJun 6, 2022
  19. Ævar Arnfjörð BjarmasonJun 6, 2022
  20. 04/15 diff-lib.c: don't dereference NULL in oneway_diff()Ævar Arnfjörð Bjarmason, Jun 3, 2022
  21. René ScharfeJun 3, 2022
  22. 05/15 refs/packed-backend.c: add a BUG() if iter is NULLÆvar Arnfjörð Bjarmason, Jun 3, 2022
  23. René ScharfeJun 3, 2022
  24. 06/15 ref-filter.c: BUG() out on show_ref() with NULL refnameÆvar Arnfjörð Bjarmason, Jun 3, 2022
  25. René ScharfeJun 4, 2022
  26. 07/15 strbuf.c: placate -fanalyzer in strbuf_grow()Ævar Arnfjörð Bjarmason, Jun 3, 2022
  27. René ScharfeJun 4, 2022
  28. Phillip WoodJun 4, 2022
  29. Ævar Arnfjörð BjarmasonJun 4, 2022
  30. René ScharfeJun 4, 2022
  31. Phillip WoodJun 5, 2022
  32. 08/15 strbuf.c: use st_add3(), not unsigned_add_overflows()Ævar Arnfjörð Bjarmason, Jun 3, 2022
  33. René ScharfeJun 4, 2022
  34. 09/15 add-patch: assert parse_diff() expectations with BUG()Ævar Arnfjörð Bjarmason, Jun 3, 2022
  35. Phillip WoodJun 4, 2022
  36. 10/15 reftable: don't have reader_get_block() confuse -fanalyzerÆvar Arnfjörð Bjarmason, Jun 3, 2022
  37. 11/15 blame.c: clarify the state of "final_commit" for -fanalyzerÆvar Arnfjörð Bjarmason, Jun 3, 2022
  38. 14/15 config.mak.dev: add a DEVOPTS=analyzer mode to use GCC's -fanalyzerÆvar Arnfjörð Bjarmason, Jun 3, 2022
  39. 12/15 pack.h: wrap write_*file*() functionsÆvar Arnfjörð Bjarmason, Jun 3, 2022
  40. 13/15 pack-write API: pass down "verify" not arbitrary flagsÆvar Arnfjörð Bjarmason, Jun 3, 2022
  41. 15/15 config.mak.dev: add and use ASSERT_FOR_FANALYZER() macroÆvar Arnfjörð Bjarmason, Jun 3, 2022
  42. Phillip WoodJun 4, 2022
  43. 0/3 remote API: fix -fanalyzer-spotted freeing issueÆvar Arnfjörð Bjarmason, Jun 7, 2022
  44. 1/3 remote.c: remove braces from one-statement "for"-loopsÆvar Arnfjörð Bjarmason, Jun 7, 2022
  45. 2/3 remote.c: don't dereference NULL in freeing loopÆvar Arnfjörð Bjarmason, Jun 7, 2022
  46. Junio C HamanoJun 7, 2022
  47. 3/3 remote API: don't buggily FREE_AND_NULL(), free() insteadÆvar Arnfjörð Bjarmason, Jun 7, 2022
  48. Glen ChooJun 7, 2022
  49. Junio C HamanoJun 7, 2022
  50. Junio C HamanoJun 7, 2022
  51. Junio C HamanoJun 7, 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.