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 convM2Su(uchar *ap, uint nap, Fcall *f, int dotu)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 break;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;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;140 case Topen:141 case Topenfd:142 if(p+BIT32SZ+BIT8SZ > ep)143 return 0;144 f->fid = GBIT32(p);145 p += BIT32SZ;146 f->mode = GBIT8(p);147 p += BIT8SZ;148 break;150 case Tcreate:151 if(p+BIT32SZ > ep)152 return 0;153 f->fid = GBIT32(p);154 p += BIT32SZ;155 p = gstring(p, ep, &f->name);156 if(p == nil)157 break;158 if(p+BIT32SZ+BIT8SZ > ep)159 return 0;160 f->perm = GBIT32(p);161 p += BIT32SZ;162 f->mode = GBIT8(p);163 p += BIT8SZ;164 if(dotu)165 p = gstring(p, ep, &f->extension);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 if(dotu){236 if(p+BIT16SZ > ep)237 return 0;238 f->errornum = GBIT16(p);239 p += BIT16SZ;240 }241 break;243 case Rflush:244 break;246 case Rauth:247 p = gqid(p, ep, &f->aqid);248 if(p == nil)249 break;250 break;252 case Rattach:253 p = gqid(p, ep, &f->qid);254 if(p == nil)255 break;256 break;258 case Rwalk:259 if(p+BIT16SZ > ep)260 return 0;261 f->nwqid = GBIT16(p);262 p += BIT16SZ;263 if(f->nwqid > MAXWELEM)264 return 0;265 for(i=0; i<f->nwqid; i++){266 p = gqid(p, ep, &f->wqid[i]);267 if(p == nil)268 break;269 }270 break;272 case Ropen:273 case Ropenfd:274 case Rcreate:275 p = gqid(p, ep, &f->qid);276 if(p == nil)277 break;278 if(p+BIT32SZ > ep)279 return 0;280 f->iounit = GBIT32(p);281 p += BIT32SZ;282 if(f->type == Ropenfd){283 if(p+BIT32SZ > ep)284 return 0;285 f->unixfd = GBIT32(p);286 p += BIT32SZ;287 }288 break;290 case Rread:291 if(p+BIT32SZ > ep)292 return 0;293 f->count = GBIT32(p);294 p += BIT32SZ;295 if(p+f->count > ep)296 return 0;297 f->data = (char*)p;298 p += f->count;299 break;301 case Rwrite:302 if(p+BIT32SZ > ep)303 return 0;304 f->count = GBIT32(p);305 p += BIT32SZ;306 break;308 case Rclunk:309 case Rremove:310 break;312 case Rstat:313 if(p+BIT16SZ > ep)314 return 0;315 f->nstat = GBIT16(p);316 p += BIT16SZ;317 if(p+f->nstat > ep)318 return 0;319 f->stat = p;320 p += f->nstat;321 break;323 case Rwstat:324 break;325 }327 if(p==nil || p>ep)328 return 0;329 if(ap+size == p)330 return size;331 return 0;332 }334 uint335 convM2S(uchar *ap, uint nap, Fcall *f)336 {337 return convM2Su(ap, nap, f, 0);338 }