/ Check-in [e43c522d]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Do not use sprintf(), strcpy() or strcat() in the implementation of the lemon parser generator tool, to avoid compiler warnings in OpenBSD.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | lemon-updates
Files: files | file ages | folders
SHA1: e43c522dde01e134f1adc94f534d2b3eda74afc2
User & Date: drh 2014-01-10 23:21:00
Context
2014-01-11
03:06
In LEMON, fix a bug in the text formatter introduced by the previous commit. Also add the new "%token_class" directive for defining symbolic names that stand any one of a collection of tokens. Closed-Leaf check-in: da7890ca user: drh tags: lemon-updates
2014-01-10
23:21
Do not use sprintf(), strcpy() or strcat() in the implementation of the lemon parser generator tool, to avoid compiler warnings in OpenBSD. check-in: e43c522d user: drh tags: lemon-updates
20:51
Remove unused structure definition from parse.y. check-in: 7f1e7ae3 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to tool/lemon.c.

    45     45   
    46     46   /*
    47     47   ** Compilers are getting increasingly pedantic about type conversions
    48     48   ** as C evolves ever closer to Ada....  To work around the latest problems
    49     49   ** we have to define the following variant of strlen().
    50     50   */
    51     51   #define lemonStrlen(X)   ((int)strlen(X))
           52  +
           53  +/*
           54  +** Compilers are starting to complain about the use of sprintf() and strcpy(),
           55  +** saying they are unsafe.  So we define our own versions of those routines too.
           56  +**
           57  +** There are three routines here:  lemon_sprintf(), lemon_vsprintf(), and
           58  +** lemon_addtext().  The first two are replacements for sprintf() and vsprintf().
           59  +** The third is a helper routine for vsnprintf() that adds texts to the end of a
           60  +** buffer, making sure the buffer is always zero-terminated.
           61  +**
           62  +** The string formatter is a minimal subset of stdlib sprintf() supporting only
           63  +** a few simply conversions:
           64  +**
           65  +**   %d
           66  +**   %s
           67  +**   %.*s
           68  +**
           69  +*/
           70  +static void lemon_addtext(
           71  +  char *zBuf,           /* The buffer to which text is added */
           72  +  int *pnUsed,          /* Slots of the buffer used so far */
           73  +  const char *zIn,      /* Text to add */
           74  +  int nIn               /* Bytes of text to add.  -1 to use strlen() */
           75  +){
           76  +  if( nIn<0 ) for(nIn=0; zIn[nIn]; nIn++){}
           77  +  if( nIn==0 ) return;
           78  +  memcpy(&zBuf[*pnUsed], zIn, nIn);
           79  +  *pnUsed += nIn;
           80  +  zBuf[*pnUsed] = 0;
           81  +}
           82  +static int lemon_vsprintf(char *str, const char *zFormat, va_list ap){
           83  +  int i, j, k, c, size;
           84  +  int nUsed = 0;
           85  +  const char *z;
           86  +  char zTemp[50];
           87  +  str[0] = 0;
           88  +  for(i=j=0; (c = zFormat[i])!=0; i++){
           89  +    if( c=='%' ){
           90  +      lemon_addtext(str, &nUsed, &zFormat[j], i-j);
           91  +      c = zFormat[++i];
           92  +      if( c=='d' ){
           93  +        int v = va_arg(ap, int);
           94  +        if( v<0 ){
           95  +          lemon_addtext(str, &nUsed, "-", 1);
           96  +          v = -v;
           97  +        }else if( v==0 ){
           98  +          lemon_addtext(str, &nUsed, "0", 1);
           99  +        }
          100  +        k = 0;
          101  +        while( v>0 ){
          102  +          k++;
          103  +          zTemp[sizeof(zTemp)-k] = (v%10) + '0';
          104  +          v /= 10;
          105  +        }
          106  +        lemon_addtext(str, &nUsed, &zTemp[sizeof(zTemp)-k], k);
          107  +      }else if( c=='s' ){
          108  +        z = va_arg(ap, const char*);
          109  +        lemon_addtext(str, &nUsed, z, -1);
          110  +      }else if( c=='.' && memcmp(&zFormat[i], ".*s", 3)==0 ){
          111  +        i += 2;
          112  +        k = va_arg(ap, int);
          113  +        z = va_arg(ap, const char*);
          114  +        lemon_addtext(str, &nUsed, z, k);
          115  +      }else if( c=='%' ){
          116  +        lemon_addtext(str, &nUsed, "%", 1);
          117  +      }else{
          118  +        fprintf(stderr, "illegal format\n");
          119  +        exit(1);
          120  +      }
          121  +      j = i+1;
          122  +    }
          123  +  }
          124  +  lemon_addtext(str, &nUsed, &zFormat[j], i-j);
          125  +  return nUsed;
          126  +}
          127  +static int lemon_sprintf(char *str, const char *format, ...){
          128  +  va_list ap;
          129  +  int rc;
          130  +  va_start(ap, format);
          131  +  rc = lemon_vsprintf(str, format, ap);
          132  +  va_end(ap);
          133  +  return rc;
          134  +}
          135  +static void lemon_strcpy(char *dest, const char *src){
          136  +  while( (*(dest++) = *(src++))!=0 ){}
          137  +}
          138  +static void lemon_strcat(char *dest, const char *src){
          139  +  while( *dest ) dest++;
          140  +  lemon_strcpy(dest, src);
          141  +}
          142  +
    52    143   
    53    144   /* a few forward declarations... */
    54    145   struct rule;
    55    146   struct lemon;
    56    147   struct action;
    57    148   
    58    149   static struct action *Action_new(void);
