1
1
#define USE_THE_REPOSITORY_VARIABLE
2
2
3
3
#include "git-compat-util.h"
4
+ #include "gettext.h"
4
5
#include "hex.h"
5
6
#include "lockfile.h"
6
7
#include "tree.h"
@@ -865,15 +866,15 @@ int cache_tree_matches_traversal(struct cache_tree *root,
865
866
return 0 ;
866
867
}
867
868
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 )
871
872
{
872
873
struct cache_entry * ce = istate -> cache [pos ];
873
-
874
874
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 ;
877
878
}
878
879
879
880
/*
@@ -882,6 +883,7 @@ static void verify_one_sparse(struct index_state *istate,
882
883
* 1 - Restart verification - a call to ensure_full_index() freed the cache
883
884
* tree that is being verified and verification needs to be restarted from
884
885
* the new toplevel cache tree.
886
+ * -1 - Verification failed.
885
887
*/
886
888
static int verify_one (struct repository * r ,
887
889
struct index_state * istate ,
@@ -891,18 +893,23 @@ static int verify_one(struct repository *r,
891
893
int i , pos , len = path -> len ;
892
894
struct strbuf tree_buf = STRBUF_INIT ;
893
895
struct object_id new_oid ;
896
+ int ret ;
894
897
895
898
for (i = 0 ; i < it -> subtree_nr ; i ++ ) {
896
899
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
+
899
904
strbuf_setlen (path , len );
900
905
}
901
906
902
907
if (it -> entry_count < 0 ||
903
908
/* 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
+ }
906
913
907
914
if (path -> len ) {
908
915
/*
@@ -912,19 +919,26 @@ static int verify_one(struct repository *r,
912
919
*/
913
920
int is_sparse = istate -> sparse_index ;
914
921
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
+ }
917
926
918
927
if (pos >= 0 ) {
919
- verify_one_sparse (istate , path , pos );
920
- return 0 ;
928
+ ret = verify_one_sparse (istate , path , pos );
929
+ goto out ;
921
930
}
922
931
923
932
pos = - pos - 1 ;
924
933
} else {
925
934
pos = 0 ;
926
935
}
927
936
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
+
928
942
i = 0 ;
929
943
while (i < it -> entry_count ) {
930
944
struct cache_entry * ce = istate -> cache [pos + i ];
@@ -935,16 +949,23 @@ static int verify_one(struct repository *r,
935
949
unsigned mode ;
936
950
int entlen ;
937
951
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
+
941
958
name = ce -> name + path -> len ;
942
959
slash = strchr (name , '/' );
943
960
if (slash ) {
944
961
entlen = slash - name ;
962
+
945
963
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
+
948
969
oid = & sub -> cache_tree -> oid ;
949
970
mode = S_IFDIR ;
950
971
i += sub -> cache_tree -> entry_count ;
@@ -957,27 +978,50 @@ static int verify_one(struct repository *r,
957
978
strbuf_addf (& tree_buf , "%o %.*s%c" , mode , entlen , name , '\0' );
958
979
strbuf_add (& tree_buf , oid -> hash , r -> hash_algo -> rawsz );
959
980
}
981
+
960
982
hash_object_file (r -> hash_algo , tree_buf .buf , tree_buf .len , OBJ_TREE ,
961
983
& 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 :
966
994
strbuf_setlen (path , len );
967
995
strbuf_release (& tree_buf );
968
- return 0 ;
996
+ return ret ;
969
997
}
970
998
971
- void cache_tree_verify (struct repository * r , struct index_state * istate )
999
+ int cache_tree_verify (struct repository * r , struct index_state * istate )
972
1000
{
973
1001
struct strbuf path = STRBUF_INIT ;
1002
+ int ret ;
974
1003
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 ) {
978
1013
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 )
980
1019
BUG ("ensure_full_index() called twice while verifying cache tree" );
981
1020
}
1021
+
1022
+ ret = 0 ;
1023
+
1024
+ out :
982
1025
strbuf_release (& path );
1026
+ return ret ;
983
1027
}
0 commit comments