Fossil SCM

Add the hname_verify_hash() routine and use it to fix "fossil test-integrity" such that it verifies the display hash regardless of the algorithm used.

drh 2017-02-28 19:15 fossil-2.0
Commit 08badee3a415cf0788adc1d50eeb03a19fac9b5b
2 files changed +5 -8 +33
+5 -8
--- src/content.c
+++ src/content.c
@@ -497,11 +497,11 @@
497497
** to be responsible for pBlob. This routine does *not* take over
498498
** responsibility for freeing pBlob.
499499
*/
500500
int content_put_ex(
501501
Blob *pBlob, /* Content to add to the repository */
502
- const char *zUuid, /* SHA1 hash of reconstructed pBlob */
502
+ const char *zUuid, /* artifact hash of reconstructed pBlob */
503503
int srcId, /* pBlob is a delta from this entry */
504504
int nBlob, /* pBlob is compressed. Original size is this */
505505
int isPrivate /* The content should be marked private */
506506
){
507507
int size;
@@ -868,11 +868,10 @@
868868
** so forth, reporting any errors found.
869869
*/
870870
void test_integrity(void){
871871
Stmt q;
872872
Blob content;
873
- Blob cksum;
874873
int n1 = 0;
875874
int n2 = 0;
876875
int nErr = 0;
877876
int total;
878877
int nCA = 0;
@@ -905,10 +904,11 @@
905904
db_prepare(&q, "SELECT rid, uuid, size FROM blob ORDER BY rid");
906905
total = db_int(0, "SELECT max(rid) FROM blob");
907906
while( db_step(&q)==SQLITE_ROW ){
908907
int rid = db_column_int(&q, 0);
909908
const char *zUuid = db_column_text(&q, 1);
909
+ int nUuid = db_column_bytes(&q, 1);
910910
int size = db_column_int(&q, 2);
911911
n1++;
912912
fossil_print(" %d/%d\r", n1, total);
913913
fflush(stdout);
914914
if( size<0 ){
@@ -919,14 +919,12 @@
919919
if( blob_size(&content)!=size ){
920920
fossil_print("size mismatch on artifact %d: wanted %d but got %d\n",
921921
rid, size, blob_size(&content));
922922
nErr++;
923923
}
924
- sha1sum_blob(&content, &cksum);
925
- if( fossil_strcmp(blob_str(&cksum), zUuid)!=0 ){
926
- fossil_print("wrong hash on artifact %d: wanted %s but got %s\n",
927
- rid, zUuid, blob_str(&cksum));
924
+ if( !hname_verify_hash(&content, zUuid, nUuid) ){
925
+ fossil_print("wrong hash on artifact %d\n",rid);
928926
nErr++;
929927
}
930928
if( bParse && looks_like_control_artifact(&content) ){
931929
Blob err;
932930
int i, n;
@@ -941,11 +939,11 @@
941939
memcpy(zFirstLine, z, i);
942940
zFirstLine[i] = 0;
943941
p = manifest_parse(&content, 0, &err);
944942
if( p==0 ){
945943
fossil_print("manifest_parse failed for %s:\n%s\n",
946
- blob_str(&cksum), blob_str(&err));
944
+ zUuid, blob_str(&err));
947945
if( strncmp(blob_str(&err), "line 1:", 7)==0 ){
948946
fossil_print("\"%s\"\n", zFirstLine);
949947
}
950948
}else{
951949
anCA[p->type]++;
@@ -954,11 +952,10 @@
954952
}
955953
blob_reset(&err);
956954
}else{
957955
blob_reset(&content);
958956
}
959
- blob_reset(&cksum);
960957
n2++;
961958
}
962959
db_finalize(&q);
963960
fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n",
964961
n2, n1, nErr);
965962
--- src/content.c
+++ src/content.c
@@ -497,11 +497,11 @@
497 ** to be responsible for pBlob. This routine does *not* take over
498 ** responsibility for freeing pBlob.
499 */
500 int content_put_ex(
501 Blob *pBlob, /* Content to add to the repository */
502 const char *zUuid, /* SHA1 hash of reconstructed pBlob */
503 int srcId, /* pBlob is a delta from this entry */
504 int nBlob, /* pBlob is compressed. Original size is this */
505 int isPrivate /* The content should be marked private */
506 ){
507 int size;
@@ -868,11 +868,10 @@
868 ** so forth, reporting any errors found.
869 */
870 void test_integrity(void){
871 Stmt q;
872 Blob content;
873 Blob cksum;
874 int n1 = 0;
875 int n2 = 0;
876 int nErr = 0;
877 int total;
878 int nCA = 0;
@@ -905,10 +904,11 @@
905 db_prepare(&q, "SELECT rid, uuid, size FROM blob ORDER BY rid");
906 total = db_int(0, "SELECT max(rid) FROM blob");
907 while( db_step(&q)==SQLITE_ROW ){
908 int rid = db_column_int(&q, 0);
909 const char *zUuid = db_column_text(&q, 1);
 
910 int size = db_column_int(&q, 2);
911 n1++;
912 fossil_print(" %d/%d\r", n1, total);
913 fflush(stdout);
914 if( size<0 ){
@@ -919,14 +919,12 @@
919 if( blob_size(&content)!=size ){
920 fossil_print("size mismatch on artifact %d: wanted %d but got %d\n",
921 rid, size, blob_size(&content));
922 nErr++;
923 }
924 sha1sum_blob(&content, &cksum);
925 if( fossil_strcmp(blob_str(&cksum), zUuid)!=0 ){
926 fossil_print("wrong hash on artifact %d: wanted %s but got %s\n",
927 rid, zUuid, blob_str(&cksum));
928 nErr++;
929 }
930 if( bParse && looks_like_control_artifact(&content) ){
931 Blob err;
932 int i, n;
@@ -941,11 +939,11 @@
941 memcpy(zFirstLine, z, i);
942 zFirstLine[i] = 0;
943 p = manifest_parse(&content, 0, &err);
944 if( p==0 ){
945 fossil_print("manifest_parse failed for %s:\n%s\n",
946 blob_str(&cksum), blob_str(&err));
947 if( strncmp(blob_str(&err), "line 1:", 7)==0 ){
948 fossil_print("\"%s\"\n", zFirstLine);
949 }
950 }else{
951 anCA[p->type]++;
@@ -954,11 +952,10 @@
954 }
955 blob_reset(&err);
956 }else{
957 blob_reset(&content);
958 }
959 blob_reset(&cksum);
960 n2++;
961 }
962 db_finalize(&q);
963 fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n",
964 n2, n1, nErr);
965
--- src/content.c
+++ src/content.c
@@ -497,11 +497,11 @@
497 ** to be responsible for pBlob. This routine does *not* take over
498 ** responsibility for freeing pBlob.
499 */
500 int content_put_ex(
501 Blob *pBlob, /* Content to add to the repository */
502 const char *zUuid, /* artifact hash of reconstructed pBlob */
503 int srcId, /* pBlob is a delta from this entry */
504 int nBlob, /* pBlob is compressed. Original size is this */
505 int isPrivate /* The content should be marked private */
506 ){
507 int size;
@@ -868,11 +868,10 @@
868 ** so forth, reporting any errors found.
869 */
870 void test_integrity(void){
871 Stmt q;
872 Blob content;
 
873 int n1 = 0;
874 int n2 = 0;
875 int nErr = 0;
876 int total;
877 int nCA = 0;
@@ -905,10 +904,11 @@
904 db_prepare(&q, "SELECT rid, uuid, size FROM blob ORDER BY rid");
905 total = db_int(0, "SELECT max(rid) FROM blob");
906 while( db_step(&q)==SQLITE_ROW ){
907 int rid = db_column_int(&q, 0);
908 const char *zUuid = db_column_text(&q, 1);
909 int nUuid = db_column_bytes(&q, 1);
910 int size = db_column_int(&q, 2);
911 n1++;
912 fossil_print(" %d/%d\r", n1, total);
913 fflush(stdout);
914 if( size<0 ){
@@ -919,14 +919,12 @@
919 if( blob_size(&content)!=size ){
920 fossil_print("size mismatch on artifact %d: wanted %d but got %d\n",
921 rid, size, blob_size(&content));
922 nErr++;
923 }
924 if( !hname_verify_hash(&content, zUuid, nUuid) ){
925 fossil_print("wrong hash on artifact %d\n",rid);
 
 
926 nErr++;
927 }
928 if( bParse && looks_like_control_artifact(&content) ){
929 Blob err;
930 int i, n;
@@ -941,11 +939,11 @@
939 memcpy(zFirstLine, z, i);
940 zFirstLine[i] = 0;
941 p = manifest_parse(&content, 0, &err);
942 if( p==0 ){
943 fossil_print("manifest_parse failed for %s:\n%s\n",
944 zUuid, blob_str(&err));
945 if( strncmp(blob_str(&err), "line 1:", 7)==0 ){
946 fossil_print("\"%s\"\n", zFirstLine);
947 }
948 }else{
949 anCA[p->type]++;
@@ -954,11 +952,10 @@
952 }
953 blob_reset(&err);
954 }else{
955 blob_reset(&content);
956 }
 
957 n2++;
958 }
959 db_finalize(&q);
960 fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n",
961 n2, n1, nErr);
962
+33
--- src/hname.c
+++ src/hname.c
@@ -82,5 +82,38 @@
8282
default: return HNAME_ERROR;
8383
}
8484
if( !validate16(zHash, nHash) ) return HNAME_ERROR;
8585
return id;
8686
}
87
+
88
+/*
89
+** Verify that zHash is a valid hash for the content in pContent.
90
+** Return true if the hash is correct. Return false if the content
91
+** does not match the hash.
92
+**
93
+** Actually, the returned value is one of the hash algorithm constants
94
+** corresponding to the hash that matched if the hash is correct.
95
+** (Examples: HNAME_SHA1 or HNAME_K224). And the return is HNAME_ERROR
96
+** if the hash does not match.
97
+*/
98
+int hname_verify_hash(Blob *pContent, const char *zHash, int nHash){
99
+ int id = HNAME_ERROR;
100
+ switch( nHash ){
101
+ case HNAME_LEN_SHA1: {
102
+ Blob hash;
103
+ sha1sum_blob(pContent, &hash);
104
+ if( memcmp(blob_buffer(&hash),zHash,HNAME_LEN_SHA1)==0 ) id = HNAME_SHA1;
105
+ blob_reset(&hash);
106
+ break;
107
+ }
108
+ case HNAME_LEN_K224:
109
+ case HNAME_LEN_K256: {
110
+ sha3sum_init(nHash*4);
111
+ sha3sum_step_blob(pContent);
112
+ if( memcmp(sha3sum_finish(0),zHash,nHash)==0 ){
113
+ id = nHash==HNAME_LEN_K224 ? HNAME_K224 : HNAME_K256;
114
+ }
115
+ break;
116
+ }
117
+ }
118
+ return id;
119
+}
87120
--- src/hname.c
+++ src/hname.c
@@ -82,5 +82,38 @@
82 default: return HNAME_ERROR;
83 }
84 if( !validate16(zHash, nHash) ) return HNAME_ERROR;
85 return id;
86 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
--- src/hname.c
+++ src/hname.c
@@ -82,5 +82,38 @@
82 default: return HNAME_ERROR;
83 }
84 if( !validate16(zHash, nHash) ) return HNAME_ERROR;
85 return id;
86 }
87
88 /*
89 ** Verify that zHash is a valid hash for the content in pContent.
90 ** Return true if the hash is correct. Return false if the content
91 ** does not match the hash.
92 **
93 ** Actually, the returned value is one of the hash algorithm constants
94 ** corresponding to the hash that matched if the hash is correct.
95 ** (Examples: HNAME_SHA1 or HNAME_K224). And the return is HNAME_ERROR
96 ** if the hash does not match.
97 */
98 int hname_verify_hash(Blob *pContent, const char *zHash, int nHash){
99 int id = HNAME_ERROR;
100 switch( nHash ){
101 case HNAME_LEN_SHA1: {
102 Blob hash;
103 sha1sum_blob(pContent, &hash);
104 if( memcmp(blob_buffer(&hash),zHash,HNAME_LEN_SHA1)==0 ) id = HNAME_SHA1;
105 blob_reset(&hash);
106 break;
107 }
108 case HNAME_LEN_K224:
109 case HNAME_LEN_K256: {
110 sha3sum_init(nHash*4);
111 sha3sum_step_blob(pContent);
112 if( memcmp(sha3sum_finish(0),zHash,nHash)==0 ){
113 id = nHash==HNAME_LEN_K224 ? HNAME_K224 : HNAME_K256;
114 }
115 break;
116 }
117 }
118 return id;
119 }
120

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button