Fossil SCM
Take care to avoid a buffer overrun if the number of rails in the graph exceeds the limit of 32.
Commit
cbafc702a99d18f8071e3c53fb2897a77070b959
Parent
52ea66df56e3ddf…
1 file changed
+19
-2
+19
-2
| --- src/graph.c | ||
| +++ src/graph.c | ||
| @@ -89,13 +89,13 @@ | ||
| 89 | 89 | GraphContext *graph_init(void){ |
| 90 | 90 | return (GraphContext*)safeMalloc( sizeof(GraphContext) ); |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | 93 | /* |
| 94 | -** Destroy a GraphContext; | |
| 94 | +** Clear all content from a graph | |
| 95 | 95 | */ |
| 96 | -void graph_free(GraphContext *p){ | |
| 96 | +static void graph_clear(GraphContext *p){ | |
| 97 | 97 | int i; |
| 98 | 98 | GraphRow *pRow; |
| 99 | 99 | while( p->pFirst ){ |
| 100 | 100 | pRow = p->pFirst; |
| 101 | 101 | p->pFirst = pRow->pNext; |
| @@ -102,10 +102,19 @@ | ||
| 102 | 102 | free(pRow); |
| 103 | 103 | } |
| 104 | 104 | for(i=0; i<p->nBranch; i++) free(p->azBranch[i]); |
| 105 | 105 | free(p->azBranch); |
| 106 | 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); | |
| 107 | 116 | free(p); |
| 108 | 117 | } |
| 109 | 118 | |
| 110 | 119 | /* |
| 111 | 120 | ** Insert a row into the hash table. pRow->rid is the key. Keys must |
| @@ -391,10 +400,11 @@ | ||
| 391 | 400 | if( omitDescenders ){ |
| 392 | 401 | pRow->iRail = findFreeRail(p, pRow->idxTop, pRow->idx, 0, 0); |
| 393 | 402 | }else{ |
| 394 | 403 | pRow->iRail = ++p->mxRail; |
| 395 | 404 | } |
| 405 | + if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; } | |
| 396 | 406 | mask = 1<<(pRow->iRail); |
| 397 | 407 | if( !omitDescenders ){ |
| 398 | 408 | pRow->bDescender = pRow->nParent>0; |
| 399 | 409 | for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){ |
| 400 | 410 | pLoop->railInUse |= mask; |
| @@ -425,32 +435,36 @@ | ||
| 425 | 435 | } |
| 426 | 436 | continue; |
| 427 | 437 | } |
| 428 | 438 | if( pRow->isDup ){ |
| 429 | 439 | pRow->iRail = findFreeRail(p, pRow->idx, pRow->idx, inUse, 0); |
| 440 | + if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; } | |
| 430 | 441 | pDesc = pRow; |
| 431 | 442 | pParent = 0; |
| 432 | 443 | }else{ |
| 433 | 444 | assert( pRow->nParent>0 ); |
| 434 | 445 | parentRid = pRow->aParent[0]; |
| 435 | 446 | pParent = hashFind(p, parentRid); |
| 436 | 447 | if( pParent==0 ){ |
| 437 | 448 | pRow->iRail = ++p->mxRail; |
| 449 | + if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; } | |
| 438 | 450 | pRow->railInUse = 1<<pRow->iRail; |
| 439 | 451 | continue; |
| 440 | 452 | } |
| 441 | 453 | if( pParent->idx>pRow->idx ){ |
| 442 | 454 | /* Common case: Child occurs after parent and is above the |
| 443 | 455 | ** parent in the timeline */ |
| 444 | 456 | pRow->iRail = findFreeRail(p, 0, pParent->idx, inUse, pParent->iRail); |
| 457 | + if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; } | |
| 445 | 458 | pParent->aiRiser[pRow->iRail] = pRow->idx; |
| 446 | 459 | }else{ |
| 447 | 460 | /* Timewarp case: Child occurs earlier in time than parent and |
| 448 | 461 | ** appears below the parent in the timeline. */ |
| 449 | 462 | int iDownRail = ++p->mxRail; |
| 450 | 463 | if( iDownRail<1 ) iDownRail = ++p->mxRail; |
| 451 | 464 | pRow->iRail = ++p->mxRail; |
| 465 | + if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; } | |
| 452 | 466 | pRow->railInUse = 1<<pRow->iRail; |
| 453 | 467 | pParent->aiRiser[iDownRail] = pRow->idx; |
| 454 | 468 | mask = 1<<iDownRail; |
| 455 | 469 | inUse |= mask; |
| 456 | 470 | for(pLoop=p->pFirst; pLoop; pLoop=pLoop->pNext){ |
| @@ -481,19 +495,21 @@ | ||
| 481 | 495 | int parentRid = pRow->aParent[i]; |
| 482 | 496 | pDesc = hashFind(p, parentRid); |
| 483 | 497 | if( pDesc==0 ){ |
| 484 | 498 | /* Merge from a node that is off-screen */ |
| 485 | 499 | int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0, 0); |
| 500 | + if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; } | |
| 486 | 501 | mask = 1<<iMrail; |
| 487 | 502 | pRow->mergeIn[iMrail] = 2; |
| 488 | 503 | pRow->mergeDown |= mask; |
| 489 | 504 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 490 | 505 | pLoop->railInUse |= mask; |
| 491 | 506 | } |
| 492 | 507 | }else{ |
| 493 | 508 | /* Merge from an on-screen node */ |
| 494 | 509 | createMergeRiser(p, pDesc, pRow); |
| 510 | + if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; } | |
| 495 | 511 | } |
| 496 | 512 | } |
| 497 | 513 | } |
| 498 | 514 | |
| 499 | 515 | /* |
| @@ -504,10 +520,11 @@ | ||
| 504 | 520 | if( !pRow->isDup ) continue; |
| 505 | 521 | pDesc = hashFind(p, pRow->rid); |
| 506 | 522 | assert( pDesc!=0 && pDesc!=pRow ); |
| 507 | 523 | createMergeRiser(p, pDesc, pRow); |
| 508 | 524 | } |
| 525 | + if( p->mxRail>=GR_MAX_RAIL ){ graph_clear(p); return; } | |
| 509 | 526 | } |
| 510 | 527 | |
| 511 | 528 | /* |
| 512 | 529 | ** Find the maximum rail number. |
| 513 | 530 | */ |
| 514 | 531 |
| --- 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 |