123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- #include <plan9.h>
- #include <fcall.h>
- static
- uchar*
- gstring(uchar *p, uchar *ep, char **s)
- {
- uint n;
- if(p+BIT16SZ > ep)
- return nil;
- n = GBIT16(p);
- p += BIT16SZ - 1;
- if(p+n+1 > ep)
- return nil;
- /* move it down, on top of count, to make room for '\0' */
- memmove(p, p + 1, n);
- p[n] = '\0';
- *s = (char*)p;
- p += n+1;
- return p;
- }
- static
- uchar*
- gqid(uchar *p, uchar *ep, Qid *q)
- {
- if(p+QIDSZ > ep)
- return nil;
- q->type = GBIT8(p);
- p += BIT8SZ;
- q->vers = GBIT32(p);
- p += BIT32SZ;
- q->path = GBIT64(p);
- p += BIT64SZ;
- return p;
- }
- /*
- * no syntactic checks.
- * three causes for error:
- * 1. message size field is incorrect
- * 2. input buffer too short for its own data (counts too long, etc.)
- * 3. too many names or qids
- * gqid() and gstring() return nil if they would reach beyond buffer.
- * main switch statement checks range and also can fall through
- * to test at end of routine.
- */
- uint
- convM2S(uchar *ap, uint nap, Fcall *f)
- {
- uchar *p, *ep;
- uint i, size;
- p = ap;
- ep = p + nap;
- if(p+BIT32SZ+BIT8SZ+BIT16SZ > ep)
- return 0;
- size = GBIT32(p);
- p += BIT32SZ;
- if(size > nap)
- return 0;
- if(size < BIT32SZ+BIT8SZ+BIT16SZ)
- return 0;
- f->type = GBIT8(p);
- p += BIT8SZ;
- f->tag = GBIT16(p);
- p += BIT16SZ;
- switch(f->type)
- {
- default:
- return 0;
- case Tversion:
- if(p+BIT32SZ > ep)
- return 0;
- f->msize = GBIT32(p);
- p += BIT32SZ;
- p = gstring(p, ep, &f->version);
- break;
- /*
- case Tsession:
- if(p+BIT16SZ > ep)
- return 0;
- f->nchal = GBIT16(p);
- p += BIT16SZ;
- if(p+f->nchal > ep)
- return 0;
- f->chal = p;
- p += f->nchal;
- break;
- */
- case Tflush:
- if(p+BIT16SZ > ep)
- return 0;
- f->oldtag = GBIT16(p);
- p += BIT16SZ;
- break;
- case Tauth:
- if(p+BIT32SZ > ep)
- return 0;
- f->afid = GBIT32(p);
- p += BIT32SZ;
- p = gstring(p, ep, &f->uname);
- if(p == nil)
- break;
- p = gstring(p, ep, &f->aname);
- if(p == nil)
- break;
- break;
- /*
- b
- case Tattach:
- if(p+BIT32SZ > ep)
- return 0;
- f->fid = GBIT32(p);
- p += BIT32SZ;
- p = gstring(p, ep, &f->uname);
- if(p == nil)
- break;
- p = gstring(p, ep, &f->aname);
- if(p == nil)
- break;
- if(p+BIT16SZ > ep)
- return 0;
- f->nauth = GBIT16(p);
- p += BIT16SZ;
- if(p+f->nauth > ep)
- return 0;
- f->auth = p;
- p += f->nauth;
- break;
- */
- case Tattach:
- if(p+BIT32SZ > ep)
- return 0;
- f->fid = GBIT32(p);
- p += BIT32SZ;
- if(p+BIT32SZ > ep)
- return 0;
- f->afid = GBIT32(p);
- p += BIT32SZ;
- p = gstring(p, ep, &f->uname);
- if(p == nil)
- break;
- p = gstring(p, ep, &f->aname);
- if(p == nil)
- break;
- break;
- case Twalk:
- if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep)
- return 0;
- f->fid = GBIT32(p);
- p += BIT32SZ;
- f->newfid = GBIT32(p);
- p += BIT32SZ;
- f->nwname = GBIT16(p);
- p += BIT16SZ;
- if(f->nwname > MAXWELEM)
- return 0;
- for(i=0; i<f->nwname; i++){
- p = gstring(p, ep, &f->wname[i]);
- if(p == nil)
- break;
- }
- break;
- case Topen:
- if(p+BIT32SZ+BIT8SZ > ep)
- return 0;
- f->fid = GBIT32(p);
- p += BIT32SZ;
- f->mode = GBIT8(p);
- p += BIT8SZ;
- break;
- case Tcreate:
- if(p+BIT32SZ > ep)
- return 0;
- f->fid = GBIT32(p);
- p += BIT32SZ;
- p = gstring(p, ep, &f->name);
- if(p == nil)
- break;
- if(p+BIT32SZ+BIT8SZ > ep)
- return 0;
- f->perm = GBIT32(p);
- p += BIT32SZ;
- f->mode = GBIT8(p);
- p += BIT8SZ;
- break;
- case Tread:
- if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
- return 0;
- f->fid = GBIT32(p);
- p += BIT32SZ;
- f->offset = GBIT64(p);
- p += BIT64SZ;
- f->count = GBIT32(p);
- p += BIT32SZ;
- break;
- case Twrite:
- if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
- return 0;
- f->fid = GBIT32(p);
- p += BIT32SZ;
- f->offset = GBIT64(p);
- p += BIT64SZ;
- f->count = GBIT32(p);
- p += BIT32SZ;
- if(p+f->count > ep)
- return 0;
- f->data = (char*)p;
- p += f->count;
- break;
- case Tclunk:
- case Tremove:
- if(p+BIT32SZ > ep)
- return 0;
- f->fid = GBIT32(p);
- p += BIT32SZ;
- break;
- case Tstat:
- if(p+BIT32SZ > ep)
- return 0;
- f->fid = GBIT32(p);
- p += BIT32SZ;
- break;
- case Twstat:
- if(p+BIT32SZ+BIT16SZ > ep)
- return 0;
- f->fid = GBIT32(p);
- p += BIT32SZ;
- f->nstat = GBIT16(p);
- p += BIT16SZ;
- if(p+f->nstat > ep)
- return 0;
- f->stat = p;
- p += f->nstat;
- break;
- /*
- */
- case Rversion:
- if(p+BIT32SZ > ep)
- return 0;
- f->msize = GBIT32(p);
- p += BIT32SZ;
- p = gstring(p, ep, &f->version);
- break;
- /*
- case Rsession:
- if(p+BIT16SZ > ep)
- return 0;
- f->nchal = GBIT16(p);
- p += BIT16SZ;
- if(p+f->nchal > ep)
- return 0;
- f->chal = p;
- p += f->nchal;
- p = gstring(p, ep, &f->authid);
- if(p == nil)
- break;
- p = gstring(p, ep, &f->authdom);
- break;
- */
- case Rerror:
- p = gstring(p, ep, &f->ename);
- break;
- case Rflush:
- break;
- /*
- case Rattach:
- p = gqid(p, ep, &f->qid);
- if(p == nil)
- break;
- if(p+BIT16SZ > ep)
- return 0;
- f->nrauth = GBIT16(p);
- p += BIT16SZ;
- if(p+f->nrauth > ep)
- return 0;
- f->rauth = p;
- p += f->nrauth;
- break;
- */
- case Rattach:
- p = gqid(p, ep, &f->qid);
- if(p == nil)
- break;
- break;
- case Rwalk:
- if(p+BIT16SZ > ep)
- return 0;
- f->nwqid = GBIT16(p);
- p += BIT16SZ;
- if(f->nwqid > MAXWELEM)
- return 0;
- for(i=0; i<f->nwqid; i++){
- p = gqid(p, ep, &f->wqid[i]);
- if(p == nil)
- break;
- }
- break;
- case Ropen:
- case Rcreate:
- p = gqid(p, ep, &f->qid);
- if(p == nil)
- break;
- if(p+BIT32SZ > ep)
- return 0;
- f->iounit = GBIT32(p);
- p += BIT32SZ;
- break;
- case Rread:
- if(p+BIT32SZ > ep)
- return 0;
- f->count = GBIT32(p);
- p += BIT32SZ;
- if(p+f->count > ep)
- return 0;
- f->data = (char*)p;
- p += f->count;
- break;
- case Rwrite:
- if(p+BIT32SZ > ep)
- return 0;
- f->count = GBIT32(p);
- p += BIT32SZ;
- break;
- case Rclunk:
- case Rremove:
- break;
- case Rstat:
- if(p+BIT16SZ > ep)
- return 0;
- f->nstat = GBIT16(p);
- p += BIT16SZ;
- if(p+f->nstat > ep)
- return 0;
- f->stat = p;
- p += f->nstat;
- break;
- case Rwstat:
- break;
- }
- if(p==nil || p>ep)
- return 0;
- if(ap+size == p)
- return size;
- return 0;
- }
|