Fossil SCM

Minor hardening against malformed and oversized deltas. Based on an off-list report from Dan Mestas.

stephan 2026-10-12 09:54 UTC trunk
Commit 76922609df651140e394b7786222ee9c5ec16cc5dad77dcedb36d552b41be890
+4 -4
--- src/delta.c
+++ src/delta.c
@@ -536,19 +536,19 @@
536536
return zDelta - zOrigDelta;
537537
}
538538
539539
/*
540540
** Return the size (in bytes) of the output from applying
541
-** a delta.
541
+** a delta or a negative value on error.
542542
**
543543
** This routine is provided so that an procedure that is able
544544
** to call delta_apply() can learn how much space is required
545
-** for the output and hence allocate nor more space that is really
545
+** for the output and hence allocate no more space than is really
546546
** needed.
547547
*/
548
-int delta_output_size(const char *zDelta, int lenDelta){
549
- int size;
548
+sqlite3_int64 delta_output_size(const char *zDelta, int lenDelta){
549
+ sqlite3_int64 size;
550550
size = getInt(&zDelta, &lenDelta);
551551
if( lenDelta<=0 || *zDelta!='\n' ){
552552
/* ERROR: size integer not terminated by "\n" */
553553
return -1;
554554
}
555555
--- src/delta.c
+++ src/delta.c
@@ -536,19 +536,19 @@
536 return zDelta - zOrigDelta;
537 }
538
539 /*
540 ** Return the size (in bytes) of the output from applying
541 ** a delta.
542 **
543 ** This routine is provided so that an procedure that is able
544 ** to call delta_apply() can learn how much space is required
545 ** for the output and hence allocate nor more space that is really
546 ** needed.
547 */
548 int delta_output_size(const char *zDelta, int lenDelta){
549 int size;
550 size = getInt(&zDelta, &lenDelta);
551 if( lenDelta<=0 || *zDelta!='\n' ){
552 /* ERROR: size integer not terminated by "\n" */
553 return -1;
554 }
555
--- src/delta.c
+++ src/delta.c
@@ -536,19 +536,19 @@
536 return zDelta - zOrigDelta;
537 }
538
539 /*
540 ** Return the size (in bytes) of the output from applying
541 ** a delta or a negative value on error.
542 **
543 ** This routine is provided so that an procedure that is able
544 ** to call delta_apply() can learn how much space is required
545 ** for the output and hence allocate no more space than is really
546 ** needed.
547 */
548 sqlite3_int64 delta_output_size(const char *zDelta, int lenDelta){
549 sqlite3_int64 size;
550 size = getInt(&zDelta, &lenDelta);
551 if( lenDelta<=0 || *zDelta!='\n' ){
552 /* ERROR: size integer not terminated by "\n" */
553 return -1;
554 }
555
+3 -2
--- src/deltacmd.c
+++ src/deltacmd.c
@@ -117,16 +117,17 @@
117117
** It works ok for pTarget and pOriginal to be the same blob.
118118
**
119119
** Return the length of the target. Return -1 if there is an error.
120120
*/
121121
int blob_delta_apply(Blob *pOriginal, Blob *pDelta, Blob *pTarget){
122
- int len, n;
122
+ int len;
123
+ sqlite3_int64 n;
123124
Blob out;
124125
125126
n = delta_output_size(blob_buffer(pDelta), blob_size(pDelta));
126127
blob_zero(&out);
127
- if( n<0 ) return -1;
128
+ if( n<0 || n>0x7fffffff ) return -1;
128129
blob_resize(&out, n);
129130
len = delta_apply(
130131
blob_buffer(pOriginal), blob_size(pOriginal),
131132
blob_buffer(pDelta), blob_size(pDelta),
132133
blob_buffer(&out));
133134
--- src/deltacmd.c
+++ src/deltacmd.c
@@ -117,16 +117,17 @@
117 ** It works ok for pTarget and pOriginal to be the same blob.
118 **
119 ** Return the length of the target. Return -1 if there is an error.
120 */
121 int blob_delta_apply(Blob *pOriginal, Blob *pDelta, Blob *pTarget){
122 int len, n;
 
123 Blob out;
124
125 n = delta_output_size(blob_buffer(pDelta), blob_size(pDelta));
126 blob_zero(&out);
127 if( n<0 ) return -1;
128 blob_resize(&out, n);
129 len = delta_apply(
130 blob_buffer(pOriginal), blob_size(pOriginal),
131 blob_buffer(pDelta), blob_size(pDelta),
132 blob_buffer(&out));
133
--- src/deltacmd.c
+++ src/deltacmd.c
@@ -117,16 +117,17 @@
117 ** It works ok for pTarget and pOriginal to be the same blob.
118 **
119 ** Return the length of the target. Return -1 if there is an error.
120 */
121 int blob_delta_apply(Blob *pOriginal, Blob *pDelta, Blob *pTarget){
122 int len;
123 sqlite3_int64 n;
124 Blob out;
125
126 n = delta_output_size(blob_buffer(pDelta), blob_size(pDelta));
127 blob_zero(&out);
128 if( n<0 || n>0x7fffffff ) return -1;
129 blob_resize(&out, n);
130 len = delta_apply(
131 blob_buffer(pOriginal), blob_size(pOriginal),
132 blob_buffer(pDelta), blob_size(pDelta),
133 blob_buffer(&out));
134
+14 -10
--- src/deltafunc.c
+++ src/deltafunc.c
@@ -64,13 +64,13 @@
6464
static void deltaApplyFunc(
6565
sqlite3_context *context,
6666
int argc,
6767
sqlite3_value **argv
6868
){
69
- const char *aOrig; int nOrig; /* The X input */
70
- const char *aDelta; int nDelta; /* The input delta (D) */
71
- char *aOut; int nOut, nOut2; /* The output */
69
+ const char *aOrig; int nOrig; /* The X input */
70
+ const char *aDelta; int nDelta; /* The input delta (D) */
71
+ char *aOut; sqlite3_int64 nOut; /* The output */
7272
7373
assert( argc==2 );
7474
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
7575
if( sqlite3_value_type(argv[1])==SQLITE_NULL ) return;
7676
nOrig = sqlite3_value_bytes(argv[0]);
@@ -82,20 +82,24 @@
8282
nOut = delta_output_size(aDelta, nDelta);
8383
if( nOut<0 ){
8484
sqlite3_result_error(context, "corrupt fossil delta", -1);
8585
return;
8686
}
87
- aOut = sqlite3_malloc64((sqlite3_int64)nOut+1);
87
+ if( nOut>0x7fffffff ){
88
+ sqlite3_result_error_toobig(context);
89
+ return;
90
+ }
91
+ aOut = sqlite3_malloc64(nOut+1);
8892
if( aOut==0 ){
8993
sqlite3_result_error_nomem(context);
9094
}else{
91
- nOut2 = delta_apply(aOrig, nOrig, aDelta, nDelta, aOut);
95
+ const int nOut2 = delta_apply(aOrig, nOrig, aDelta, nDelta, aOut);
9296
if( nOut2!=nOut ){
9397
sqlite3_free(aOut);
9498
sqlite3_result_error(context, "corrupt fossil delta", -1);
9599
}else{
96
- sqlite3_result_blob(context, aOut, nOut, sqlite3_free);
100
+ sqlite3_result_blob(context, aOut, nOut2, sqlite3_free);
97101
}
98102
}
99103
}
100104
101105
@@ -108,11 +112,11 @@
108112
sqlite3_context *context,
109113
int argc,
110114
sqlite3_value **argv
111115
){
112116
const char *aDelta; int nDelta; /* The input delta (D) */
113
- int nOut; /* Size of output */
117
+ sqlite3_int64 nOut; /* Size of output */
114118
assert( argc==1 );
115119
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
116120
nDelta = sqlite3_value_bytes(argv[0]);
117121
aDelta = (const char*)sqlite3_value_blob(argv[0]);
118122
@@ -120,11 +124,11 @@
120124
nOut = delta_output_size(aDelta, nDelta);
121125
if( nOut<0 ){
122126
sqlite3_result_error(context, "corrupt fossil delta", -1);
123127
return;
124128
}else{
125
- sqlite3_result_int(context, nOut);
129
+ sqlite3_result_int64(context, nOut);
126130
}
127131
}
128132
129133
/*****************************************************************************
130134
** Table-valued SQL function: delta_parse(DELTA)
@@ -368,16 +372,16 @@
368372
case DELTAPARSEVTAB_OP: {
369373
sqlite3_result_text(ctx, azOp[pCur->eOp], -1, SQLITE_STATIC);
370374
break;
371375
}
372376
case DELTAPARSEVTAB_A1: {
373
- sqlite3_result_int(ctx, pCur->a1);
377
+ sqlite3_result_int64(ctx, pCur->a1);
374378
break;
375379
}
376380
case DELTAPARSEVTAB_A2: {
377381
if( pCur->eOp==DELTAPARSE_OP_COPY ){
378
- sqlite3_result_int(ctx, pCur->a2);
382
+ sqlite3_result_int64(ctx, pCur->a2);
379383
}else if( pCur->eOp==DELTAPARSE_OP_INSERT ){
380384
if( (i64)pCur->a2 + (i64)pCur->a1 > pCur->nDelta ){
381385
sqlite3_result_zeroblob(ctx, pCur->a1);
382386
}else{
383387
sqlite3_result_blob(ctx, pCur->aDelta+pCur->a2, pCur->a1,
384388
--- src/deltafunc.c
+++ src/deltafunc.c
@@ -64,13 +64,13 @@
64 static void deltaApplyFunc(
65 sqlite3_context *context,
66 int argc,
67 sqlite3_value **argv
68 ){
69 const char *aOrig; int nOrig; /* The X input */
70 const char *aDelta; int nDelta; /* The input delta (D) */
71 char *aOut; int nOut, nOut2; /* The output */
72
73 assert( argc==2 );
74 if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
75 if( sqlite3_value_type(argv[1])==SQLITE_NULL ) return;
76 nOrig = sqlite3_value_bytes(argv[0]);
@@ -82,20 +82,24 @@
82 nOut = delta_output_size(aDelta, nDelta);
83 if( nOut<0 ){
84 sqlite3_result_error(context, "corrupt fossil delta", -1);
85 return;
86 }
87 aOut = sqlite3_malloc64((sqlite3_int64)nOut+1);
 
 
 
 
88 if( aOut==0 ){
89 sqlite3_result_error_nomem(context);
90 }else{
91 nOut2 = delta_apply(aOrig, nOrig, aDelta, nDelta, aOut);
92 if( nOut2!=nOut ){
93 sqlite3_free(aOut);
94 sqlite3_result_error(context, "corrupt fossil delta", -1);
95 }else{
96 sqlite3_result_blob(context, aOut, nOut, sqlite3_free);
97 }
98 }
99 }
100
101
@@ -108,11 +112,11 @@
108 sqlite3_context *context,
109 int argc,
110 sqlite3_value **argv
111 ){
112 const char *aDelta; int nDelta; /* The input delta (D) */
113 int nOut; /* Size of output */
114 assert( argc==1 );
115 if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
116 nDelta = sqlite3_value_bytes(argv[0]);
117 aDelta = (const char*)sqlite3_value_blob(argv[0]);
118
@@ -120,11 +124,11 @@
120 nOut = delta_output_size(aDelta, nDelta);
121 if( nOut<0 ){
122 sqlite3_result_error(context, "corrupt fossil delta", -1);
123 return;
124 }else{
125 sqlite3_result_int(context, nOut);
126 }
127 }
128
129 /*****************************************************************************
130 ** Table-valued SQL function: delta_parse(DELTA)
@@ -368,16 +372,16 @@
368 case DELTAPARSEVTAB_OP: {
369 sqlite3_result_text(ctx, azOp[pCur->eOp], -1, SQLITE_STATIC);
370 break;
371 }
372 case DELTAPARSEVTAB_A1: {
373 sqlite3_result_int(ctx, pCur->a1);
374 break;
375 }
376 case DELTAPARSEVTAB_A2: {
377 if( pCur->eOp==DELTAPARSE_OP_COPY ){
378 sqlite3_result_int(ctx, pCur->a2);
379 }else if( pCur->eOp==DELTAPARSE_OP_INSERT ){
380 if( (i64)pCur->a2 + (i64)pCur->a1 > pCur->nDelta ){
381 sqlite3_result_zeroblob(ctx, pCur->a1);
382 }else{
383 sqlite3_result_blob(ctx, pCur->aDelta+pCur->a2, pCur->a1,
384
--- src/deltafunc.c
+++ src/deltafunc.c
@@ -64,13 +64,13 @@
64 static void deltaApplyFunc(
65 sqlite3_context *context,
66 int argc,
67 sqlite3_value **argv
68 ){
69 const char *aOrig; int nOrig; /* The X input */
70 const char *aDelta; int nDelta; /* The input delta (D) */
71 char *aOut; sqlite3_int64 nOut; /* The output */
72
73 assert( argc==2 );
74 if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
75 if( sqlite3_value_type(argv[1])==SQLITE_NULL ) return;
76 nOrig = sqlite3_value_bytes(argv[0]);
@@ -82,20 +82,24 @@
82 nOut = delta_output_size(aDelta, nDelta);
83 if( nOut<0 ){
84 sqlite3_result_error(context, "corrupt fossil delta", -1);
85 return;
86 }
87 if( nOut>0x7fffffff ){
88 sqlite3_result_error_toobig(context);
89 return;
90 }
91 aOut = sqlite3_malloc64(nOut+1);
92 if( aOut==0 ){
93 sqlite3_result_error_nomem(context);
94 }else{
95 const int nOut2 = delta_apply(aOrig, nOrig, aDelta, nDelta, aOut);
96 if( nOut2!=nOut ){
97 sqlite3_free(aOut);
98 sqlite3_result_error(context, "corrupt fossil delta", -1);
99 }else{
100 sqlite3_result_blob(context, aOut, nOut2, sqlite3_free);
101 }
102 }
103 }
104
105
@@ -108,11 +112,11 @@
112 sqlite3_context *context,
113 int argc,
114 sqlite3_value **argv
115 ){
116 const char *aDelta; int nDelta; /* The input delta (D) */
117 sqlite3_int64 nOut; /* Size of output */
118 assert( argc==1 );
119 if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
120 nDelta = sqlite3_value_bytes(argv[0]);
121 aDelta = (const char*)sqlite3_value_blob(argv[0]);
122
@@ -120,11 +124,11 @@
124 nOut = delta_output_size(aDelta, nDelta);
125 if( nOut<0 ){
126 sqlite3_result_error(context, "corrupt fossil delta", -1);
127 return;
128 }else{
129 sqlite3_result_int64(context, nOut);
130 }
131 }
132
133 /*****************************************************************************
134 ** Table-valued SQL function: delta_parse(DELTA)
@@ -368,16 +372,16 @@
372 case DELTAPARSEVTAB_OP: {
373 sqlite3_result_text(ctx, azOp[pCur->eOp], -1, SQLITE_STATIC);
374 break;
375 }
376 case DELTAPARSEVTAB_A1: {
377 sqlite3_result_int64(ctx, pCur->a1);
378 break;
379 }
380 case DELTAPARSEVTAB_A2: {
381 if( pCur->eOp==DELTAPARSE_OP_COPY ){
382 sqlite3_result_int64(ctx, pCur->a2);
383 }else if( pCur->eOp==DELTAPARSE_OP_INSERT ){
384 if( (i64)pCur->a2 + (i64)pCur->a1 > pCur->nDelta ){
385 sqlite3_result_zeroblob(ctx, pCur->a1);
386 }else{
387 sqlite3_result_blob(ctx, pCur->aDelta+pCur->a2, pCur->a1,
388

Keyboard Shortcuts

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