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 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 break;166 case Tread:167 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)168 return 0;169 f->fid = GBIT32(p);170 p += BIT32SZ;171 f->offset = GBIT64(p);172 p += BIT64SZ;173 f->count = GBIT32(p);174 p += BIT32SZ;175 break;177 case Twrite:178 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)179 return 0;180 f->fid = GBIT32(p);181 p += BIT32SZ;182 f->offset = GBIT64(p);183 p += BIT64SZ;184 f->count = GBIT32(p);185 p += BIT32SZ;186 if(p+f->count > ep)187 return 0;188 f->data = (char*)p;189 p += f->count;190 break;192 case Tclunk:193 case Tremove:194 if(p+BIT32SZ > ep)195 return 0;196 f->fid = GBIT32(p);197 p += BIT32SZ;198 break;200 case Tstat:201 if(p+BIT32SZ > ep)202 return 0;203 f->fid = GBIT32(p);204 p += BIT32SZ;205 break;207 case Twstat:208 if(p+BIT32SZ+BIT16SZ > ep)209 return 0;210 f->fid = GBIT32(p);211 p += BIT32SZ;212 f->nstat = GBIT16(p);213 p += BIT16SZ;214 if(p+f->nstat > ep)215 return 0;216 f->stat = p;217 p += f->nstat;218 break;220 /*221 */222 case Rversion:223 if(p+BIT32SZ > ep)224 return 0;225 f->msize = GBIT32(p);226 p += BIT32SZ;227 p = gstring(p, ep, &f->version);228 break;230 case Rerror:231 p = gstring(p, ep, &f->ename);232 break;234 case Rflush:235 break;237 case Rauth:238 p = gqid(p, ep, &f->aqid);239 if(p == nil)240 break;241 break;243 case Rattach:244 p = gqid(p, ep, &f->qid);245 if(p == nil)246 break;247 break;249 case Rwalk:250 if(p+BIT16SZ > ep)251 return 0;252 f->nwqid = GBIT16(p);253 p += BIT16SZ;254 if(f->nwqid > MAXWELEM)255 return 0;256 for(i=0; i<f->nwqid; i++){257 p = gqid(p, ep, &f->wqid[i]);258 if(p == nil)259 break;260 }261 break;263 case Ropen:264 case Ropenfd:265 case Rcreate:266 p = gqid(p, ep, &f->qid);267 if(p == nil)268 break;269 if(p+BIT32SZ > ep)270 return 0;271 f->iounit = GBIT32(p);272 p += BIT32SZ;273 if(f->type == Ropenfd){274 if(p+BIT32SZ > ep)275 return 0;276 f->unixfd = GBIT32(p);277 p += BIT32SZ;278 }279 break;281 case Rread:282 if(p+BIT32SZ > ep)283 return 0;284 f->count = GBIT32(p);285 p += BIT32SZ;286 if(p+f->count > ep)287 return 0;288 f->data = (char*)p;289 p += f->count;290 break;292 case Rwrite:293 if(p+BIT32SZ > ep)294 return 0;295 f->count = GBIT32(p);296 p += BIT32SZ;297 break;299 case Rclunk:300 case Rremove:301 break;303 case Rstat:304 if(p+BIT16SZ > ep)305 return 0;306 f->nstat = GBIT16(p);307 p += BIT16SZ;308 if(p+f->nstat > ep)309 return 0;310 f->stat = p;311 p += f->nstat;312 break;314 case Rwstat:315 break;316 }318 if(p==nil || p>ep)319 return 0;320 if(ap+size == p)321 return size;322 return 0;323 }