Fossil SCM
Do extra error checking to determine that a sync target given as a filename is a valid Fossil repository. Issue a better error message if it is not.
Commit
31361e328f89cbd7da6584f7cf131018078d6ae3cd86f9a8ce73521e00eb3b28
Parent
c129f29566439e5…
2 files changed
+52
-1
+3
M
src/db.c
+52
-1
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -2125,26 +2125,77 @@ | ||
| 2125 | 2125 | ** Returns non-zero if support for symlinks is currently enabled. |
| 2126 | 2126 | */ |
| 2127 | 2127 | int db_allow_symlinks(void){ |
| 2128 | 2128 | return g.allowSymlinks; |
| 2129 | 2129 | } |
| 2130 | + | |
| 2131 | +/* | |
| 2132 | +** Return TRUE if the file in the argument seems like it might be an | |
| 2133 | +** SQLite database file that contains a Fossil repository schema. | |
| 2134 | +*/ | |
| 2135 | +int db_looks_like_a_repository(const char *zDbName){ | |
| 2136 | + sqlite3 *db = 0; | |
| 2137 | + i64 sz; | |
| 2138 | + int rc; | |
| 2139 | + int res = 0; | |
| 2140 | + sqlite3_stmt *pStmt = 0; | |
| 2141 | + | |
| 2142 | + sz = file_size(zDbName, ExtFILE); | |
| 2143 | + if( sz<16834 ) return 0; | |
| 2144 | + if( sz & 0x1ff ) return 0; | |
| 2145 | + rc = sqlite3_open(zDbName, &db); | |
| 2146 | + if( rc ) goto is_repo_end; | |
| 2147 | + rc = sqlite3_prepare_v2(db, | |
| 2148 | + "SELECT count(*) FROM sqlite_schema" | |
| 2149 | + " WHERE name COLLATE nocase IN" | |
| 2150 | + "('blob','delta','rcvfrom','user','config','mlink','plink');", | |
| 2151 | + -1, &pStmt, 0); | |
| 2152 | + if( rc ) goto is_repo_end; | |
| 2153 | + rc = sqlite3_step(pStmt); | |
| 2154 | + if( rc!=SQLITE_ROW ) goto is_repo_end; | |
| 2155 | + if( sqlite3_column_int(pStmt, 0)!=7 ) goto is_repo_end; | |
| 2156 | + res = 1; | |
| 2157 | + | |
| 2158 | +is_repo_end: | |
| 2159 | + sqlite3_finalize(pStmt); | |
| 2160 | + sqlite3_close(db); | |
| 2161 | + return res; | |
| 2162 | +} | |
| 2163 | + | |
| 2164 | +/* | |
| 2165 | +** COMMAND: test-is-repo | |
| 2166 | +*/ | |
| 2167 | +void test_is_repo(void){ | |
| 2168 | + int i; | |
| 2169 | + for(i=2; i<g.argc; i++){ | |
| 2170 | + fossil_print("%s: %s\n", | |
| 2171 | + db_looks_like_a_repository(g.argv[i]) ? "yes" : " no", | |
| 2172 | + g.argv[i] | |
| 2173 | + ); | |
| 2174 | + } | |
| 2175 | +} | |
| 2176 | + | |
| 2130 | 2177 | |
| 2131 | 2178 | /* |
| 2132 | 2179 | ** Open the repository database given by zDbName. If zDbName==NULL then |
| 2133 | 2180 | ** get the name from the already open local database. |
| 2134 | 2181 | */ |
| 2135 | 2182 | void db_open_repository(const char *zDbName){ |
| 2183 | + i64 sz; | |
| 2136 | 2184 | if( g.repositoryOpen ) return; |
| 2137 | 2185 | if( zDbName==0 ){ |
| 2138 | 2186 | if( g.localOpen ){ |
| 2139 | 2187 | zDbName = db_repository_filename(); |
| 2140 | 2188 | } |
| 2141 | 2189 | if( zDbName==0 ){ |
| 2142 | 2190 | db_err("unable to find the name of a repository database"); |
| 2143 | 2191 | } |
| 2144 | 2192 | } |
| 2145 | - if( file_access(zDbName, R_OK) || file_size(zDbName, ExtFILE)<1024 ){ | |
| 2193 | + if( file_access(zDbName, R_OK) | |
| 2194 | + || (sz = file_size(zDbName, ExtFILE))<16384 | |
| 2195 | + || (sz&0x1ff)!=0 | |
| 2196 | + ){ | |
| 2146 | 2197 | if( file_access(zDbName, F_OK) ){ |
| 2147 | 2198 | #ifdef FOSSIL_ENABLE_JSON |
| 2148 | 2199 | g.json.resultCode = FSL_JSON_E_DB_NOT_FOUND; |
| 2149 | 2200 | #endif |
| 2150 | 2201 | fossil_fatal("repository does not exist or" |
| 2151 | 2202 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -2125,26 +2125,77 @@ | |
| 2125 | ** Returns non-zero if support for symlinks is currently enabled. |
| 2126 | */ |
| 2127 | int db_allow_symlinks(void){ |
| 2128 | return g.allowSymlinks; |
| 2129 | } |
| 2130 | |
| 2131 | /* |
| 2132 | ** Open the repository database given by zDbName. If zDbName==NULL then |
| 2133 | ** get the name from the already open local database. |
| 2134 | */ |
| 2135 | void db_open_repository(const char *zDbName){ |
| 2136 | if( g.repositoryOpen ) return; |
| 2137 | if( zDbName==0 ){ |
| 2138 | if( g.localOpen ){ |
| 2139 | zDbName = db_repository_filename(); |
| 2140 | } |
| 2141 | if( zDbName==0 ){ |
| 2142 | db_err("unable to find the name of a repository database"); |
| 2143 | } |
| 2144 | } |
| 2145 | if( file_access(zDbName, R_OK) || file_size(zDbName, ExtFILE)<1024 ){ |
| 2146 | if( file_access(zDbName, F_OK) ){ |
| 2147 | #ifdef FOSSIL_ENABLE_JSON |
| 2148 | g.json.resultCode = FSL_JSON_E_DB_NOT_FOUND; |
| 2149 | #endif |
| 2150 | fossil_fatal("repository does not exist or" |
| 2151 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -2125,26 +2125,77 @@ | |
| 2125 | ** Returns non-zero if support for symlinks is currently enabled. |
| 2126 | */ |
| 2127 | int db_allow_symlinks(void){ |
| 2128 | return g.allowSymlinks; |
| 2129 | } |
| 2130 | |
| 2131 | /* |
| 2132 | ** Return TRUE if the file in the argument seems like it might be an |
| 2133 | ** SQLite database file that contains a Fossil repository schema. |
| 2134 | */ |
| 2135 | int db_looks_like_a_repository(const char *zDbName){ |
| 2136 | sqlite3 *db = 0; |
| 2137 | i64 sz; |
| 2138 | int rc; |
| 2139 | int res = 0; |
| 2140 | sqlite3_stmt *pStmt = 0; |
| 2141 | |
| 2142 | sz = file_size(zDbName, ExtFILE); |
| 2143 | if( sz<16834 ) return 0; |
| 2144 | if( sz & 0x1ff ) return 0; |
| 2145 | rc = sqlite3_open(zDbName, &db); |
| 2146 | if( rc ) goto is_repo_end; |
| 2147 | rc = sqlite3_prepare_v2(db, |
| 2148 | "SELECT count(*) FROM sqlite_schema" |
| 2149 | " WHERE name COLLATE nocase IN" |
| 2150 | "('blob','delta','rcvfrom','user','config','mlink','plink');", |
| 2151 | -1, &pStmt, 0); |
| 2152 | if( rc ) goto is_repo_end; |
| 2153 | rc = sqlite3_step(pStmt); |
| 2154 | if( rc!=SQLITE_ROW ) goto is_repo_end; |
| 2155 | if( sqlite3_column_int(pStmt, 0)!=7 ) goto is_repo_end; |
| 2156 | res = 1; |
| 2157 | |
| 2158 | is_repo_end: |
| 2159 | sqlite3_finalize(pStmt); |
| 2160 | sqlite3_close(db); |
| 2161 | return res; |
| 2162 | } |
| 2163 | |
| 2164 | /* |
| 2165 | ** COMMAND: test-is-repo |
| 2166 | */ |
| 2167 | void test_is_repo(void){ |
| 2168 | int i; |
| 2169 | for(i=2; i<g.argc; i++){ |
| 2170 | fossil_print("%s: %s\n", |
| 2171 | db_looks_like_a_repository(g.argv[i]) ? "yes" : " no", |
| 2172 | g.argv[i] |
| 2173 | ); |
| 2174 | } |
| 2175 | } |
| 2176 | |
| 2177 | |
| 2178 | /* |
| 2179 | ** Open the repository database given by zDbName. If zDbName==NULL then |
| 2180 | ** get the name from the already open local database. |
| 2181 | */ |
| 2182 | void db_open_repository(const char *zDbName){ |
| 2183 | i64 sz; |
| 2184 | if( g.repositoryOpen ) return; |
| 2185 | if( zDbName==0 ){ |
| 2186 | if( g.localOpen ){ |
| 2187 | zDbName = db_repository_filename(); |
| 2188 | } |
| 2189 | if( zDbName==0 ){ |
| 2190 | db_err("unable to find the name of a repository database"); |
| 2191 | } |
| 2192 | } |
| 2193 | if( file_access(zDbName, R_OK) |
| 2194 | || (sz = file_size(zDbName, ExtFILE))<16384 |
| 2195 | || (sz&0x1ff)!=0 |
| 2196 | ){ |
| 2197 | if( file_access(zDbName, F_OK) ){ |
| 2198 | #ifdef FOSSIL_ENABLE_JSON |
| 2199 | g.json.resultCode = FSL_JSON_E_DB_NOT_FOUND; |
| 2200 | #endif |
| 2201 | fossil_fatal("repository does not exist or" |
| 2202 |
+3
| --- src/http_transport.c | ||
| +++ src/http_transport.c | ||
| @@ -178,10 +178,13 @@ | ||
| 178 | 178 | socket_set_errmsg("HTTPS: Fossil has been compiled without SSL support"); |
| 179 | 179 | rc = 1; |
| 180 | 180 | #endif |
| 181 | 181 | }else if( pUrlData->isFile ){ |
| 182 | 182 | sqlite3_uint64 iRandId; |
| 183 | + if( !db_looks_like_a_repository(pUrlData->name) ){ | |
| 184 | + fossil_fatal("not a fossil repository: \"%s\"", pUrlData->name); | |
| 185 | + } | |
| 183 | 186 | sqlite3_randomness(sizeof(iRandId), &iRandId); |
| 184 | 187 | transport.zOutFile = mprintf("%s-%llu-out.http", |
| 185 | 188 | g.zRepositoryName, iRandId); |
| 186 | 189 | transport.zInFile = mprintf("%s-%llu-in.http", |
| 187 | 190 | g.zRepositoryName, iRandId); |
| 188 | 191 |
| --- src/http_transport.c | |
| +++ src/http_transport.c | |
| @@ -178,10 +178,13 @@ | |
| 178 | socket_set_errmsg("HTTPS: Fossil has been compiled without SSL support"); |
| 179 | rc = 1; |
| 180 | #endif |
| 181 | }else if( pUrlData->isFile ){ |
| 182 | sqlite3_uint64 iRandId; |
| 183 | sqlite3_randomness(sizeof(iRandId), &iRandId); |
| 184 | transport.zOutFile = mprintf("%s-%llu-out.http", |
| 185 | g.zRepositoryName, iRandId); |
| 186 | transport.zInFile = mprintf("%s-%llu-in.http", |
| 187 | g.zRepositoryName, iRandId); |
| 188 |
| --- src/http_transport.c | |
| +++ src/http_transport.c | |
| @@ -178,10 +178,13 @@ | |
| 178 | socket_set_errmsg("HTTPS: Fossil has been compiled without SSL support"); |
| 179 | rc = 1; |
| 180 | #endif |
| 181 | }else if( pUrlData->isFile ){ |
| 182 | sqlite3_uint64 iRandId; |
| 183 | if( !db_looks_like_a_repository(pUrlData->name) ){ |
| 184 | fossil_fatal("not a fossil repository: \"%s\"", pUrlData->name); |
| 185 | } |
| 186 | sqlite3_randomness(sizeof(iRandId), &iRandId); |
| 187 | transport.zOutFile = mprintf("%s-%llu-out.http", |
| 188 | g.zRepositoryName, iRandId); |
| 189 | transport.zInFile = mprintf("%s-%llu-in.http", |
| 190 | g.zRepositoryName, iRandId); |
| 191 |