Fossil SCM
On the printf extension converters (ex: %T, %w) the "alternate form flag" (ex: %#T, %#w) means first read an integer from the argument list and then only process that number of characters from the string or blob that is read next from the argument list.
Commit
8c3ec00311d4641ac2bb9f9fd537cb4a7dd153f6
Parent
eae7ddfa4e7a5ae…
1 file changed
+39
-12
+39
-12
| --- src/printf.c | ||
| +++ src/printf.c | ||
| @@ -146,10 +146,23 @@ | ||
| 146 | 146 | |
| 147 | 147 | /* |
| 148 | 148 | ** Size of temporary conversion buffer. |
| 149 | 149 | */ |
| 150 | 150 | #define etBUFSIZE 500 |
| 151 | + | |
| 152 | +/* | |
| 153 | +** Find the length of a string as long as that length does not | |
| 154 | +** exceed N bytes. If no zero terminator is seen in the first | |
| 155 | +** N bytes then return N. If N is negative, then this routine | |
| 156 | +** is an alias for strlen(). | |
| 157 | +*/ | |
| 158 | +static int strnlen(const char *z, int N){ | |
| 159 | + int n = 0; | |
| 160 | + while( (N-- != 0) && *(z++)!=0 ){ n++; } | |
| 161 | + return n; | |
| 162 | +} | |
| 163 | + | |
| 151 | 164 | |
| 152 | 165 | /* |
| 153 | 166 | ** The root program. All variations call this core. |
| 154 | 167 | ** |
| 155 | 168 | ** INPUTS: |
| @@ -547,13 +560,14 @@ | ||
| 547 | 560 | } |
| 548 | 561 | bufpt = buf; |
| 549 | 562 | break; |
| 550 | 563 | case etPATH: { |
| 551 | 564 | int i; |
| 565 | + int limit = flag_alternateform ? va_arg(ap,int) : -1; | |
| 552 | 566 | char *e = va_arg(ap,char*); |
| 553 | 567 | if( e==0 ){e="";} |
| 554 | - length = strlen(e); | |
| 568 | + length = strnlen(e, limit); | |
| 555 | 569 | zExtra = bufpt = malloc(length+1); |
| 556 | 570 | for( i=0; i<length; i++ ){ |
| 557 | 571 | if( e[i]=='\\' ){ |
| 558 | 572 | bufpt[i]='/'; |
| 559 | 573 | }else{ |
| @@ -562,31 +576,37 @@ | ||
| 562 | 576 | } |
| 563 | 577 | bufpt[length]='\0'; |
| 564 | 578 | break; |
| 565 | 579 | } |
| 566 | 580 | case etSTRING: |
| 567 | - case etDYNSTRING: | |
| 581 | + case etDYNSTRING: { | |
| 582 | + int limit = flag_alternateform ? va_arg(ap,int) : -1; | |
| 568 | 583 | bufpt = va_arg(ap,char*); |
| 569 | 584 | if( bufpt==0 ){ |
| 570 | 585 | bufpt = ""; |
| 571 | 586 | }else if( xtype==etDYNSTRING ){ |
| 572 | 587 | zExtra = bufpt; |
| 573 | 588 | } |
| 574 | - length = strlen(bufpt); | |
| 589 | + length = strnlen(bufpt, limit); | |
| 575 | 590 | if( precision>=0 && precision<length ) length = precision; |
| 576 | 591 | break; |
| 592 | + } | |
| 577 | 593 | case etBLOB: { |
| 594 | + int limit = flag_alternateform ? va_arg(ap, int) : -1; | |
| 578 | 595 | Blob *pBlob = va_arg(ap, Blob*); |
| 579 | 596 | bufpt = blob_buffer(pBlob); |
| 580 | 597 | length = blob_size(pBlob); |
| 598 | + if( limit>=0 && limit<length ) length = limit; | |
| 581 | 599 | break; |
| 582 | 600 | } |
| 583 | 601 | case etBLOBSQL: { |
| 602 | + int limit = flag_alternateform ? va_arg(ap, int) : -1; | |
| 584 | 603 | Blob *pBlob = va_arg(ap, Blob*); |
| 585 | 604 | char *zOrig = blob_buffer(pBlob); |
| 586 | 605 | int i, j, n, cnt; |
| 587 | 606 | n = blob_size(pBlob); |
| 607 | + if( limit>=0 && limit<n ) n = limit; | |
| 588 | 608 | for(cnt=i=0; i<n; i++){ if( zOrig[i]=='\'' ) cnt++; } |
| 589 | 609 | if( n+cnt+2 > etBUFSIZE ){ |
| 590 | 610 | bufpt = zExtra = malloc( n + cnt + 2 ); |
| 591 | 611 | }else{ |
| 592 | 612 | bufpt = buf; |
| @@ -603,15 +623,17 @@ | ||
| 603 | 623 | } |
| 604 | 624 | case etSQLESCAPE: |
| 605 | 625 | case etSQLESCAPE2: { |
| 606 | 626 | int i, j, n, ch, isnull; |
| 607 | 627 | int needQuote; |
| 628 | + int limit = flag_alternateform ? va_arg(ap,int) : -1; | |
| 608 | 629 | char *escarg = va_arg(ap,char*); |
| 609 | 630 | isnull = escarg==0; |
| 610 | 631 | if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); |
| 611 | - for(i=n=0; (ch=escarg[i])!=0; i++){ | |
| 612 | - if( ch=='\'' ) n++; | |
| 632 | + if( limit<0 ) limit = strlen(escarg); | |
| 633 | + for(i=n=0; i<limit; i++){ | |
| 634 | + if( escarg[i]=='\'' ) n++; | |
| 613 | 635 | } |
| 614 | 636 | needQuote = !isnull && xtype==etSQLESCAPE2; |
| 615 | 637 | n += i + 1 + needQuote*2; |
| 616 | 638 | if( n>etBUFSIZE ){ |
| 617 | 639 | bufpt = zExtra = malloc( n ); |
| @@ -619,56 +641,61 @@ | ||
| 619 | 641 | }else{ |
| 620 | 642 | bufpt = buf; |
| 621 | 643 | } |
| 622 | 644 | j = 0; |
| 623 | 645 | if( needQuote ) bufpt[j++] = '\''; |
| 624 | - for(i=0; (ch=escarg[i])!=0; i++){ | |
| 625 | - bufpt[j++] = ch; | |
| 646 | + for(i=0; i<limit; i++){ | |
| 647 | + bufpt[j++] = ch = escarg[i]; | |
| 626 | 648 | if( ch=='\'' ) bufpt[j++] = ch; |
| 627 | 649 | } |
| 628 | 650 | if( needQuote ) bufpt[j++] = '\''; |
| 629 | 651 | bufpt[j] = 0; |
| 630 | 652 | length = j; |
| 631 | 653 | if( precision>=0 && precision<length ) length = precision; |
| 632 | 654 | break; |
| 633 | 655 | } |
| 634 | 656 | case etHTMLIZE: { |
| 657 | + int limit = flag_alternateform ? va_arg(ap,int) : -1; | |
| 635 | 658 | char *zMem = va_arg(ap,char*); |
| 636 | 659 | if( zMem==0 ) zMem = ""; |
| 637 | - zExtra = bufpt = htmlize(zMem, -1); | |
| 660 | + zExtra = bufpt = htmlize(zMem, limit); | |
| 638 | 661 | length = strlen(bufpt); |
| 639 | 662 | if( precision>=0 && precision<length ) length = precision; |
| 640 | 663 | break; |
| 641 | 664 | } |
| 642 | 665 | case etHTTPIZE: { |
| 666 | + int limit = flag_alternateform ? va_arg(ap,int) : -1; | |
| 643 | 667 | char *zMem = va_arg(ap,char*); |
| 644 | 668 | if( zMem==0 ) zMem = ""; |
| 645 | - zExtra = bufpt = httpize(zMem, -1); | |
| 669 | + zExtra = bufpt = httpize(zMem, limit); | |
| 646 | 670 | length = strlen(bufpt); |
| 647 | 671 | if( precision>=0 && precision<length ) length = precision; |
| 648 | 672 | break; |
| 649 | 673 | } |
| 650 | 674 | case etURLIZE: { |
| 675 | + int limit = flag_alternateform ? va_arg(ap,int) : -1; | |
| 651 | 676 | char *zMem = va_arg(ap,char*); |
| 652 | 677 | if( zMem==0 ) zMem = ""; |
| 653 | - zExtra = bufpt = urlize(zMem, -1); | |
| 678 | + zExtra = bufpt = urlize(zMem, limit); | |
| 654 | 679 | length = strlen(bufpt); |
| 655 | 680 | if( precision>=0 && precision<length ) length = precision; |
| 656 | 681 | break; |
| 657 | 682 | } |
| 658 | 683 | case etFOSSILIZE: { |
| 684 | + int limit = flag_alternateform ? va_arg(ap,int) : -1; | |
| 659 | 685 | char *zMem = va_arg(ap,char*); |
| 660 | 686 | if( zMem==0 ) zMem = ""; |
| 661 | - zExtra = bufpt = fossilize(zMem, -1); | |
| 687 | + zExtra = bufpt = fossilize(zMem, limit); | |
| 662 | 688 | length = strlen(bufpt); |
| 663 | 689 | if( precision>=0 && precision<length ) length = precision; |
| 664 | 690 | break; |
| 665 | 691 | } |
| 666 | 692 | case etWIKISTR: { |
| 693 | + int limit = flag_alternateform ? va_arg(ap,int) : -1; | |
| 667 | 694 | char *zWiki = va_arg(ap, char*); |
| 668 | 695 | Blob wiki; |
| 669 | - blob_init(&wiki, zWiki, -1); | |
| 696 | + blob_init(&wiki, zWiki, limit); | |
| 670 | 697 | wiki_convert(&wiki, pBlob, WIKI_INLINE); |
| 671 | 698 | blob_reset(&wiki); |
| 672 | 699 | length = width = 0; |
| 673 | 700 | break; |
| 674 | 701 | } |
| 675 | 702 |
| --- src/printf.c | |
| +++ src/printf.c | |
| @@ -146,10 +146,23 @@ | |
| 146 | |
| 147 | /* |
| 148 | ** Size of temporary conversion buffer. |
| 149 | */ |
| 150 | #define etBUFSIZE 500 |
| 151 | |
| 152 | /* |
| 153 | ** The root program. All variations call this core. |
| 154 | ** |
| 155 | ** INPUTS: |
| @@ -547,13 +560,14 @@ | |
| 547 | } |
| 548 | bufpt = buf; |
| 549 | break; |
| 550 | case etPATH: { |
| 551 | int i; |
| 552 | char *e = va_arg(ap,char*); |
| 553 | if( e==0 ){e="";} |
| 554 | length = strlen(e); |
| 555 | zExtra = bufpt = malloc(length+1); |
| 556 | for( i=0; i<length; i++ ){ |
| 557 | if( e[i]=='\\' ){ |
| 558 | bufpt[i]='/'; |
| 559 | }else{ |
| @@ -562,31 +576,37 @@ | |
| 562 | } |
| 563 | bufpt[length]='\0'; |
| 564 | break; |
| 565 | } |
| 566 | case etSTRING: |
| 567 | case etDYNSTRING: |
| 568 | bufpt = va_arg(ap,char*); |
| 569 | if( bufpt==0 ){ |
| 570 | bufpt = ""; |
| 571 | }else if( xtype==etDYNSTRING ){ |
| 572 | zExtra = bufpt; |
| 573 | } |
| 574 | length = strlen(bufpt); |
| 575 | if( precision>=0 && precision<length ) length = precision; |
| 576 | break; |
| 577 | case etBLOB: { |
| 578 | Blob *pBlob = va_arg(ap, Blob*); |
| 579 | bufpt = blob_buffer(pBlob); |
| 580 | length = blob_size(pBlob); |
| 581 | break; |
| 582 | } |
| 583 | case etBLOBSQL: { |
| 584 | Blob *pBlob = va_arg(ap, Blob*); |
| 585 | char *zOrig = blob_buffer(pBlob); |
| 586 | int i, j, n, cnt; |
| 587 | n = blob_size(pBlob); |
| 588 | for(cnt=i=0; i<n; i++){ if( zOrig[i]=='\'' ) cnt++; } |
| 589 | if( n+cnt+2 > etBUFSIZE ){ |
| 590 | bufpt = zExtra = malloc( n + cnt + 2 ); |
| 591 | }else{ |
| 592 | bufpt = buf; |
| @@ -603,15 +623,17 @@ | |
| 603 | } |
| 604 | case etSQLESCAPE: |
| 605 | case etSQLESCAPE2: { |
| 606 | int i, j, n, ch, isnull; |
| 607 | int needQuote; |
| 608 | char *escarg = va_arg(ap,char*); |
| 609 | isnull = escarg==0; |
| 610 | if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); |
| 611 | for(i=n=0; (ch=escarg[i])!=0; i++){ |
| 612 | if( ch=='\'' ) n++; |
| 613 | } |
| 614 | needQuote = !isnull && xtype==etSQLESCAPE2; |
| 615 | n += i + 1 + needQuote*2; |
| 616 | if( n>etBUFSIZE ){ |
| 617 | bufpt = zExtra = malloc( n ); |
| @@ -619,56 +641,61 @@ | |
| 619 | }else{ |
| 620 | bufpt = buf; |
| 621 | } |
| 622 | j = 0; |
| 623 | if( needQuote ) bufpt[j++] = '\''; |
| 624 | for(i=0; (ch=escarg[i])!=0; i++){ |
| 625 | bufpt[j++] = ch; |
| 626 | if( ch=='\'' ) bufpt[j++] = ch; |
| 627 | } |
| 628 | if( needQuote ) bufpt[j++] = '\''; |
| 629 | bufpt[j] = 0; |
| 630 | length = j; |
| 631 | if( precision>=0 && precision<length ) length = precision; |
| 632 | break; |
| 633 | } |
| 634 | case etHTMLIZE: { |
| 635 | char *zMem = va_arg(ap,char*); |
| 636 | if( zMem==0 ) zMem = ""; |
| 637 | zExtra = bufpt = htmlize(zMem, -1); |
| 638 | length = strlen(bufpt); |
| 639 | if( precision>=0 && precision<length ) length = precision; |
| 640 | break; |
| 641 | } |
| 642 | case etHTTPIZE: { |
| 643 | char *zMem = va_arg(ap,char*); |
| 644 | if( zMem==0 ) zMem = ""; |
| 645 | zExtra = bufpt = httpize(zMem, -1); |
| 646 | length = strlen(bufpt); |
| 647 | if( precision>=0 && precision<length ) length = precision; |
| 648 | break; |
| 649 | } |
| 650 | case etURLIZE: { |
| 651 | char *zMem = va_arg(ap,char*); |
| 652 | if( zMem==0 ) zMem = ""; |
| 653 | zExtra = bufpt = urlize(zMem, -1); |
| 654 | length = strlen(bufpt); |
| 655 | if( precision>=0 && precision<length ) length = precision; |
| 656 | break; |
| 657 | } |
| 658 | case etFOSSILIZE: { |
| 659 | char *zMem = va_arg(ap,char*); |
| 660 | if( zMem==0 ) zMem = ""; |
| 661 | zExtra = bufpt = fossilize(zMem, -1); |
| 662 | length = strlen(bufpt); |
| 663 | if( precision>=0 && precision<length ) length = precision; |
| 664 | break; |
| 665 | } |
| 666 | case etWIKISTR: { |
| 667 | char *zWiki = va_arg(ap, char*); |
| 668 | Blob wiki; |
| 669 | blob_init(&wiki, zWiki, -1); |
| 670 | wiki_convert(&wiki, pBlob, WIKI_INLINE); |
| 671 | blob_reset(&wiki); |
| 672 | length = width = 0; |
| 673 | break; |
| 674 | } |
| 675 |
| --- src/printf.c | |
| +++ src/printf.c | |
| @@ -146,10 +146,23 @@ | |
| 146 | |
| 147 | /* |
| 148 | ** Size of temporary conversion buffer. |
| 149 | */ |
| 150 | #define etBUFSIZE 500 |
| 151 | |
| 152 | /* |
| 153 | ** Find the length of a string as long as that length does not |
| 154 | ** exceed N bytes. If no zero terminator is seen in the first |
| 155 | ** N bytes then return N. If N is negative, then this routine |
| 156 | ** is an alias for strlen(). |
| 157 | */ |
| 158 | static int strnlen(const char *z, int N){ |
| 159 | int n = 0; |
| 160 | while( (N-- != 0) && *(z++)!=0 ){ n++; } |
| 161 | return n; |
| 162 | } |
| 163 | |
| 164 | |
| 165 | /* |
| 166 | ** The root program. All variations call this core. |
| 167 | ** |
| 168 | ** INPUTS: |
| @@ -547,13 +560,14 @@ | |
| 560 | } |
| 561 | bufpt = buf; |
| 562 | break; |
| 563 | case etPATH: { |
| 564 | int i; |
| 565 | int limit = flag_alternateform ? va_arg(ap,int) : -1; |
| 566 | char *e = va_arg(ap,char*); |
| 567 | if( e==0 ){e="";} |
| 568 | length = strnlen(e, limit); |
| 569 | zExtra = bufpt = malloc(length+1); |
| 570 | for( i=0; i<length; i++ ){ |
| 571 | if( e[i]=='\\' ){ |
| 572 | bufpt[i]='/'; |
| 573 | }else{ |
| @@ -562,31 +576,37 @@ | |
| 576 | } |
| 577 | bufpt[length]='\0'; |
| 578 | break; |
| 579 | } |
| 580 | case etSTRING: |
| 581 | case etDYNSTRING: { |
| 582 | int limit = flag_alternateform ? va_arg(ap,int) : -1; |
| 583 | bufpt = va_arg(ap,char*); |
| 584 | if( bufpt==0 ){ |
| 585 | bufpt = ""; |
| 586 | }else if( xtype==etDYNSTRING ){ |
| 587 | zExtra = bufpt; |
| 588 | } |
| 589 | length = strnlen(bufpt, limit); |
| 590 | if( precision>=0 && precision<length ) length = precision; |
| 591 | break; |
| 592 | } |
| 593 | case etBLOB: { |
| 594 | int limit = flag_alternateform ? va_arg(ap, int) : -1; |
| 595 | Blob *pBlob = va_arg(ap, Blob*); |
| 596 | bufpt = blob_buffer(pBlob); |
| 597 | length = blob_size(pBlob); |
| 598 | if( limit>=0 && limit<length ) length = limit; |
| 599 | break; |
| 600 | } |
| 601 | case etBLOBSQL: { |
| 602 | int limit = flag_alternateform ? va_arg(ap, int) : -1; |
| 603 | Blob *pBlob = va_arg(ap, Blob*); |
| 604 | char *zOrig = blob_buffer(pBlob); |
| 605 | int i, j, n, cnt; |
| 606 | n = blob_size(pBlob); |
| 607 | if( limit>=0 && limit<n ) n = limit; |
| 608 | for(cnt=i=0; i<n; i++){ if( zOrig[i]=='\'' ) cnt++; } |
| 609 | if( n+cnt+2 > etBUFSIZE ){ |
| 610 | bufpt = zExtra = malloc( n + cnt + 2 ); |
| 611 | }else{ |
| 612 | bufpt = buf; |
| @@ -603,15 +623,17 @@ | |
| 623 | } |
| 624 | case etSQLESCAPE: |
| 625 | case etSQLESCAPE2: { |
| 626 | int i, j, n, ch, isnull; |
| 627 | int needQuote; |
| 628 | int limit = flag_alternateform ? va_arg(ap,int) : -1; |
| 629 | char *escarg = va_arg(ap,char*); |
| 630 | isnull = escarg==0; |
| 631 | if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); |
| 632 | if( limit<0 ) limit = strlen(escarg); |
| 633 | for(i=n=0; i<limit; i++){ |
| 634 | if( escarg[i]=='\'' ) n++; |
| 635 | } |
| 636 | needQuote = !isnull && xtype==etSQLESCAPE2; |
| 637 | n += i + 1 + needQuote*2; |
| 638 | if( n>etBUFSIZE ){ |
| 639 | bufpt = zExtra = malloc( n ); |
| @@ -619,56 +641,61 @@ | |
| 641 | }else{ |
| 642 | bufpt = buf; |
| 643 | } |
| 644 | j = 0; |
| 645 | if( needQuote ) bufpt[j++] = '\''; |
| 646 | for(i=0; i<limit; i++){ |
| 647 | bufpt[j++] = ch = escarg[i]; |
| 648 | if( ch=='\'' ) bufpt[j++] = ch; |
| 649 | } |
| 650 | if( needQuote ) bufpt[j++] = '\''; |
| 651 | bufpt[j] = 0; |
| 652 | length = j; |
| 653 | if( precision>=0 && precision<length ) length = precision; |
| 654 | break; |
| 655 | } |
| 656 | case etHTMLIZE: { |
| 657 | int limit = flag_alternateform ? va_arg(ap,int) : -1; |
| 658 | char *zMem = va_arg(ap,char*); |
| 659 | if( zMem==0 ) zMem = ""; |
| 660 | zExtra = bufpt = htmlize(zMem, limit); |
| 661 | length = strlen(bufpt); |
| 662 | if( precision>=0 && precision<length ) length = precision; |
| 663 | break; |
| 664 | } |
| 665 | case etHTTPIZE: { |
| 666 | int limit = flag_alternateform ? va_arg(ap,int) : -1; |
| 667 | char *zMem = va_arg(ap,char*); |
| 668 | if( zMem==0 ) zMem = ""; |
| 669 | zExtra = bufpt = httpize(zMem, limit); |
| 670 | length = strlen(bufpt); |
| 671 | if( precision>=0 && precision<length ) length = precision; |
| 672 | break; |
| 673 | } |
| 674 | case etURLIZE: { |
| 675 | int limit = flag_alternateform ? va_arg(ap,int) : -1; |
| 676 | char *zMem = va_arg(ap,char*); |
| 677 | if( zMem==0 ) zMem = ""; |
| 678 | zExtra = bufpt = urlize(zMem, limit); |
| 679 | length = strlen(bufpt); |
| 680 | if( precision>=0 && precision<length ) length = precision; |
| 681 | break; |
| 682 | } |
| 683 | case etFOSSILIZE: { |
| 684 | int limit = flag_alternateform ? va_arg(ap,int) : -1; |
| 685 | char *zMem = va_arg(ap,char*); |
| 686 | if( zMem==0 ) zMem = ""; |
| 687 | zExtra = bufpt = fossilize(zMem, limit); |
| 688 | length = strlen(bufpt); |
| 689 | if( precision>=0 && precision<length ) length = precision; |
| 690 | break; |
| 691 | } |
| 692 | case etWIKISTR: { |
| 693 | int limit = flag_alternateform ? va_arg(ap,int) : -1; |
| 694 | char *zWiki = va_arg(ap, char*); |
| 695 | Blob wiki; |
| 696 | blob_init(&wiki, zWiki, limit); |
| 697 | wiki_convert(&wiki, pBlob, WIKI_INLINE); |
| 698 | blob_reset(&wiki); |
| 699 | length = width = 0; |
| 700 | break; |
| 701 | } |
| 702 |