Fossil SCM

Take care to avoid a buffer overrun if the number of rails in the graph exceeds the limit of 32.

drh 2011-03-16 01:53 trunk
Commit cbafc702a99d18f8071e3c53fb2897a77070b959
1 file changed +19 -2
+19 -2
--- src/graph.c
+++ src/graph.c
@@ -89,13 +89,13 @@
8989
GraphContext *graph_init(void){
9090
return (GraphContext*)safeMalloc( sizeof(GraphContext) );
9191
}
9292
9393
/*
94
-** Destroy a GraphContext;
94
+** Clear all content from a graph
9595
*/
96
-void graph_free(GraphContext *p){
96
+static void graph_clear(GraphContext *p){
9797
int i;
9898
GraphRow *pRow;
9999
while( p->pFirst ){
100100
pRow = p->pFirst;
101101
p->pFirst = pRow->pNext;
@@ -102,10 +102,19 @@
102102
free(pRow);
103103
}
104104
for(i=0; i<p->nBranch; i++) free(p->azBranch[i]);
105105
free(p->azBranch);
106106
free(p->apHash);
107
+ memset(p, 0, sizeof(*p));
108
+ p->nErr = 1;
109
+}
110
+
111
+/*
112
+** Destroy a GraphContext;
113
+*/
114
+void graph_free(GraphContext *p){
115
+ graph_clear(p);
107116
free(p);
108117
}
109118
110119
/*
111120
** Insert a row into the hash table. pRow->rid is the key. Keys must
@@ -391,10 +400,11 @@
391400
if( omitDescenders ){
392401
pRow->iRail = findFreeRail(p, pRow->idxTop, pRow->idx, 0, 0);
393402
}else{
394403
pRow->iRail = ++p->mxRail;
395404
}
405
+ if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; }
396406
mask = 1<<(pRow->iRail);
397407
if( !omitDescenders ){
398408
pRow->bDescender = pRow->nParent>0;
399409
for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){
400410
pLoop->railInUse |= mask;
@@ -425,32 +435,36 @@
425435
}
426436
continue;
427437
}
428438
if( pRow->isDup ){
429439
pRow->iRail = findFreeRail(p, pRow->idx, pRow->idx, inUse, 0);
440
+ if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; }
430441
pDesc = pRow;
431442
pParent = 0;
432443
}else{
433444
assert( pRow->nParent>0 );
434445
parentRid = pRow->aParent[0];
435446
pParent = hashFind(p, parentRid);
436447
if( pParent==0 ){
437448
pRow->iRail = ++p->mxRail;
449
+ if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; }
438450
pRow->railInUse = 1<<pRow->iRail;
439451
continue;
440452
}
441453
if( pParent->idx>pRow->idx ){
442454
/* Common case: Child occurs after parent and is above the
443455
** parent in the timeline */
444456
pRow->iRail = findFreeRail(p, 0, pParent->idx, inUse, pParent->iRail);
457
+ if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; }
445458
pParent->aiRiser[pRow->iRail] = pRow->idx;
446459
}else{
447460
/* Timewarp case: Child occurs earlier in time than parent and
448461
** appears below the parent in the timeline. */
449462
int iDownRail = ++p->mxRail;
450463
if( iDownRail<1 ) iDownRail = ++p->mxRail;
451464
pRow->iRail = ++p->mxRail;
465
+ if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; }
452466
pRow->railInUse = 1<<pRow->iRail;
453467
pParent->aiRiser[iDownRail] = pRow->idx;
454468
mask = 1<<iDownRail;
455469
inUse |= mask;
456470
for(pLoop=p->pFirst; pLoop; pLoop=pLoop->pNext){
@@ -481,19 +495,21 @@
481495
int parentRid = pRow->aParent[i];
482496
pDesc = hashFind(p, parentRid);
483497
if( pDesc==0 ){
484498
/* Merge from a node that is off-screen */
485499
int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0, 0);
500
+ if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; }
486501
mask = 1<<iMrail;
487502
pRow->mergeIn[iMrail] = 2;
488503
pRow->mergeDown |= mask;
489504
for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){
490505
pLoop->railInUse |= mask;
491506
}
492507
}else{
493508
/* Merge from an on-screen node */
494509
createMergeRiser(p, pDesc, pRow);
510
+ if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; }
495511
}
496512
}
497513
}
498514
499515
/*
@@ -504,10 +520,11 @@
504520
if( !pRow->isDup ) continue;
505521
pDesc = hashFind(p, pRow->rid);
506522
assert( pDesc!=0 && pDesc!=pRow );
507523
createMergeRiser(p, pDesc, pRow);
508524
}
525
+ if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; }
509526
}
510527
511528
/*
512529
** Find the maximum rail number.
513530
*/
514531
--- src/graph.c
+++ src/graph.c
@@ -89,13 +89,13 @@
89 GraphContext *graph_init(void){
90 return (GraphContext*)safeMalloc( sizeof(GraphContext) );
91 }
92
93 /*
94 ** Destroy a GraphContext;
95 */
96 void graph_free(GraphContext *p){
97 int i;
98 GraphRow *pRow;
99 while( p->pFirst ){
100 pRow = p->pFirst;
101 p->pFirst = pRow->pNext;
@@ -102,10 +102,19 @@
102 free(pRow);
103 }
104 for(i=0; i<p->nBranch; i++) free(p->azBranch[i]);
105 free(p->azBranch);
106 free(p->apHash);
 
 
 
 
 
 
 
 
 
107 free(p);
108 }
109
110 /*
111 ** Insert a row into the hash table. pRow->rid is the key. Keys must
@@ -391,10 +400,11 @@
391 if( omitDescenders ){
392 pRow->iRail = findFreeRail(p, pRow->idxTop, pRow->idx, 0, 0);
393 }else{
394 pRow->iRail = ++p->mxRail;
395 }
 
396 mask = 1<<(pRow->iRail);
397 if( !omitDescenders ){
398 pRow->bDescender = pRow->nParent>0;
399 for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){
400 pLoop->railInUse |= mask;
@@ -425,32 +435,36 @@
425 }
426 continue;
427 }
428 if( pRow->isDup ){
429 pRow->iRail = findFreeRail(p, pRow->idx, pRow->idx, inUse, 0);
 
430 pDesc = pRow;
431 pParent = 0;
432 }else{
433 assert( pRow->nParent>0 );
434 parentRid = pRow->aParent[0];
435 pParent = hashFind(p, parentRid);
436 if( pParent==0 ){
437 pRow->iRail = ++p->mxRail;
 
438 pRow->railInUse = 1<<pRow->iRail;
439 continue;
440 }
441 if( pParent->idx>pRow->idx ){
442 /* Common case: Child occurs after parent and is above the
443 ** parent in the timeline */
444 pRow->iRail = findFreeRail(p, 0, pParent->idx, inUse, pParent->iRail);
 
