Fossil SCM

Add checks to ensure that Blob allocation sizes are within a legal max range, failing if they're too big, to address 'uv add' misbehavior reported in [forum:d5cd3e3c19|forum post d5cd3e3c19].

stephan 2023-06-22 10:47 trunk
Commit 6efd41941ced78c5f34ea2c141c400f409ca0207f7a611b971eda31e96625438
1 file changed +30 -12
+30 -12
--- src/blob.c
+++ src/blob.c
@@ -175,10 +175,27 @@
175175
static void blob_panic(void){
176176
static const char zErrMsg[] = "out of memory\n";
177177
fputs(zErrMsg, stderr);
178178
fossil_exit(1);
179179
}
180
+
181
+/*
182
+** Maximum size of a Blob's managed memory. This is ~2GB, largely for
183
+** historical reasons.
184
+**
185
+*/
186
+#define MAX_BLOB_SIZE 0x7fff000
187
+
188
+/*
189
+** If n >= MAX_BLOB_SIZE, calls blob_panic(),
190
+** else this is a no-op.
191
+*/
192
+static void blob_assert_safe_size(i64 n){
193
+ if( n>=(i64)MAX_BLOB_SIZE ){
194
+ blob_panic();
195
+ }
196
+}
180197
181198
/*
182199
** A reallocation function that assumes that aData came from malloc().
183200
** This function attempts to resize the buffer of the blob to hold
184201
** newSize bytes.
@@ -194,11 +211,13 @@
194211
pBlob->nAlloc = 0;
195212
pBlob->nUsed = 0;
196213
pBlob->iCursor = 0;
197214
pBlob->blobFlags = 0;
198215
}else if( newSize>pBlob->nAlloc || newSize+4000<pBlob->nAlloc ){
199
- char *pNew = fossil_realloc(pBlob->aData, newSize);
216
+ char *pNew;
217
+ blob_assert_safe_size((i64)newSize);
218
+ pNew = fossil_realloc(pBlob->aData, newSize);
200219
pBlob->aData = pNew;
201220
pBlob->nAlloc = newSize;
202221
if( pBlob->nUsed>pBlob->nAlloc ){
203222
pBlob->nUsed = pBlob->nAlloc;
204223
}
@@ -219,11 +238,13 @@
219238
*/
220239
static void blobReallocStatic(Blob *pBlob, unsigned int newSize){
221240
if( newSize==0 ){
222241
*pBlob = empty_blob;
223242
}else{
224
- char *pNew = fossil_malloc( newSize );
243
+ char *pNew;
244
+ blob_assert_safe_size((i64)newSize);
245
+ pNew = fossil_malloc( newSize );
225246
if( pBlob->nUsed>newSize ) pBlob->nUsed = newSize;
226247
memcpy(pNew, pBlob->aData, pBlob->nUsed);
227248
pBlob->aData = pNew;
228249
pBlob->xRealloc = blobReallocMalloc;
229250
pBlob->nAlloc = newSize;
@@ -329,14 +350,12 @@
329350
nNew = pBlob->nUsed;
330351
nNew += nData;
331352
if( nNew >= pBlob->nAlloc ){
332353
nNew += pBlob->nAlloc;
333354
nNew += 100;
334
- if( nNew>=0x7fff0000 ){
335
- blob_panic();
336
- }
337
- pBlob->xRealloc(pBlob, (int)nNew);
355
+ blob_assert_safe_size(nNew);
356
+ pBlob->xRealloc(pBlob, (unsigned)nNew);
338357
if( pBlob->nUsed + nData >= pBlob->nAlloc ){
339358
blob_panic();
340359
}
341360
}
342361
memcpy(&pBlob->aData[pBlob->nUsed], aData, nData);
@@ -605,23 +624,22 @@
605624
** Ensures that the given blob has at least the given amount of memory
606625
** allocated to it. Does not modify pBlob->nUsed nor will it reduce
607626
** the currently-allocated amount of memory.
608627
**
609628
** For semantic compatibility with blob_append_full(), if newSize is
610
-** >=0x7fff000 (~2GB) then this function will trigger blob_panic(). If
611
-** it didn't, it would be possible to bypass that hard-coded limit via
629
+** >=MAX_BLOB_SIZE then this function will trigger blob_panic(). If it
630
+** didn't, it would be possible to bypass that hard-coded limit via
612631
** this function.
613632
**
614633
** We've had at least one report:
615634
** https://fossil-scm.org/forum/forumpost/b7bbd28db4
616635
** which implies that this is unconditionally failing on mingw 32-bit
617636
** builds.
618637
*/
619638
void blob_reserve(Blob *pBlob, unsigned int newSize){
620
- if(newSize>=0x7fff0000 ){
621
- blob_panic();
622
- }else if(newSize>pBlob->nAlloc){
639
+ blob_assert_safe_size( (i64)newSize );
640
+ if(newSize>pBlob->nAlloc){
623641
pBlob->xRealloc(pBlob, newSize+1);
624642
pBlob->aData[newSize] = 0;
625643
}
626644
}
627645
@@ -919,11 +937,11 @@
919937
memset(&dCfg, 0, sizeof(dCfg));
920938
921939
sbs = find_option("side-by-side","y",0)!=0;
922940
if( (z = find_option("width","W",1))!=0 && (w = atoi(z))>0 ){
923941
dCfg.wColumn = w;
924
- }
942
+ }
925943
verify_all_options();
926944
if( g.argc!=3 ) usage("INPUTFILE");
927945
928946
blob_read_from_file(&f, g.argv[2], ExtFILE);
929947
blob_strip_comment_lines(&f, &h);
930948
--- src/blob.c
+++ src/blob.c
@@ -175,10 +175,27 @@
175 static void blob_panic(void){
176 static const char zErrMsg[] = "out of memory\n";
177 fputs(zErrMsg, stderr);
178 fossil_exit(1);
179 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
181 /*
182 ** A reallocation function that assumes that aData came from malloc().
183 ** This function attempts to resize the buffer of the blob to hold
184 ** newSize bytes.
@@ -194,11 +211,13 @@
194 pBlob->nAlloc = 0;
195 pBlob->nUsed = 0;
196 pBlob->iCursor = 0;
197 pBlob->blobFlags = 0;
198 }else if( newSize>pBlob->nAlloc || newSize+4000<pBlob->nAlloc ){
199 char *pNew = fossil_realloc(pBlob->aData, newSize);
 
 
200 pBlob->aData = pNew;
201 pBlob->nAlloc = newSize;
202 if( pBlob->nUsed>pBlob->nAlloc ){
203 pBlob->nUsed = pBlob->nAlloc;
204 }
@@ -219,11 +238,13 @@
219 */
220 static void blobReallocStatic(Blob *pBlob, unsigned int newSize){
221 if( newSize==0 ){
222 *pBlob = empty_blob;
223 }else{
224 char *pNew = fossil_malloc( newSize );
 
 
225 if( pBlob->nUsed>newSize ) pBlob->nUsed = newSize;
226 memcpy(pNew, pBlob->aData, pBlob->nUsed);
227 pBlob->aData = pNew;
228 pBlob->xRealloc = blobReallocMalloc;
229 pBlob->nAlloc = newSize;
@@ -329,14 +350,12 @@
329 nNew = pBlob->nUsed;
330 nNew += nData;
331 if( nNew >= pBlob->nAlloc ){
332 nNew += pBlob->nAlloc;
333 nNew += 100;
334 if( nNew>=0x7fff0000 ){
335 blob_panic();
336 }
337 pBlob->xRealloc(pBlob, (int)nNew);
338 if( pBlob->nUsed + nData >= pBlob->nAlloc ){
339 blob_panic();
340 }
341 }
342 memcpy(&pBlob->aData[pBlob->nUsed], aData, nData);
@@ -605,23 +624,22 @@
605 ** Ensures that the given blob has at least the given amount of memory
606 ** allocated to it. Does not modify pBlob->nUsed nor will it reduce
607 ** the currently-allocated amount of memory.
608 **
609 ** For semantic compatibility with blob_append_full(), if newSize is
610 ** >=0x7fff000 (~2GB) then this function will trigger blob_panic(). If
611 ** it didn't, it would be possible to bypass that hard-coded limit via
612 ** this function.
613 **
614 ** We've had at least one report:
615 ** https://fossil-scm.org/forum/forumpost/b7bbd28db4
616 ** which implies that this is unconditionally failing on mingw 32-bit
617 ** builds.
618 */
619 void blob_reserve(Blob *pBlob, unsigned int newSize){
620 if(newSize>=0x7fff0000 ){
621 blob_panic();
622 }else if(newSize>pBlob->nAlloc){
623 pBlob->xRealloc(pBlob, newSize+1);
624 pBlob->aData[newSize] = 0;
625 }
626 }
627
@@ -919,11 +937,11 @@
919 memset(&dCfg, 0, sizeof(dCfg));
920
921 sbs = find_option("side-by-side","y",0)!=0;
922 if( (z = find_option("width","W",1))!=0 && (w = atoi(z))>0 ){
923 dCfg.wColumn = w;
924 }
925 verify_all_options();
926 if( g.argc!=3 ) usage("INPUTFILE");
927
928 blob_read_from_file(&f, g.argv[2], ExtFILE);
929 blob_strip_comment_lines(&f, &h);
930
--- src/blob.c
+++ src/blob.c
@@ -175,10 +175,27 @@
175 static void blob_panic(void){
176 static const char zErrMsg[] = "out of memory\n";
177 fputs(zErrMsg, stderr);
178 fossil_exit(1);
179 }
180
181 /*
182 ** Maximum size of a Blob's managed memory. This is ~2GB, largely for
183 ** historical reasons.
184 **
185 */
186 #define MAX_BLOB_SIZE 0x7fff000
187
188 /*
189 ** If n >= MAX_BLOB_SIZE, calls blob_panic(),
190 ** else this is a no-op.
191 */
192 static void blob_assert_safe_size(i64 n){
193 if( n>=(i64)MAX_BLOB_SIZE ){
194 blob_panic();
195 }
196 }
197
198 /*
199 ** A reallocation function that assumes that aData came from malloc().
200 ** This function attempts to resize the buffer of the blob to hold
201 ** newSize bytes.
@@ -194,11 +211,13 @@
211 pBlob->nAlloc = 0;
212 pBlob->nUsed = 0;
213 pBlob->iCursor = 0;
214 pBlob->blobFlags = 0;
215 }else if( newSize>pBlob->nAlloc || newSize+4000<pBlob->nAlloc ){
216 char *pNew;
217 blob_assert_safe_size((i64)newSize);
218 pNew = fossil_realloc(pBlob->aData, newSize);
219 pBlob->aData = pNew;
220 pBlob->nAlloc = newSize;
221 if( pBlob->nUsed>pBlob->nAlloc ){
222 pBlob->nUsed = pBlob->nAlloc;
223 }
@@ -219,11 +238,13 @@
238 */
239 static void blobReallocStatic(Blob *pBlob, unsigned int newSize){
240 if( newSize==0 ){
241 *pBlob = empty_blob;
242 }else{
243 char *pNew;
244 blob_assert_safe_size((i64)newSize);
245 pNew = fossil_malloc( newSize );
246 if( pBlob->nUsed>newSize ) pBlob->nUsed = newSize;
247 memcpy(pNew, pBlob->aData, pBlob->nUsed);
248 pBlob->aData = pNew;
249 pBlob->xRealloc = blobReallocMalloc;
250 pBlob->nAlloc = newSize;
@@ -329,14 +350,12 @@
350 nNew = pBlob->nUsed;
351 nNew += nData;
352 if( nNew >= pBlob->nAlloc ){
353 nNew += pBlob->nAlloc;
354 nNew += 100;
355 blob_assert_safe_size(nNew);
356 pBlob->xRealloc(pBlob, (unsigned)nNew);
 
 
357 if( pBlob->nUsed + nData >= pBlob->nAlloc ){
358 blob_panic();
359 }
360 }
361 memcpy(&pBlob->aData[pBlob->nUsed], aData, nData);
@@ -605,23 +624,22 @@
624 ** Ensures that the given blob has at least the given amount of memory
625 ** allocated to it. Does not modify pBlob->nUsed nor will it reduce
626 ** the currently-allocated amount of memory.
627 **
628 ** For semantic compatibility with blob_append_full(), if newSize is
629 ** >=MAX_BLOB_SIZE then this function will trigger blob_panic(). If it
630 ** didn't, it would be possible to bypass that hard-coded limit via
631 ** this function.
632 **
633 ** We've had at least one report:
634 ** https://fossil-scm.org/forum/forumpost/b7bbd28db4
635 ** which implies that this is unconditionally failing on mingw 32-bit
636 ** builds.
637 */
638 void blob_reserve(Blob *pBlob, unsigned int newSize){
639 blob_assert_safe_size( (i64)newSize );
640 if(newSize>pBlob->nAlloc){
 
641 pBlob->xRealloc(pBlob, newSize+1);
642 pBlob->aData[newSize] = 0;
643 }
644 }
645
@@ -919,11 +937,11 @@
937 memset(&dCfg, 0, sizeof(dCfg));
938
939 sbs = find_option("side-by-side","y",0)!=0;
940 if( (z = find_option("width","W",1))!=0 && (w = atoi(z))>0 ){
941 dCfg.wColumn = w;
942 }
943 verify_all_options();
944 if( g.argc!=3 ) usage("INPUTFILE");
945
946 blob_read_from_file(&f, g.argv[2], ExtFILE);
947 blob_strip_comment_lines(&f, &h);
948

Keyboard Shortcuts

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