................................................................................
  1363   1454     }
  1364   1455     paz = &azDefine[nDefine-1];
  1365   1456     *paz = (char *) malloc( lemonStrlen(z)+1 );
  1366   1457     if( *paz==0 ){
  1367   1458       fprintf(stderr,"out of memory\n");
  1368   1459       exit(1);
  1369   1460     }
  1370         -  strcpy(*paz, z);
         1461  +  lemon_strcpy(*paz, z);
  1371   1462     for(z=*paz; *z && *z!='='; z++){}
  1372   1463     *z = 0;
  1373   1464   }
  1374   1465   
  1375   1466   static char *user_templatename = NULL;
  1376   1467   static void handle_T_option(char *z){
  1377   1468     user_templatename = (char *) malloc( lemonStrlen(z)+1 );
  1378   1469     if( user_templatename==0 ){
  1379   1470       memory_error();
  1380   1471     }
  1381         -  strcpy(user_templatename, z);
         1472  +  lemon_strcpy(user_templatename, z);
  1382   1473   }
  1383   1474   
  1384   1475   /* The main program.  Parse the command line and do it... */
  1385   1476   int main(int argc, char **argv)
  1386   1477   {
  1387   1478     static int version = 0;
  1388   1479     static int rpflag = 0;
................................................................................
  2343   2434           n = nOld + nNew + 20;
  2344   2435           addLineMacro = !psp->gp->nolinenosflag && psp->insertLineMacro &&
  2345   2436                           (psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0);
  2346   2437           if( addLineMacro ){
  2347   2438             for(z=psp->filename, nBack=0; *z; z++){
  2348   2439               if( *z=='\\' ) nBack++;
  2349   2440             }
  2350         -          sprintf(zLine, "#line %d ", psp->tokenlineno);
         2441  +          lemon_sprintf(zLine, "#line %d ", psp->tokenlineno);
  2351   2442             nLine = lemonStrlen(zLine);
  2352   2443             n += nLine + lemonStrlen(psp->filename) + nBack;
  2353   2444           }
  2354   2445           *psp->declargslot = (char *) realloc(*psp->declargslot, n);
  2355   2446           zBuf = *psp->declargslot + nOld;
  2356   2447           if( addLineMacro ){
  2357   2448             if( nOld && zBuf[-1]!='\n' ){
................................................................................
  2712   2803     char *cp;
  2713   2804   
  2714   2805     name = (char*)malloc( lemonStrlen(lemp->filename) + lemonStrlen(suffix) + 5 );
  2715   2806     if( name==0 ){
  2716   2807       fprintf(stderr,"Can't allocate space for a filename.\n");
  2717   2808       exit(1);
  2718   2809     }
  2719         -  strcpy(name,lemp->filename);
         2810  +  lemon_strcpy(name,lemp->filename);
  2720   2811     cp = strrchr(name,'.');
  2721   2812     if( cp ) *cp = 0;
  2722         -  strcat(name,suffix);
         2813  +  lemon_strcat(name,suffix);
  2723   2814     return name;
  2724   2815   }
  2725   2816   
  2726   2817   /* Open a file with a name based on the name of the input file,
  2727   2818   ** but with a different (specified) suffix, and return a pointer
  2728   2819   ** to the stream */
  2729   2820   PRIVATE FILE *file_open(
................................................................................
  2912   3003       stp = lemp->sorted[i];
  2913   3004       fprintf(fp,"State %d:\n",stp->statenum);
  2914   3005       if( lemp->basisflag ) cfp=stp->bp;
  2915   3006       else                  cfp=stp->cfp;
  2916   3007       while( cfp ){
  2917   3008         char buf[20];
  2918   3009         if( cfp->dot==cfp->rp->nrhs ){
  2919         -        sprintf(buf,"(%d)",cfp->rp->index);
         3010  +        lemon_sprintf(buf,"(%d)",cfp->rp->index);
  2920   3011           fprintf(fp,"    %5s ",buf);
  2921   3012         }else{
  2922   3013           fprintf(fp,"          ");
  2923   3014         }
  2924   3015         ConfigPrint(fp,cfp);
  2925   3016         fprintf(fp,"\n");
  2926   3017   #if 0
................................................................................
  2977   3068   #else
  2978   3069     cp = strrchr(argv0,'/');
  2979   3070   #endif
  2980   3071     if( cp ){
  2981   3072       c = *cp;
  2982   3073       *cp = 0;
  2983   3074       path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 );
  2984         -    if( path ) sprintf(path,"%s/%s",argv0,name);
         3075  +    if( path ) lemon_sprintf(path,"%s/%s",argv0,name);
  2985   3076       *cp = c;
  2986   3077     }else{
  2987   3078       pathlist = getenv("PATH");
  2988   3079       if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
  2989   3080       pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 );
  2990   3081       path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 );
  2991   3082       if( (pathbuf != 0) && (path!=0) ){
  2992   3083         pathbufptr = pathbuf;
  2993         -      strcpy(pathbuf, pathlist);
         3084  +      lemon_strcpy(pathbuf, pathlist);
  2994   3085         while( *pathbuf ){
  2995   3086           cp = strchr(pathbuf,':');
  2996   3087           if( cp==0 ) cp = &pathbuf[lemonStrlen(pathbuf)];
  2997   3088           c = *cp;
  2998   3089           *cp = 0;
  2999         -        sprintf(path,"%s/%s",pathbuf,name);
         3090  +        lemon_sprintf(path,"%s/%s",pathbuf,name);
  3000   3091           *cp = c;
  3001   3092           if( c==0 ) pathbuf[0] = 0;
  3002   3093           else pathbuf = &cp[1];
  3003   3094           if( access(path,modemask)==0 ) break;
  3004   3095         }
  3005   3096         free(pathbufptr);
  3006   3097       }
................................................................................
  3083   3174         return 0;
  3084   3175       }
  3085   3176       return in;
  3086   3177     }
  3087   3178   
  3088   3179     cp = strrchr(lemp->filename,'.');
  3089   3180     if( cp ){
  3090         -    sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename);
         3181  +    lemon_sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename);
  3091   3182     }else{
  3092         -    sprintf(buf,"%s.lt",lemp->filename);
         3183  +    lemon_sprintf(buf,"%s.lt",lemp->filename);
  3093   3184     }
  3094   3185     if( access(buf,004)==0 ){
  3095   3186       tpltname = buf;
  3096   3187     }else if( access(templatename,004)==0 ){
  3097   3188       tpltname = templatename;
  3098   3189     }else{
  3099   3190       tpltname = pathsearch(lemp->argv0,templatename,0);
................................................................................
  3236   3327       alloced = n + sizeof(zInt)*2 + used + 200;
  3237   3328       z = (char *) realloc(z,  alloced);
  3238   3329     }
  3239   3330     if( z==0 ) return empty;
  3240   3331     while( n-- > 0 ){
  3241   3332       c = *(zText++);
  3242   3333       if( c=='%' && n>0 && zText[0]=='d' ){
  3243         -      sprintf(zInt, "%d", p1);
         3334  +      lemon_sprintf(zInt, "%d", p1);
  3244   3335         p1 = p2;
  3245         -      strcpy(&z[used], zInt);
         3336  +      lemon_strcpy(&z[used], zInt);
  3246   3337         used += lemonStrlen(&z[used]);
  3247   3338         zText++;
  3248   3339         n--;
  3249   3340       }else{
  3250   3341         z[used++] = c;
  3251   3342       }
  3252   3343     }
