Check-in [8c3ec00311]
Not logged in
Overview

SHA1 Hash:8c3ec00311d4641ac2bb9f9fd537cb4a7dd153f6
Date: 2008-02-04 19:07:58
User: drh
Comment: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.
Timelines: ancestors | descendants | both | trunk
Other Links: files | ZIP archive | manifest

Tags And Properties
Changes
[hide diffs]

Modified src/printf.c from [af38cba6b0] to [cefba92273].

@@ -148,10 +148,23 @@
 ** Size of temporary conversion buffer.
 */
 #define etBUFSIZE 500
 
 /*
+** Find the length of a string as long as that length does not
+** exceed N bytes.  If no zero terminator is seen in the first
+** N bytes then return N.  If N is negative, then this routine
+** is an alias for strlen().
+*/
+static int strnlen(const char *z, int N){
+  int n = 0;
+  while( (N-- != 0) && *(z++)!=0 ){ n++; }
+  return n;
+}
+
+
+/*
 ** The root program.  All variations call this core.
 **
 ** INPUTS:
 **   func   This is a pointer to a function taking three arguments
 **            1. A pointer to anything.  Same as the "arg" parameter.
@@ -547,13 +560,14 @@
         }
         bufpt = buf;
         break;
       case etPATH: {
         int i;
+        int limit = flag_alternateform ? va_arg(ap,int) : -1;
         char *e = va_arg(ap,char*);
         if( e==0 ){e="";}
-        length = strlen(e);
+        length = strnlen(e, limit);
         zExtra = bufpt = malloc(length+1);
         for( i=0; i<length; i++ ){
           if( e[i]=='\\' ){
             bufpt[i]='/';
           }else{
@@ -562,31 +576,37 @@
         }
         bufpt[length]='\0';
         break;
       }
       case etSTRING:
-      case etDYNSTRING:
+      case etDYNSTRING: {
+        int limit = flag_alternateform ? va_arg(ap,int) : -1;
         bufpt = va_arg(ap,char*);
         if( bufpt==0 ){
           bufpt = "";
         }else if( xtype==etDYNSTRING ){
           zExtra = bufpt;
         }
-        length = strlen(bufpt);
+        length = strnlen(bufpt, limit);
         if( precision>=0 && precision<length ) length = precision;
         break;
+      }
       case etBLOB: {
+        int limit = flag_alternateform ? va_arg(ap, int) : -1;
         Blob *pBlob = va_arg(ap, Blob*);
         bufpt = blob_buffer(pBlob);
         length = blob_size(pBlob);
+        if( limit>=0 && limit<length ) length = limit;
         break;
       }
       case etBLOBSQL: {
+        int limit = flag_alternateform ? va_arg(ap, int) : -1;
         Blob *pBlob = va_arg(ap, Blob*);
         char *zOrig = blob_buffer(pBlob);
         int i, j, n, cnt;
         n = blob_size(pBlob);
+        if( limit>=0 && limit<n ) n = limit;
         for(cnt=i=0; i<n; i++){ if( zOrig[i]=='\'' ) cnt++; }
         if( n+cnt+2 > etBUFSIZE ){
           bufpt = zExtra = malloc( n + cnt + 2 );
         }else{
           bufpt = buf;
@@ -603,15 +623,17 @@
       }
       case etSQLESCAPE:
       case etSQLESCAPE2: {
         int i, j, n, ch, isnull;
         int needQuote;
+        int limit = flag_alternateform ? va_arg(ap,int) : -1;
         char *escarg = va_arg(ap,char*);
         isnull = escarg==0;
         if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
-        for(i=n=0; (ch=escarg[i])!=0; i++){
-          if( ch=='\'' )  n++;
+        if( limit<0 ) limit = strlen(escarg);
+        for(i=n=0; i<limit; i++){
+          if( escarg[i]=='\'' )  n++;
         }
         needQuote = !isnull && xtype==etSQLESCAPE2;
         n += i + 1 + needQuote*2;
         if( n>etBUFSIZE ){
           bufpt = zExtra = malloc( n );
@@ -619,56 +641,61 @@
         }else{
           bufpt = buf;
         }
         j = 0;
         if( needQuote ) bufpt[j++] = '\'';
-        for(i=0; (ch=escarg[i])!=0; i++){
-          bufpt[j++] = ch;
+        for(i=0; i<limit; i++){
+          bufpt[j++] = ch = escarg[i];
           if( ch=='\'' ) bufpt[j++] = ch;
         }
         if( needQuote ) bufpt[j++] = '\'';
         bufpt[j] = 0;
         length = j;
         if( precision>=0 && precision<length ) length = precision;
         break;
       }
       case etHTMLIZE: {
+        int limit = flag_alternateform ? va_arg(ap,int) : -1;
         char *zMem = va_arg(ap,char*);
         if( zMem==0 ) zMem = "";
-        zExtra = bufpt = htmlize(zMem, -1);
+        zExtra = bufpt = htmlize(zMem, limit);
         length = strlen(bufpt);
         if( precision>=0 && precision<length ) length = precision;
         break;
       }
       case etHTTPIZE: {
+        int limit = flag_alternateform ? va_arg(ap,int) : -1;
         char *zMem = va_arg(ap,char*);
         if( zMem==0 ) zMem = "";
-        zExtra = bufpt = httpize(zMem, -1);
+        zExtra = bufpt = httpize(zMem, limit);
         length = strlen(bufpt);
         if( precision>=0 && precision<length ) length = precision;
         break;
       }
       case etURLIZE: {
+        int limit = flag_alternateform ? va_arg(ap,int) : -1;
         char *zMem = va_arg(ap,char*);
         if( zMem==0 ) zMem = "";
-        zExtra = bufpt = urlize(zMem, -1);
+        zExtra = bufpt = urlize(zMem, limit);
         length = strlen(bufpt);
         if( precision>=0 && precision<length ) length = precision;
         break;
       }
       case etFOSSILIZE: {
+        int limit = flag_alternateform ? va_arg(ap,int) : -1;
         char *zMem = va_arg(ap,char*);
         if( zMem==0 ) zMem = "";
-        zExtra = bufpt = fossilize(zMem, -1);
+        zExtra = bufpt = fossilize(zMem, limit);
         length = strlen(bufpt);
         if( precision>=0 && precision<length ) length = precision;
         break;
       }
       case etWIKISTR: {
+        int limit = flag_alternateform ? va_arg(ap,int) : -1;
         char *zWiki = va_arg(ap, char*);
         Blob wiki;
-        blob_init(&wiki, zWiki, -1);
+        blob_init(&wiki, zWiki, limit);
         wiki_convert(&wiki, pBlob, WIKI_INLINE);
         blob_reset(&wiki);
         length = width = 0;
         break;
       }