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 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 f->errornum = 0;233 if(dotu){234 if(p+BIT16SZ > ep)235 return 0;236 f->errornum = GBIT16(p);237 p += BIT16SZ;238 }239 break;241 case Rflush:242 break;244 case Rauth:245 p = gqid(p, ep, &f->aqid);246 if(p == nil)247 break;248 break;250 case Rattach:251 p = gqid(p, ep, &f->qid);252 if(p == nil)253 break;254 break;256 case Rwalk:257 if(p+BIT16SZ > ep)258 return 0;259 f->nwqid = GBIT16(p);260 p += BIT16SZ;261 if(f->nwqid > MAXWELEM)262 return 0;263 for(i=0; i<f->nwqid; i++){264 p = gqid(p, ep, &f->wqid[i]);265 if(p == nil)266 break;267 }268 break;270 case Ropen:271 case Ropenfd:272 case Rcreate:273 p = gqid(p, ep, &f->qid);274 if(p == nil)275 break;276 if(p+BIT32SZ > ep)277 return 0;278 f->iounit = GBIT32(p);279 p += BIT32SZ;280 if(f->type == Ropenfd){281 if(p+BIT32SZ > ep)282 return 0;283 f->unixfd = GBIT32(p);284 p += BIT32SZ;285 }286 break;288 case Rread:289 if(p+BIT32SZ > ep)290 return 0;291 f->count = GBIT32(p);292 p += BIT32SZ;293 if(p+f->count > ep)294 return 0;295 f->data = (char*)p;296 p += f->count;297 break;299 case Rwrite:300 if(p+BIT32SZ > ep)301 return 0;302 f->count = GBIT32(p);303 p += BIT32SZ;304 break;306 case Rclunk:307 case Rremove:308 break;310 case Rstat:311 if(p+BIT16SZ > ep)312 return 0;313 f->nstat = GBIT16(p);314 p += BIT16SZ;315 if(p+f->nstat > ep)316 return 0;317 f->stat = p;318 p += f->nstat;319 break;321 case Rwstat:322 break;323 }325 if(p==nil || p>ep)326 return 0;327 if(ap+size == p)328 return size;329 return 0;330 }332 uint333 convM2S(uchar *ap, uint nap, Fcall *f)334 {335 return convM2Su(ap, nap, f, 0);336 }