Commit ac07a40a3c7827ff92b46afff32379b1ec1950b2

Colin Stolley 2022-01-12T16:57:51

Check packed-refs filestamp before reusing mmap. Avoid using a stale mmap() by tracking the filestamp.

diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index af5345d..753cff7 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -67,6 +67,7 @@ typedef struct refdb_fs_backend {
 	int fsync;
 	git_map packed_refs_map;
 	git_mutex prlock; /* protect packed_refs_map */
+	git_futils_filestamp packed_refs_stamp;
 	bool sorted;
 } refdb_fs_backend;
 
@@ -495,6 +496,7 @@ static void packed_map_free(refdb_fs_backend *backend)
 #endif
 		backend->packed_refs_map.data = NULL;
 		backend->packed_refs_map.len = 0;
+		git_futils_filestamp_set(&backend->packed_refs_stamp, NULL);
 	}
 }
 
@@ -507,10 +509,13 @@ static int packed_map_check(refdb_fs_backend *backend)
 	if ((error = git_mutex_lock(&backend->prlock)) < 0)
 		return error;
 
-	if (backend->packed_refs_map.data) {
+	if (backend->packed_refs_map.data &&
+	    !git_futils_filestamp_check(
+	            &backend->packed_refs_stamp, backend->refcache->path)) {
 		git_mutex_unlock(&backend->prlock);
 		return error;
 	}
+	packed_map_free(backend);
 
 	fd = git_futils_open_ro(backend->refcache->path);
 	if (fd < 0) {
@@ -535,6 +540,8 @@ static int packed_map_check(refdb_fs_backend *backend)
 		return 0;
 	}
 
+	git_futils_filestamp_set_from_stat(&backend->packed_refs_stamp, &st);
+
 #ifdef GIT_WIN32
 	/* on windows, we copy the entire file into memory rather than using
 	 * mmap() because using mmap() on windows also locks the file and this