Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | More work on making the xfer protocol fail fast for certain invalid inputs. |
|---|---|
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
f9f90d9b15cb3669d803d5ebf4e0726c |
| User & Date: | stephan 2024-09-24 11:13:20.464 |
Context
|
2024-09-24
| ||
| 18:05 | Fix a memleak in manifest_crosslink() when hooks are activated (one uuid leaked per checkin manifest). When posting a chat-robot message for a forum post, add links to the artifact and user's timeline to that message (as is done for checkins. check-in: 5fabb7ccb7 user: stephan tags: trunk | |
| 11:13 | More work on making the xfer protocol fail fast for certain invalid inputs. check-in: f9f90d9b15 user: stephan tags: trunk | |
|
2024-09-23
| ||
| 22:06 | Improve the validation of the sequence number in clone messages in the sync protocol. check-in: 295b396036 user: stephan tags: trunk | |
Changes
Changes to src/xfer.c.
| ︙ | ︙ | |||
334 335 336 337 338 339 340 341 342 343 344 345 346 347 |
pHash = &pXfer->aToken[3];
if( pXfer->nToken==5
|| !blob_is_filename(&pXfer->aToken[1])
|| !blob_is_int64(&pXfer->aToken[2], &mtime)
|| (!blob_eq(pHash,"-") && !blob_is_hname(pHash))
|| !blob_is_int(&pXfer->aToken[4], &sz)
|| !blob_is_int(&pXfer->aToken[5], &flags)
){
blob_appendf(&pXfer->err, "malformed uvfile line");
return;
}
blob_init(&content, 0, 0);
blob_init(&x, 0, 0);
if( sz>0 && (flags & 0x0005)==0 ){
| > | 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
pHash = &pXfer->aToken[3];
if( pXfer->nToken==5
|| !blob_is_filename(&pXfer->aToken[1])
|| !blob_is_int64(&pXfer->aToken[2], &mtime)
|| (!blob_eq(pHash,"-") && !blob_is_hname(pHash))
|| !blob_is_int(&pXfer->aToken[4], &sz)
|| !blob_is_int(&pXfer->aToken[5], &flags)
|| (mtime<0 || sz<0 || flags<0)
){
blob_appendf(&pXfer->err, "malformed uvfile line");
return;
}
blob_init(&content, 0, 0);
blob_init(&x, 0, 0);
if( sz>0 && (flags & 0x0005)==0 ){
|
| ︙ | ︙ | |||
1120 1121 1122 1123 1124 1125 1126 |
*/
const char *xfer_ticket_code(void){
return db_get("xfer-ticket-script", 0);
}
/*
** Reset the CGI content, roll back any pending db transaction, and
| | | > | | | | 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 |
*/
const char *xfer_ticket_code(void){
return db_get("xfer-ticket-script", 0);
}
/*
** Reset the CGI content, roll back any pending db transaction, and
** emit an "error" xfer message. The message text gets fossil-encoded
** by this function. This is only intended for use with
** fail-fast/fatal errors, not ones which can be skipped over.
*/
static void xfer_fatal_error(const char *zMsg){
cgi_reset_content();
if( db_transaction_nesting_depth()>0 ){
db_rollback_transaction();
}
@ error %F(zMsg)
}
/*
** Run the specified TH1 script, if any, and returns 1 on error.
*/
int xfer_run_script(
const char *zScript,
|
| ︙ | ︙ | |||
1473 1474 1475 1476 1477 1478 1479 |
){
int seqno, max;
if( iVers>=3 ){
cgi_set_content_type("application/x-fossil-uncompressed");
}
blob_is_int(&xfer.aToken[2], &seqno);
if( seqno<=0 ){
| | | 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 |
){
int seqno, max;
if( iVers>=3 ){
cgi_set_content_type("application/x-fossil-uncompressed");
}
blob_is_int(&xfer.aToken[2], &seqno);
if( seqno<=0 ){
xfer_fatal_error("invalid clone sequence number");
return;
}
max = db_int(0, "SELECT max(rid) FROM blob");
while( xfer.mxSend>(int)blob_size(xfer.pOut) && seqno<=max){
if( time(NULL) >= xfer.maxTime ) break;
if( iVers>=3 ){
send_compressed_file(&xfer, seqno);
|
| ︙ | ︙ | |||
1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 |
** Client has sent a configuration value to the server.
** This is only permitted for high-privilege users.
*/
if( blob_eq(&xfer.aToken[0],"config") && xfer.nToken==3
&& blob_is_int(&xfer.aToken[2], &size) ){
const char *zName = blob_str(&xfer.aToken[1]);
Blob content;
blob_zero(&content);
blob_extract(xfer.pIn, size, &content);
if( !g.perm.Admin ){
cgi_reset_content();
@ error not\sauthorized\sto\spush\sconfiguration
nErr++;
break;
| > > > > | 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 |
** Client has sent a configuration value to the server.
** This is only permitted for high-privilege users.
*/
if( blob_eq(&xfer.aToken[0],"config") && xfer.nToken==3
&& blob_is_int(&xfer.aToken[2], &size) ){
const char *zName = blob_str(&xfer.aToken[1]);
Blob content;
if( size<0 ){
xfer_fatal_error("invalid config record");
return;
}
blob_zero(&content);
blob_extract(xfer.pIn, size, &content);
if( !g.perm.Admin ){
cgi_reset_content();
@ error not\sauthorized\sto\spush\sconfiguration
nErr++;
break;
|
| ︙ | ︙ | |||
2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 |
&& blob_is_int64(&xfer.aToken[2], &mtime)
&& blob_is_int(&xfer.aToken[4], &size)
&& (blob_eq(&xfer.aToken[3],"-") || blob_is_hname(&xfer.aToken[3]))
){
const char *zName = blob_str(&xfer.aToken[1]);
const char *zHash = blob_str(&xfer.aToken[3]);
int iStatus;
iStatus = unversioned_status(zName, mtime, zHash);
if( (syncFlags & SYNC_UV_REVERT)!=0 ){
if( iStatus==4 ) iStatus = 2;
if( iStatus==5 ) iStatus = 1;
}
if( syncFlags & (SYNC_UV_TRACE|SYNC_UV_DRYRUN) ){
const char *zMsg = 0;
| > > > > | 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 |
&& blob_is_int64(&xfer.aToken[2], &mtime)
&& blob_is_int(&xfer.aToken[4], &size)
&& (blob_eq(&xfer.aToken[3],"-") || blob_is_hname(&xfer.aToken[3]))
){
const char *zName = blob_str(&xfer.aToken[1]);
const char *zHash = blob_str(&xfer.aToken[3]);
int iStatus;
if( mtime<0 || size<0 ){
xfer_fatal_error("invalid uvigot");
return ++nErr;
}
iStatus = unversioned_status(zName, mtime, zHash);
if( (syncFlags & SYNC_UV_REVERT)!=0 ){
if( iStatus==4 ) iStatus = 2;
if( iStatus==5 ) iStatus = 1;
}
if( syncFlags & (SYNC_UV_TRACE|SYNC_UV_DRYRUN) ){
const char *zMsg = 0;
|
| ︙ | ︙ | |||
2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 |
** The received configuration setting is silently ignored if it was
** not requested by a prior "reqconfig" sent from client to server.
*/
if( blob_eq(&xfer.aToken[0],"config") && xfer.nToken==3
&& blob_is_int(&xfer.aToken[2], &size) ){
const char *zName = blob_str(&xfer.aToken[1]);
Blob content;
blob_zero(&content);
blob_extract(xfer.pIn, size, &content);
g.perm.Admin = g.perm.RdAddr = 1;
configure_receive(zName, &content, origConfigRcvMask);
nCardRcvd++;
nArtifactRcvd++;
blob_reset(&content);
| > > > > | 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 |
** The received configuration setting is silently ignored if it was
** not requested by a prior "reqconfig" sent from client to server.
*/
if( blob_eq(&xfer.aToken[0],"config") && xfer.nToken==3
&& blob_is_int(&xfer.aToken[2], &size) ){
const char *zName = blob_str(&xfer.aToken[1]);
Blob content;
if( size<0 ){
xfer_fatal_error("invalid config record");
return ++nErr;
}
blob_zero(&content);
blob_extract(xfer.pIn, size, &content);
g.perm.Admin = g.perm.RdAddr = 1;
configure_receive(zName, &content, origConfigRcvMask);
nCardRcvd++;
nArtifactRcvd++;
blob_reset(&content);
|
| ︙ | ︙ | |||
2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 |
** When doing a clone, the server tries to send all of its artifacts
** in sequence. This card indicates the sequence number of the next
** blob that needs to be sent. If N<=0 that indicates that all blobs
** have been sent.
*/
if( blob_eq(&xfer.aToken[0], "clone_seqno") && xfer.nToken==2 ){
blob_is_int(&xfer.aToken[1], &cloneSeqno);
}else
/* message MESSAGE
**
** A message is received from the server. Print it.
** Similar to "error" but does not stop processing.
**
| > > > > | 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 |
** When doing a clone, the server tries to send all of its artifacts
** in sequence. This card indicates the sequence number of the next
** blob that needs to be sent. If N<=0 that indicates that all blobs
** have been sent.
*/
if( blob_eq(&xfer.aToken[0], "clone_seqno") && xfer.nToken==2 ){
blob_is_int(&xfer.aToken[1], &cloneSeqno);
if( cloneSeqno<0 ){
xfer_fatal_error("invalid clone_seqno");
return ++nErr;
}
}else
/* message MESSAGE
**
** A message is received from the server. Print it.
** Similar to "error" but does not stop processing.
**
|
| ︙ | ︙ | |||
2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 |
*/
else if( blob_eq(&xfer.aToken[1], "ci-lock-fail") && xfer.nToken==4 ){
char *zUser = blob_terminate(&xfer.aToken[2]);
sqlite3_int64 mtime, iNow;
defossilize(zUser);
iNow = time(NULL);
if( blob_is_int64(&xfer.aToken[3], &mtime) && iNow>mtime ){
iNow = time(NULL);
fossil_print("\nParent check-in locked by %s %s ago\n",
zUser, human_readable_age((iNow+1-mtime)/86400.0));
}else{
fossil_print("\nParent check-in locked by %s\n", zUser);
}
g.ckinLockFail = fossil_strdup(zUser);
| > > > > | 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 |
*/
else if( blob_eq(&xfer.aToken[1], "ci-lock-fail") && xfer.nToken==4 ){
char *zUser = blob_terminate(&xfer.aToken[2]);
sqlite3_int64 mtime, iNow;
defossilize(zUser);
iNow = time(NULL);
if( blob_is_int64(&xfer.aToken[3], &mtime) && iNow>mtime ){
if( mtime<0 ){
xfer_fatal_error("invalid ci-lock-fail time");
return ++nErr;
}
iNow = time(NULL);
fossil_print("\nParent check-in locked by %s %s ago\n",
zUser, human_readable_age((iNow+1-mtime)/86400.0));
}else{
fossil_print("\nParent check-in locked by %s\n", zUser);
}
g.ckinLockFail = fossil_strdup(zUser);
|
| ︙ | ︙ |