convM2S.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       convM2S.c (4968B)
       ---
            1 #include "u.h"
            2 #include "lib.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                 break;
          104 
          105         case Tattach:
          106                 if(p+BIT32SZ > ep)
          107                         return 0;
          108                 f->fid = GBIT32(p);
          109                 p += BIT32SZ;
          110                 if(p+BIT32SZ > ep)
          111                         return 0;
          112                 f->afid = GBIT32(p);
          113                 p += BIT32SZ;
          114                 p = gstring(p, ep, &f->uname);
          115                 if(p == nil)
          116                         break;
          117                 p = gstring(p, ep, &f->aname);
          118                 if(p == nil)
          119                         break;
          120                 break;
          121 
          122         case Twalk:
          123                 if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep)
          124                         return 0;
          125                 f->fid = GBIT32(p);
          126                 p += BIT32SZ;
          127                 f->newfid = GBIT32(p);
          128                 p += BIT32SZ;
          129                 f->nwname = GBIT16(p);
          130                 p += BIT16SZ;
          131                 if(f->nwname > MAXWELEM)
          132                         return 0;
          133                 for(i=0; i<f->nwname; i++){
          134                         p = gstring(p, ep, &f->wname[i]);
          135                         if(p == nil)
          136                                 break;
          137                 }
          138                 break;
          139 
          140         case Topen:
          141                 if(p+BIT32SZ+BIT8SZ > ep)
          142                         return 0;
          143                 f->fid = GBIT32(p);
          144                 p += BIT32SZ;
          145                 f->mode = GBIT8(p);
          146                 p += BIT8SZ;
          147                 break;
          148 
          149         case Tcreate:
          150                 if(p+BIT32SZ > ep)
          151                         return 0;
          152                 f->fid = GBIT32(p);
          153                 p += BIT32SZ;
          154                 p = gstring(p, ep, &f->name);
          155                 if(p == nil)
          156                         break;
          157                 if(p+BIT32SZ+BIT8SZ > ep)
          158                         return 0;
          159                 f->perm = GBIT32(p);
          160                 p += BIT32SZ;
          161                 f->mode = GBIT8(p);
          162                 p += BIT8SZ;
          163                 break;
          164 
          165         case Tread:
          166                 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
          167                         return 0;
          168                 f->fid = GBIT32(p);
          169                 p += BIT32SZ;
          170                 f->offset = GBIT64(p);
          171                 p += BIT64SZ;
          172                 f->count = GBIT32(p);
          173                 p += BIT32SZ;
          174                 break;
          175 
          176         case Twrite:
          177                 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
          178                         return 0;
          179                 f->fid = GBIT32(p);
          180                 p += BIT32SZ;
          181                 f->offset = GBIT64(p);
          182                 p += BIT64SZ;
          183                 f->count = GBIT32(p);
          184                 p += BIT32SZ;
          185                 if(p+f->count > ep)
          186                         return 0;
          187                 f->data = (char*)p;
          188                 p += f->count;
          189                 break;
          190 
          191         case Tclunk:
          192         case Tremove:
          193                 if(p+BIT32SZ > ep)
          194                         return 0;
          195                 f->fid = GBIT32(p);
          196                 p += BIT32SZ;
          197                 break;
          198 
          199         case Tstat:
          200                 if(p+BIT32SZ > ep)
          201                         return 0;
          202                 f->fid = GBIT32(p);
          203                 p += BIT32SZ;
          204                 break;
          205 
          206         case Twstat:
          207                 if(p+BIT32SZ+BIT16SZ > ep)
          208                         return 0;
          209                 f->fid = GBIT32(p);
          210                 p += BIT32SZ;
          211                 f->nstat = GBIT16(p);
          212                 p += BIT16SZ;
          213                 if(p+f->nstat > ep)
          214                         return 0;
          215                 f->stat = p;
          216                 p += f->nstat;
          217                 break;
          218 
          219 /*
          220  */
          221         case Rversion:
          222                 if(p+BIT32SZ > ep)
          223                         return 0;
          224                 f->msize = GBIT32(p);
          225                 p += BIT32SZ;
          226                 p = gstring(p, ep, &f->version);
          227                 break;
          228 
          229         case Rerror:
          230                 p = gstring(p, ep, &f->ename);
          231                 break;
          232 
          233         case Rflush:
          234                 break;
          235 
          236         case Rauth:
          237                 p = gqid(p, ep, &f->aqid);
          238                 if(p == nil)
          239                         break;
          240                 break;
          241 
          242         case Rattach:
          243                 p = gqid(p, ep, &f->qid);
          244                 if(p == nil)
          245                         break;
          246                 break;
          247 
          248         case Rwalk:
          249                 if(p+BIT16SZ > ep)
          250                         return 0;
          251                 f->nwqid = GBIT16(p);
          252                 p += BIT16SZ;
          253                 if(f->nwqid > MAXWELEM)
          254                         return 0;
          255                 for(i=0; i<f->nwqid; i++){
          256                         p = gqid(p, ep, &f->wqid[i]);
          257                         if(p == nil)
          258                                 break;
          259                 }
          260                 break;
          261 
          262         case Ropen:
          263         case Rcreate:
          264                 p = gqid(p, ep, &f->qid);
          265                 if(p == nil)
          266                         break;
          267                 if(p+BIT32SZ > ep)
          268                         return 0;
          269                 f->iounit = GBIT32(p);
          270                 p += BIT32SZ;
          271                 break;
          272 
          273         case Rread:
          274                 if(p+BIT32SZ > ep)
          275                         return 0;
          276                 f->count = GBIT32(p);
          277                 p += BIT32SZ;
          278                 if(p+f->count > ep)
          279                         return 0;
          280                 f->data = (char*)p;
          281                 p += f->count;
          282                 break;
          283 
          284         case Rwrite:
          285                 if(p+BIT32SZ > ep)
          286                         return 0;
          287                 f->count = GBIT32(p);
          288                 p += BIT32SZ;
          289                 break;
          290 
          291         case Rclunk:
          292         case Rremove:
          293                 break;
          294 
          295         case Rstat:
          296                 if(p+BIT16SZ > ep)
          297                         return 0;
          298                 f->nstat = GBIT16(p);
          299                 p += BIT16SZ;
          300                 if(p+f->nstat > ep)
          301                         return 0;
          302                 f->stat = p;
          303                 p += f->nstat;
          304                 break;
          305 
          306         case Rwstat:
          307                 break;
          308         }
          309 
          310         if(p==nil || p>ep)
          311                 return 0;
          312         if(ap+size == p)
          313                 return size;
          314         return 0;
          315 }