Blob
1 #include <u.h>2 #include <libc.h>3 #include <fcall.h>5 static6 uchar*7 gstring(uchar *p, uchar *ep, char **s)8 {9 uint n;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 }25 static26 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 }40 /*41 * no syntactic checks.42 * three causes for error:43 * 1. message size field is incorrect44 * 2. input buffer too short for its own data (counts too long, etc.)45 * 3. too many names or qids46 * gqid() and gstring() return nil if they would reach beyond buffer.47 * main switch statement checks range and also can fall through48 * to test at end of routine.49 */50 uint51 convM2S(uchar *ap, uint nap, Fcall *f)52 {53 uchar *p, *ep;54 uint i, size;56 p = ap;57 ep = p + nap;59 if(p+BIT32SZ+BIT8SZ+BIT16SZ > ep)60 return 0;61 size = GBIT32(p);62 p += BIT32SZ;64 if(size < BIT32SZ+BIT8SZ+BIT16SZ)65 return 0;67 f->type = GBIT8(p);68 p += BIT8SZ;69 f->tag = GBIT16(p);70 p += BIT16SZ;72 switch(f->type)73 {74 default:75 return 0;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;85 case Tflush:86 if(p+BIT16SZ > ep)87 return 0;88 f->oldtag = GBIT16(p);89 p += BIT16SZ;90 break;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;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;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;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;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;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;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;194 case Tclunk:195 case Tremove:196 if(p+BIT32SZ > ep)197 return 0;198 f->fid = GBIT32(p);199 p += BIT32SZ;200 break;202 case Tstat:203 if(p+BIT32SZ > ep)204 return 0;205 f->fid = GBIT32(p);206 p += BIT32SZ;207 break;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;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;232 case Rerror:233 p = gstring(p, ep, &f->ename);234 f->errornum = 0;235 break;237 case Rflush:238 break;240 case Rauth:241 p = gqid(p, ep, &f->aqid);242 if(p == nil)243 break;244 break;246 case Rattach:247 p = gqid(p, ep, &f->qid);248 if(p == nil)249 break;250 break;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;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;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;295 case Rwrite:296 if(p+BIT32SZ > ep)297 return 0;298 f->count = GBIT32(p);299 p += BIT32SZ;300 break;302 case Rclunk:303 case Rremove:304 break;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;317 case Rwstat:318 break;319 }321 if(p==nil || p>ep)322 return 0;323 if(ap+size == p)324 return size;325 return 0;326 }