11#define USE_THE_REPOSITORY_VARIABLE
22
33#include "git-compat-util.h"
4+ #include "gettext.h"
45#include "hex.h"
56#include "lockfile.h"
67#include "tree.h"
@@ -865,15 +866,15 @@ int cache_tree_matches_traversal(struct cache_tree *root,
865866 return 0 ;
866867}
867868
868- static void verify_one_sparse (struct index_state * istate ,
869- struct strbuf * path ,
870- int pos )
869+ static int verify_one_sparse (struct index_state * istate ,
870+ struct strbuf * path ,
871+ int pos )
871872{
872873 struct cache_entry * ce = istate -> cache [pos ];
873-
874874 if (!S_ISSPARSEDIR (ce -> ce_mode ))
875- BUG ("directory '%s' is present in index, but not sparse" ,
876- path -> buf );
875+ return error (_ ("directory '%s' is present in index, but not sparse" ),
876+ path -> buf );
877+ return 0 ;
877878}
878879
879880/*
@@ -882,6 +883,7 @@ static void verify_one_sparse(struct index_state *istate,
882883 * 1 - Restart verification - a call to ensure_full_index() freed the cache
883884 * tree that is being verified and verification needs to be restarted from
884885 * the new toplevel cache tree.
886+ * -1 - Verification failed.
885887 */
886888static int verify_one (struct repository * r ,
887889 struct index_state * istate ,
@@ -891,18 +893,23 @@ static int verify_one(struct repository *r,
891893 int i , pos , len = path -> len ;
892894 struct strbuf tree_buf = STRBUF_INIT ;
893895 struct object_id new_oid ;
896+ int ret ;
894897
895898 for (i = 0 ; i < it -> subtree_nr ; i ++ ) {
896899 strbuf_addf (path , "%s/" , it -> down [i ]-> name );
897- if (verify_one (r , istate , it -> down [i ]-> cache_tree , path ))
898- return 1 ;
900+ ret = verify_one (r , istate , it -> down [i ]-> cache_tree , path );
901+ if (ret )
902+ goto out ;
903+
899904 strbuf_setlen (path , len );
900905 }
901906
902907 if (it -> entry_count < 0 ||
903908 /* no verification on tests (t7003) that replace trees */
904- lookup_replace_object (r , & it -> oid ) != & it -> oid )
905- return 0 ;
909+ lookup_replace_object (r , & it -> oid ) != & it -> oid ) {
910+ ret = 0 ;
911+ goto out ;
912+ }
906913
907914 if (path -> len ) {
908915 /*
@@ -912,19 +919,26 @@ static int verify_one(struct repository *r,
912919 */
913920 int is_sparse = istate -> sparse_index ;
914921 pos = index_name_pos (istate , path -> buf , path -> len );
915- if (is_sparse && !istate -> sparse_index )
916- return 1 ;
922+ if (is_sparse && !istate -> sparse_index ) {
923+ ret = 1 ;
924+ goto out ;
925+ }
917926
918927 if (pos >= 0 ) {
919- verify_one_sparse (istate , path , pos );
920- return 0 ;
928+ ret = verify_one_sparse (istate , path , pos );
929+ goto out ;
921930 }
922931
923932 pos = - pos - 1 ;
924933 } else {
925934 pos = 0 ;
926935 }
927936
937+ if (it -> entry_count + pos > istate -> cache_nr ) {
938+ ret = error (_ ("corrupted cache-tree has entries not present in index" ));
939+ goto out ;
940+ }
941+
928942 i = 0 ;
929943 while (i < it -> entry_count ) {
930944 struct cache_entry * ce = istate -> cache [pos + i ];
@@ -935,16 +949,23 @@ static int verify_one(struct repository *r,
935949 unsigned mode ;
936950 int entlen ;
937951
938- if (ce -> ce_flags & (CE_STAGEMASK | CE_INTENT_TO_ADD | CE_REMOVE ))
939- BUG ("%s with flags 0x%x should not be in cache-tree" ,
940- ce -> name , ce -> ce_flags );
952+ if (ce -> ce_flags & (CE_STAGEMASK | CE_INTENT_TO_ADD | CE_REMOVE )) {
953+ ret = error (_ ("%s with flags 0x%x should not be in cache-tree" ),
954+ ce -> name , ce -> ce_flags );
955+ goto out ;
956+ }
957+
941958 name = ce -> name + path -> len ;
942959 slash = strchr (name , '/' );
943960 if (slash ) {
944961 entlen = slash - name ;
962+
945963 sub = find_subtree (it , ce -> name + path -> len , entlen , 0 );
946- if (!sub || sub -> cache_tree -> entry_count < 0 )
947- BUG ("bad subtree '%.*s'" , entlen , name );
964+ if (!sub || sub -> cache_tree -> entry_count < 0 ) {
965+ ret = error (_ ("bad subtree '%.*s'" ), entlen , name );
966+ goto out ;
967+ }
968+
948969 oid = & sub -> cache_tree -> oid ;
949970 mode = S_IFDIR ;
950971 i += sub -> cache_tree -> entry_count ;
@@ -957,27 +978,50 @@ static int verify_one(struct repository *r,
957978 strbuf_addf (& tree_buf , "%o %.*s%c" , mode , entlen , name , '\0' );
958979 strbuf_add (& tree_buf , oid -> hash , r -> hash_algo -> rawsz );
959980 }
981+
960982 hash_object_file (r -> hash_algo , tree_buf .buf , tree_buf .len , OBJ_TREE ,
961983 & new_oid );
962- if (!oideq (& new_oid , & it -> oid ))
963- BUG ("cache-tree for path %.*s does not match. "
964- "Expected %s got %s" , len , path -> buf ,
965- oid_to_hex (& new_oid ), oid_to_hex (& it -> oid ));
984+
985+ if (!oideq (& new_oid , & it -> oid )) {
986+ ret = error (_ ("cache-tree for path %.*s does not match. "
987+ "Expected %s got %s" ), len , path -> buf ,
988+ oid_to_hex (& new_oid ), oid_to_hex (& it -> oid ));
989+ goto out ;
990+ }
991+
992+ ret = 0 ;
993+ out :
966994 strbuf_setlen (path , len );
967995 strbuf_release (& tree_buf );
968- return 0 ;
996+ return ret ;
969997}
970998
971- void cache_tree_verify (struct repository * r , struct index_state * istate )
999+ int cache_tree_verify (struct repository * r , struct index_state * istate )
9721000{
9731001 struct strbuf path = STRBUF_INIT ;
1002+ int ret ;
9741003
975- if (!istate -> cache_tree )
976- return ;
977- if (verify_one (r , istate , istate -> cache_tree , & path )) {
1004+ if (!istate -> cache_tree ) {
1005+ ret = 0 ;
1006+ goto out ;
1007+ }
1008+
1009+ ret = verify_one (r , istate , istate -> cache_tree , & path );
1010+ if (ret < 0 )
1011+ goto out ;
1012+ if (ret > 0 ) {
9781013 strbuf_reset (& path );
979- if (verify_one (r , istate , istate -> cache_tree , & path ))
1014+
1015+ ret = verify_one (r , istate , istate -> cache_tree , & path );
1016+ if (ret < 0 )
1017+ goto out ;
1018+ if (ret > 0 )
9801019 BUG ("ensure_full_index() called twice while verifying cache tree" );
9811020 }
1021+
1022+ ret = 0 ;
1023+
1024+ out :
9821025 strbuf_release (& path );
1026+ return ret ;
9831027}
0 commit comments