URI: 
       tconvM2S.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tconvM2S.c (5169B)
       ---
            1 #include        <u.h>
            2 #include        <libc.h>
            3 #include        <fcall.h>
            4 
            5 static
            6 uchar*
            7 gstring(uchar *p, uchar *ep, char **s)
            8 {
            9         uint n;
           10 
           11         if(p+BIT16SZ > ep)
           12                 return nil;
           13         n = GBIT16(p);
           14         p += BIT16SZ - 1;
           15         if(p+n+1 > ep)
           16                 return nil;
           17         /* move it down, on top of count, to make room for '\0' */
           18         memmove(p, p + 1, n);
           19         p[n] = '\0';
           20         *s = (char*)p;
           21         p += n+1;
           22         return p;
           23 }
           24 
           25 static
           26 uchar*
           27 gqid(uchar *p, uchar *ep, Qid *q)
           28 {
           29         if(p+QIDSZ > ep)
           30                 return nil;
           31         q->type = GBIT8(p);
           32         p += BIT8SZ;
           33         q->vers = GBIT32(p);
           34         p += BIT32SZ;
           35         q->path = GBIT64(p);
           36         p += BIT64SZ;
           37         return p;
           38 }
           39 
           40 /*
           41  * no syntactic checks.
           42  * three causes for error:
           43  *  1. message size field is incorrect
           44  *  2. input buffer too short for its own data (counts too long, etc.)
           45  *  3. too many names or qids
           46  * gqid() and gstring() return nil if they would reach beyond buffer.
           47  * main switch statement checks range and also can fall through
           48  * to test at end of routine.
           49  */
           50 uint
           51 convM2S(uchar *ap, uint nap, Fcall *f)
           52 {
           53         uchar *p, *ep;
           54         uint i, size;
           55 
           56         p = ap;
           57         ep = p + nap;
           58 
           59         if(p+BIT32SZ+BIT8SZ+BIT16SZ > ep)
           60                 return 0;
           61         size = GBIT32(p);
           62         p += BIT32SZ;
           63 
           64         if(size < BIT32SZ+BIT8SZ+BIT16SZ)
           65                 return 0;
           66 
           67         f->type = GBIT8(p);
           68         p += BIT8SZ;
           69         f->tag = GBIT16(p);
           70         p += BIT16SZ;
           71 
           72         switch(f->type)
           73         {
           74         default:
           75                 return 0;
           76 
           77         case Tversion:
           78                 if(p+BIT32SZ > ep)
           79                         return 0;
           80                 f->msize = GBIT32(p);
           81                 p += BIT32SZ;
           82                 p = gstring(p, ep, &f->version);
           83                 break;
           84 
           85         case Tflush:
           86                 if(p+BIT16SZ > ep)
           87                         return 0;
           88                 f->oldtag = GBIT16(p);
           89                 p += BIT16SZ;
           90                 break;
           91 
           92         case Tauth:
           93                 if(p+BIT32SZ > ep)
           94                         return 0;
           95                 f->afid = GBIT32(p);
           96                 p += BIT32SZ;
           97                 p = gstring(p, ep, &f->uname);
           98                 if(p == nil)
           99                         break;
          100                 p = gstring(p, ep, &f->aname);
          101                 if(p == nil)
          102                         break;
          103                 f->uidnum = NOUID;
          104                 break;
          105 
          106         case Tattach:
          107                 if(p+BIT32SZ > ep)
          108                         return 0;
          109                 f->fid = GBIT32(p);
          110                 p += BIT32SZ;
          111                 if(p+BIT32SZ > ep)
          112                         return 0;
          113                 f->afid = GBIT32(p);
          114                 p += BIT32SZ;
          115                 p = gstring(p, ep, &f->uname);
          116                 if(p == nil)
          117                         break;
          118                 p = gstring(p, ep, &f->aname);
          119                 if(p == nil)
          120                         break;
          121                 f->uidnum = NOUID;
          122                 break;
          123 
          124         case Twalk:
          125                 if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep)
          126                         return 0;
          127                 f->fid = GBIT32(p);
          128                 p += BIT32SZ;
          129                 f->newfid = GBIT32(p);
          130                 p += BIT32SZ;
          131                 f->nwname = GBIT16(p);
          132                 p += BIT16SZ;
          133                 if(f->nwname > MAXWELEM)
          134                         return 0;
          135                 for(i=0; i<f->nwname; i++){
          136                         p = gstring(p, ep, &f->wname[i]);
          137                         if(p == nil)
          138                                 break;
          139                 }
          140                 break;
          141 
          142         case Topen:
          143         case Topenfd:
          144                 if(p+BIT32SZ+BIT8SZ > ep)
          145                         return 0;
          146                 f->fid = GBIT32(p);
          147                 p += BIT32SZ;
          148                 f->mode = GBIT8(p);
          149                 p += BIT8SZ;
          150                 break;
          151 
          152         case Tcreate:
          153                 if(p+BIT32SZ > ep)
          154                         return 0;
          155                 f->fid = GBIT32(p);
          156                 p += BIT32SZ;
          157                 p = gstring(p, ep, &f->name);
          158                 if(p == nil)
          159                         break;
          160                 if(p+BIT32SZ+BIT8SZ > ep)
          161                         return 0;
          162                 f->perm = GBIT32(p);
          163                 p += BIT32SZ;
          164                 f->mode = GBIT8(p);
          165                 p += BIT8SZ;
          166                 break;
          167 
          168         case Tread:
          169                 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
          170                         return 0;
          171                 f->fid = GBIT32(p);
          172                 p += BIT32SZ;
          173                 f->offset = GBIT64(p);
          174                 p += BIT64SZ;
          175                 f->count = GBIT32(p);
          176                 p += BIT32SZ;
          177                 break;
          178 
          179         case Twrite:
          180                 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
          181                         return 0;
          182                 f->fid = GBIT32(p);
          183                 p += BIT32SZ;
          184                 f->offset = GBIT64(p);
          185                 p += BIT64SZ;
          186                 f->count = GBIT32(p);
          187                 p += BIT32SZ;
          188                 if(p+f->count > ep)
          189                         return 0;
          190                 f->data = (char*)p;
          191                 p += f->count;
          192                 break;
          193 
          194         case Tclunk:
          195         case Tremove:
          196                 if(p+BIT32SZ > ep)
          197                         return 0;
          198                 f->fid = GBIT32(p);
          199                 p += BIT32SZ;
          200                 break;
          201 
          202         case Tstat:
          203                 if(p+BIT32SZ > ep)
          204                         return 0;
          205                 f->fid = GBIT32(p);
          206                 p += BIT32SZ;
          207                 break;
          208 
          209         case Twstat:
          210                 if(p+BIT32SZ+BIT16SZ > ep)
          211                         return 0;
          212                 f->fid = GBIT32(p);
          213                 p += BIT32SZ;
          214                 f->nstat = GBIT16(p);
          215                 p += BIT16SZ;
          216                 if(p+f->nstat > ep)
          217                         return 0;
          218                 f->stat = p;
          219                 p += f->nstat;
          220                 break;
          221 
          222 /*
          223  */
          224         case Rversion:
          225                 if(p+BIT32SZ > ep)
          226                         return 0;
          227                 f->msize = GBIT32(p);
          228                 p += BIT32SZ;
          229                 p = gstring(p, ep, &f->version);
          230                 break;
          231 
          232         case Rerror:
          233                 p = gstring(p, ep, &f->ename);
          234                 f->errornum = 0;
          235                 break;
          236 
          237         case Rflush:
          238                 break;
          239 
          240         case Rauth:
          241                 p = gqid(p, ep, &f->aqid);
          242                 if(p == nil)
          243                         break;
          244                 break;
          245 
          246         case Rattach:
          247                 p = gqid(p, ep, &f->qid);
          248                 if(p == nil)
          249                         break;
          250                 break;
          251 
          252         case Rwalk:
          253                 if(p+BIT16SZ > ep)
          254                         return 0;
          255                 f->nwqid = GBIT16(p);
          256                 p += BIT16SZ;
          257                 if(f->nwqid > MAXWELEM)
          258                         return 0;
          259                 for(i=0; i<f->nwqid; i++){
          260                         p = gqid(p, ep, &f->wqid[i]);
          261                         if(p == nil)
          262                                 break;
          263                 }
          264                 break;
          265 
          266         case Ropen:
          267         case Ropenfd:
          268         case Rcreate:
          269                 p = gqid(p, ep, &f->qid);
          270                 if(p == nil)
          271                         break;
          272                 if(p+BIT32SZ > ep)
          273                         return 0;
          274                 f->iounit = GBIT32(p);
          275                 p += BIT32SZ;
          276                 if(f->type == Ropenfd){
          277                         if(p+BIT32SZ > ep)
          278                                 return 0;
          279                         f->unixfd = GBIT32(p);
          280                         p += BIT32SZ;
          281                 }
          282                 break;
          283 
          284         case Rread:
          285                 if(p+BIT32SZ > ep)
          286                         return 0;
          287                 f->count = GBIT32(p);
          288                 p += BIT32SZ;
          289                 if(p+f->count > ep)
          290                         return 0;
          291                 f->data = (char*)p;
          292                 p += f->count;
          293                 break;
          294 
          295         case Rwrite:
          296                 if(p+BIT32SZ > ep)
          297                         return 0;
          298                 f->count = GBIT32(p);
          299                 p += BIT32SZ;
          300                 break;
          301 
          302         case Rclunk:
          303         case Rremove:
          304                 break;
          305 
          306         case Rstat:
          307                 if(p+BIT16SZ > ep)
          308                         return 0;
          309                 f->nstat = GBIT16(p);
          310                 p += BIT16SZ;
          311                 if(p+f->nstat > ep)
          312                         return 0;
          313                 f->stat = p;
          314                 p += f->nstat;
          315                 break;
          316 
          317         case Rwstat:
          318                 break;
          319         }
          320 
          321         if(p==nil || p>ep)
          322                 return 0;
          323         if(ap+size == p)
          324                 return size;
          325         return 0;
          326 }