................................................................................
  3463   3554       if( types[hash]==0 ){
  3464   3555         sp->dtnum = hash + 1;
  3465   3556         types[hash] = (char*)malloc( lemonStrlen(stddt)+1 );
  3466   3557         if( types[hash]==0 ){
  3467   3558           fprintf(stderr,"Out of memory.\n");
  3468   3559           exit(1);
  3469   3560         }
  3470         -      strcpy(types[hash],stddt);
         3561  +      lemon_strcpy(types[hash],stddt);
  3471   3562       }
  3472   3563     }
  3473   3564   
  3474   3565     /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */
  3475   3566     name = lemp->name ? lemp->name : "Parse";
  3476   3567     lineno = *plineno;
  3477   3568     if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; }
................................................................................
  3852   3943       }
  3853   3944     }
  3854   3945     tplt_xfer(lemp->name, in, out, &lineno);
  3855   3946   
  3856   3947     /* Generate a table containing the symbolic name of every symbol
  3857   3948     */
  3858   3949     for(i=0; i<lemp->nsymbol; i++){
  3859         -    sprintf(line,"\"%s\",",lemp->symbols[i]->name);
         3950  +    lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name);
  3860   3951       fprintf(out,"  %-15s",line);
  3861   3952       if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; }
  3862   3953     }
  3863   3954     if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; }
  3864   3955     tplt_xfer(lemp->name,in,out,&lineno);
  3865   3956   
  3866   3957     /* Generate a table containing a text string that describes every
................................................................................
  4019   4110   
  4020   4111     if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
  4021   4112     else                    prefix = "";
  4022   4113     in = file_open(lemp,".h","rb");
  4023   4114     if( in ){
  4024   4115       int nextChar;
  4025   4116       for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){
  4026         -      sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
         4117  +      lemon_sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
  4027   4118         if( strcmp(line,pattern) ) break;
  4028   4119       }
  4029   4120       nextChar = fgetc(in);
  4030   4121       fclose(in);
  4031   4122       if( i==lemp->nterminal && nextChar==EOF ){
  4032   4123         /* No change in the file.  Don't rewrite it. */
  4033   4124         return;
................................................................................
  4249   4340   {
  4250   4341     const char *z;
  4251   4342     char *cpy;
  4252   4343   
  4253   4344     if( y==0 ) return 0;
  4254   4345     z = Strsafe_find(y);
  4255   4346     if( z==0 && (cpy=(char *)malloc( lemonStrlen(y)+1 ))!=0 ){
  4256         -    strcpy(cpy,y);
         4347  +    lemon_strcpy(cpy,y);
  4257   4348       z = cpy;
  4258   4349       Strsafe_insert(z);
  4259   4350     }
  4260   4351     MemoryCheck(z);
  4261   4352     return z;
  4262   4353   }
  4263   4354