445 pParent->aiRiser[pRow->iRail] = pRow->idx;
446 }else{
447 /* Timewarp case: Child occurs earlier in time than parent and
448 ** appears below the parent in the timeline. */
449 int iDownRail = ++p->mxRail;
450 if( iDownRail<1 ) iDownRail = ++p->mxRail;
451 pRow->iRail = ++p->mxRail;
 
452 pRow->railInUse = 1<<pRow->iRail;
453 pParent->aiRiser[iDownRail] = pRow->idx;
454 mask = 1<<iDownRail;
455 inUse |= mask;
456 for(pLoop=p->pFirst; pLoop; pLoop=pLoop->pNext){
@@ -481,19 +495,21 @@
481 int parentRid = pRow->aParent[i];
482 pDesc = hashFind(p, parentRid);
483 if( pDesc==0 ){
484 /* Merge from a node that is off-screen */
485 int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0, 0);
 
486 mask = 1<<iMrail;
487 pRow->mergeIn[iMrail] = 2;
488 pRow->mergeDown |= mask;
489 for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){
490 pLoop->railInUse |= mask;
491 }
492 }else{
493 /* Merge from an on-screen node */
494 createMergeRiser(p, pDesc, pRow);
 
495 }
496 }
497 }
498
499 /*
@@ -504,10 +520,11 @@
504 if( !pRow->isDup ) continue;
505 pDesc = hashFind(p, pRow->rid);
506 assert( pDesc!=0 && pDesc!=pRow );
507 createMergeRiser(p, pDesc, pRow);
508 }
 
509 }
510
511 /*
512 ** Find the maximum rail number.
513 */
514
--- src/graph.c
+++ src/graph.c
@@ -89,13 +89,13 @@
89 GraphContext *graph_init(void){
90 return (GraphContext*)safeMalloc( sizeof(GraphContext) );
91 }
92
93 /*
94 ** Clear all content from a graph
95 */
96 static void graph_clear(GraphContext *p){
97 int i;
98 GraphRow *pRow;
99 while( p->pFirst ){
100 pRow = p->pFirst;
101 p->pFirst = pRow->pNext;
@@ -102,10 +102,19 @@
102 free(pRow);
103 }
104 for(i=0; i<p->nBranch; i++) free(p->azBranch[i]);
105 free(p->azBranch);
106 free(p->apHash);
107 memset(p, 0, sizeof(*p));
108 p->nErr = 1;
109 }
110
111 /*
112 ** Destroy a GraphContext;
113 */
114 void graph_free(GraphContext *p){
115 graph_clear(p);
116 free(p);
117 }
118
119 /*
120 ** Insert a row into the hash table. pRow->rid is the key. Keys must
@@ -391,10 +400,11 @@
400 if( omitDescenders ){
401 pRow->iRail = findFreeRail(p, pRow->idxTop, pRow->idx, 0, 0);
402 }else{
403 pRow->iRail = ++p->mxRail;
404 }
405 if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; }
406 mask = 1<<(pRow->iRail);
407 if( !omitDescenders ){
408 pRow->bDescender = pRow->nParent>0;
409 for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){
410 pLoop->railInUse |= mask;
@@ -425,32 +435,36 @@
435 }
436 continue;
437 }
438 if( pRow->isDup ){
439 pRow->iRail = findFreeRail(p, pRow->idx, pRow->idx, inUse, 0);
440 if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; }
441 pDesc = pRow;
442 pParent = 0;
443 }else{
444 assert( pRow->nParent>0 );
445 parentRid = pRow->aParent[0];
446 pParent = hashFind(p, parentRid);
447 if( pParent==0 ){
448 pRow->iRail = ++p->mxRail;
449 if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; }
450 pRow->railInUse = 1<<pRow->iRail;
451 continue;
452 }
453 if( pParent->idx>pRow->idx ){
454 /* Common case: Child occurs after parent and is above the
455 ** parent in the timeline */
456 pRow->iRail = findFreeRail(p, 0, pParent->idx, inUse, pParent->iRail);
457 if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; }
458 pParent->aiRiser[pRow->iRail] = pRow->idx;
459 }else{
460 /* Timewarp case: Child occurs earlier in time than parent and
461 ** appears below the parent in the timeline. */
462 int iDownRail = ++p->mxRail;
463 if( iDownRail<1 ) iDownRail = ++p->mxRail;
464 pRow->iRail = ++p->mxRail;
465 if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; }
466 pRow->railInUse = 1<<pRow->iRail;
467 pParent->aiRiser[iDownRail] = pRow->idx;
468 mask = 1<<iDownRail;
469 inUse |= mask;
470 for(pLoop=p->pFirst; pLoop; pLoop=pLoop->pNext){
@@ -481,19 +495,21 @@
495 int parentRid = pRow->aParent[i];
496 pDesc = hashFind(p, parentRid);
497 if( pDesc==0 ){
498 /* Merge from a node that is off-screen */
499 int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0, 0);
500 if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; }
501 mask = 1<<iMrail;
502 pRow->mergeIn[iMrail] = 2;
503 pRow->mergeDown |= mask;
504 for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){
505 pLoop->railInUse |= mask;
506 }
507 }else{
508 /* Merge from an on-screen node */
509 createMergeRiser(p, pDesc, pRow);
510 if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; }
511 }
512 }
513 }
514
515 /*
@@ -504,10 +520,11 @@
520 if( !pRow->isDup ) continue;
521 pDesc = hashFind(p, pRow->rid);
522 assert( pDesc!=0 && pDesc!=pRow );
523 createMergeRiser(p, pDesc, pRow);
524 }
525 if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; }
526 }
527
528 /*
529 ** Find the maximum rail number.
530 */
531

Keyboard Shortcuts

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