Fossil SCM

Update the fingerprint mechanism so that it if the revised hash algorithm fails, it retries using the legacy hash algorithm before reporting an error (and alarming users). The revised hash is always stored. The "test-fingerprint" command is updated to show both the old and the new hash algorithm and the fingerprint currently stored in the localdb.

drh 2019-09-27 18:47 trunk
Commit 36d3685833e1eb1a2802c0094c7e7bc7a588bb209328e6ab4b0259a163e96296
1 file changed +39 -19
+39 -19
--- src/db.c
+++ src/db.c
@@ -1735,11 +1735,11 @@
17351735
char *z;
17361736
stash_rid_renumbering_event();
17371737
vfile_rid_renumbering_event(0);
17381738
undo_reset();
17391739
bisect_reset();
1740
- z = db_fingerprint(0);
1740
+ z = db_fingerprint(0, 1);
17411741
db_lset("fingerprint", z);
17421742
fossil_free(z);
17431743
fossil_print(
17441744
"WARNING: The repository database has been replaced by a clone.\n"
17451745
"Bisect history and undo have been lost.\n"
@@ -3933,18 +3933,30 @@
39333933
** the remaining fields of the RCVFROM table entry. MD5 is used for this
39343934
** because it is 4x faster than SHA3 and 5x faster than SHA1, and there
39353935
** are no security concerns - this is just a checksum, not a security
39363936
** token.
39373937
*/
3938
-char *db_fingerprint(int rcvid){
3938
+char *db_fingerprint(int rcvid, int iVersion){
39393939
char *z = 0;
39403940
Blob sql = BLOB_INITIALIZER;
39413941
Stmt q;
3942
- blob_append_sql(&sql,
3943
- "SELECT rcvid, quote(uid), datetime(mtime), quote(nonce), quote(ipaddr)"
3944
- " FROM rcvfrom"
3945
- );
3942
+ if( iVersion==0 ){
3943
+ /* The original fingerprint algorithm used "quote(mtime)". But this
3944
+ ** could give slightly different answers depending on how the floating-
3945
+ ** point hardware is configured. For example, it gave different
3946
+ ** answers on native Linux versus running under valgrind. */
3947
+ blob_append_sql(&sql,
3948
+ "SELECT rcvid, quote(uid), quote(mtime), quote(nonce), quote(ipaddr)"
3949
+ " FROM rcvfrom"
3950
+ );
3951
+ }else{
3952
+ /* These days, we use "datetime(mtime)" for more consistent answers */
3953
+ blob_append_sql(&sql,
3954
+ "SELECT rcvid, quote(uid), datetime(mtime), quote(nonce), quote(ipaddr)"
3955
+ " FROM rcvfrom"
3956
+ );
3957
+ }
39463958
if( rcvid<=0 ){
39473959
blob_append_sql(&sql, " ORDER BY rcvid DESC LIMIT 1");
39483960
}else{
39493961
blob_append_sql(&sql, " WHERE rcvid=%d", rcvid);
39503962
}
@@ -3963,30 +3975,31 @@
39633975
}
39643976
39653977
/*
39663978
** COMMAND: test-fingerprint
39673979
**
3968
-** Usage: %fossil test-fingerprint ?RCVID? ?--check?
3980
+** Usage: %fossil test-fingerprint ?RCVID?
39693981
**
3970
-** Display the repository fingerprint. Or if the --check option
3971
-** is provided and this command is run from a checkout, invoke the
3972
-** db_fingerprint_ok() method and print its result.
3982
+** Display the repository fingerprint using the supplied RCVID or
3983
+** using the latest RCVID if not is given on the command line.
3984
+** Show both the legacy and the newer version of the fingerprint,
3985
+** and the currently stored fingerprint if there is one.
39733986
*/
39743987
void test_fingerprint(void){
39753988
int rcvid = 0;
3976
- if( find_option("check",0,0)!=0 ){
3977
- db_must_be_within_tree();
3978
- fossil_print("db_fingerprint_ok() => %d\n", db_fingerprint_ok());
3979
- return;
3980
- }
39813989
db_find_and_open_repository(OPEN_ANY_SCHEMA,0);
39823990
if( g.argc==3 ){
39833991
rcvid = atoi(g.argv[2]);
39843992
}else if( g.argc!=2 ){
39853993
fossil_fatal("wrong number of arguments");
39863994
}
3987
- fossil_print("%z\n", db_fingerprint(rcvid));
3995
+ fossil_print("legecy: %z\n", db_fingerprint(rcvid, 0));
3996
+ fossil_print("version-1: %z\n", db_fingerprint(rcvid, 1));
3997
+ if( g.localOpen ){
3998
+ fossil_print("localdb: %z\n", db_lget("fingerprint","(none)"));
3999
+ fossil_print("db_fingerprint_ok(): %d\n", db_fingerprint_ok());
4000
+ }
39884001
}
39894002
39904003
/*
39914004
** Set the value of the "checkout" entry in the VVAR table.
39924005
**
@@ -3996,11 +4009,11 @@
39964009
char *z;
39974010
db_lset_int("checkout", rid);
39984011
z = db_text(0,"SELECT uuid FROM blob WHERE rid=%d",rid);
39994012
db_lset("checkout-hash", z);
40004013
fossil_free(z);
4001
- z = db_fingerprint(0);
4014
+ z = db_fingerprint(0, 1);
40024015
db_lset("fingerprint", z);
40034016
fossil_free(z);
40044017
}
40054018
40064019
/*
@@ -4018,11 +4031,18 @@
40184031
if( zCkout==0 ){
40194032
/* This is an older checkout that does not record a fingerprint.
40204033
** We have to assume everything is ok */
40214034
return 2;
40224035
}
4023
- zRepo = db_fingerprint(atoi(zCkout));
4036
+ zRepo = db_fingerprint(atoi(zCkout), 1);
40244037
rc = fossil_strcmp(zCkout,zRepo)==0;
4025
- fossil_free(zCkout);
40264038
fossil_free(zRepo);
4039
+ /* If the initial test fails, try again using the older fingerprint
4040
+ ** algorithm */
4041
+ if( !rc ){
4042
+ zRepo = db_fingerprint(atoi(zCkout), 0);
4043
+ rc = fossil_strcmp(zCkout,zRepo)==0;
4044
+ fossil_free(zRepo);
4045
+ }
4046
+ fossil_free(zCkout);
40274047
return rc;
40284048
}
40294049
--- src/db.c
+++ src/db.c
@@ -1735,11 +1735,11 @@
1735 char *z;
1736 stash_rid_renumbering_event();
1737 vfile_rid_renumbering_event(0);
1738 undo_reset();
1739 bisect_reset();
1740 z = db_fingerprint(0);
1741 db_lset("fingerprint", z);
1742 fossil_free(z);
1743 fossil_print(
1744 "WARNING: The repository database has been replaced by a clone.\n"
1745 "Bisect history and undo have been lost.\n"
@@ -3933,18 +3933,30 @@
3933 ** the remaining fields of the RCVFROM table entry. MD5 is used for this
3934 ** because it is 4x faster than SHA3 and 5x faster than SHA1, and there
3935 ** are no security concerns - this is just a checksum, not a security
3936 ** token.
3937 */
3938 char *db_fingerprint(int rcvid){
3939 char *z = 0;
3940 Blob sql = BLOB_INITIALIZER;
3941 Stmt q;
3942 blob_append_sql(&sql,
3943 "SELECT rcvid, quote(uid), datetime(mtime), quote(nonce), quote(ipaddr)"
3944 " FROM rcvfrom"
3945 );
 
 
 
 
 
 
 
 
 
 
 
 
3946 if( rcvid<=0 ){
3947 blob_append_sql(&sql, " ORDER BY rcvid DESC LIMIT 1");
3948 }else{
3949 blob_append_sql(&sql, " WHERE rcvid=%d", rcvid);
3950 }
@@ -3963,30 +3975,31 @@
3963 }
3964
3965 /*
3966 ** COMMAND: test-fingerprint
3967 **
3968 ** Usage: %fossil test-fingerprint ?RCVID? ?--check?
3969 **
3970 ** Display the repository fingerprint. Or if the --check option
3971 ** is provided and this command is run from a checkout, invoke the
3972 ** db_fingerprint_ok() method and print its result.
 
3973 */
3974 void test_fingerprint(void){
3975 int rcvid = 0;
3976 if( find_option("check",0,0)!=0 ){
3977 db_must_be_within_tree();
3978 fossil_print("db_fingerprint_ok() => %d\n", db_fingerprint_ok());
3979 return;
3980 }
3981 db_find_and_open_repository(OPEN_ANY_SCHEMA,0);
3982 if( g.argc==3 ){
3983 rcvid = atoi(g.argv[2]);
3984 }else if( g.argc!=2 ){
3985 fossil_fatal("wrong number of arguments");
3986 }
3987 fossil_print("%z\n", db_fingerprint(rcvid));
 
 
 
 
 
3988 }
3989
3990 /*
3991 ** Set the value of the "checkout" entry in the VVAR table.
3992 **
@@ -3996,11 +4009,11 @@
3996 char *z;
3997 db_lset_int("checkout", rid);
3998 z = db_text(0,"SELECT uuid FROM blob WHERE rid=%d",rid);
3999 db_lset("checkout-hash", z);
4000 fossil_free(z);
4001 z = db_fingerprint(0);
4002 db_lset("fingerprint", z);
4003 fossil_free(z);
4004 }
4005
4006 /*
@@ -4018,11 +4031,18 @@
4018 if( zCkout==0 ){
4019 /* This is an older checkout that does not record a fingerprint.
4020 ** We have to assume everything is ok */
4021 return 2;
4022 }
4023 zRepo = db_fingerprint(atoi(zCkout));
4024 rc = fossil_strcmp(zCkout,zRepo)==0;
4025 fossil_free(zCkout);
4026 fossil_free(zRepo);
 
 
 
 
 
 
 
 
4027 return rc;
4028 }
4029
--- src/db.c
+++ src/db.c
@@ -1735,11 +1735,11 @@
1735 char *z;
1736 stash_rid_renumbering_event();
1737 vfile_rid_renumbering_event(0);
1738 undo_reset();
1739 bisect_reset();
1740 z = db_fingerprint(0, 1);
1741 db_lset("fingerprint", z);
1742 fossil_free(z);
1743 fossil_print(
1744 "WARNING: The repository database has been replaced by a clone.\n"
1745 "Bisect history and undo have been lost.\n"
@@ -3933,18 +3933,30 @@
3933 ** the remaining fields of the RCVFROM table entry. MD5 is used for this
3934 ** because it is 4x faster than SHA3 and 5x faster than SHA1, and there
3935 ** are no security concerns - this is just a checksum, not a security
3936 ** token.
3937 */
3938 char *db_fingerprint(int rcvid, int iVersion){
3939 char *z = 0;
3940 Blob sql = BLOB_INITIALIZER;
3941 Stmt q;
3942 if( iVersion==0 ){
3943 /* The original fingerprint algorithm used "quote(mtime)". But this
3944 ** could give slightly different answers depending on how the floating-
3945 ** point hardware is configured. For example, it gave different
3946 ** answers on native Linux versus running under valgrind. */
3947 blob_append_sql(&sql,
3948 "SELECT rcvid, quote(uid), quote(mtime), quote(nonce), quote(ipaddr)"
3949 " FROM rcvfrom"
3950 );
3951 }else{
3952 /* These days, we use "datetime(mtime)" for more consistent answers */
3953 blob_append_sql(&sql,
3954 "SELECT rcvid, quote(uid), datetime(mtime), quote(nonce), quote(ipaddr)"
3955 " FROM rcvfrom"
3956 );
3957 }
3958 if( rcvid<=0 ){
3959 blob_append_sql(&sql, " ORDER BY rcvid DESC LIMIT 1");
3960 }else{
3961 blob_append_sql(&sql, " WHERE rcvid=%d", rcvid);
3962 }
@@ -3963,30 +3975,31 @@
3975 }
3976
3977 /*
3978 ** COMMAND: test-fingerprint
3979 **
3980 ** Usage: %fossil test-fingerprint ?RCVID?
3981 **
3982 ** Display the repository fingerprint using the supplied RCVID or
3983 ** using the latest RCVID if not is given on the command line.
3984 ** Show both the legacy and the newer version of the fingerprint,
3985 ** and the currently stored fingerprint if there is one.
3986 */
3987 void test_fingerprint(void){
3988 int rcvid = 0;
 
 
 
 
 
3989 db_find_and_open_repository(OPEN_ANY_SCHEMA,0);
3990 if( g.argc==3 ){
3991 rcvid = atoi(g.argv[2]);
3992 }else if( g.argc!=2 ){
3993 fossil_fatal("wrong number of arguments");
3994 }
3995 fossil_print("legecy: %z\n", db_fingerprint(rcvid, 0));
3996 fossil_print("version-1: %z\n", db_fingerprint(rcvid, 1));
3997 if( g.localOpen ){
3998 fossil_print("localdb: %z\n", db_lget("fingerprint","(none)"));
3999 fossil_print("db_fingerprint_ok(): %d\n", db_fingerprint_ok());
4000 }
4001 }
4002
4003 /*
4004 ** Set the value of the "checkout" entry in the VVAR table.
4005 **
@@ -3996,11 +4009,11 @@
4009 char *z;
4010 db_lset_int("checkout", rid);
4011 z = db_text(0,"SELECT uuid FROM blob WHERE rid=%d",rid);
4012 db_lset("checkout-hash", z);
4013 fossil_free(z);
4014 z = db_fingerprint(0, 1);
4015 db_lset("fingerprint", z);
4016 fossil_free(z);
4017 }
4018
4019 /*
@@ -4018,11 +4031,18 @@
4031 if( zCkout==0 ){
4032 /* This is an older checkout that does not record a fingerprint.
4033 ** We have to assume everything is ok */
4034 return 2;
4035 }
4036 zRepo = db_fingerprint(atoi(zCkout), 1);
4037 rc = fossil_strcmp(zCkout,zRepo)==0;
 
4038 fossil_free(zRepo);
4039 /* If the initial test fails, try again using the older fingerprint
4040 ** algorithm */
4041 if( !rc ){
4042 zRepo = db_fingerprint(atoi(zCkout), 0);
4043 rc = fossil_strcmp(zCkout,zRepo)==0;
4044 fossil_free(zRepo);
4045 }
4046 fossil_free(zCkout);
4047 return rc;
4048 }
4049

Keyboard Shortcuts

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