1 #include <plan9.h> 2 #include <fcall.h> 3 4 static 5 uchar* 6 gstring(uchar *p, uchar *ep, char **s) 7 { 8 uint n; 9 10 if(p+BIT16SZ > ep) 11 return nil; 12 n = GBIT16(p); 13 p += BIT16SZ - 1; 14 if(p+n+1 > ep) 15 return nil; 16 /* move it down, on top of count, to make room for '\0' */ 17 memmove(p, p + 1, n); 18 p[n] = '\0'; 19 *s = (char*)p; 20 p += n+1; 21 return p; 22 } 23 24 static 25 uchar* 26 gqid(uchar *p, uchar *ep, Qid *q) 27 { 28 if(p+QIDSZ > ep) 29 return nil; 30 q->type = GBIT8(p); 31 p += BIT8SZ; 32 q->vers = GBIT32(p); 33 p += BIT32SZ; 34 q->path = GBIT64(p); 35 p += BIT64SZ; 36 return p; 37 } 38 39 /* 40 * no syntactic checks. 41 * three causes for error: 42 * 1. message size field is incorrect 43 * 2. input buffer too short for its own data (counts too long, etc.) 44 * 3. too many names or qids 45 * gqid() and gstring() return nil if they would reach beyond buffer. 46 * main switch statement checks range and also can fall through 47 * to test at end of routine. 48 */ 49 uint 50 convM2S(uchar *ap, uint nap, Fcall *f) 51 { 52 uchar *p, *ep; 53 uint i, size; 54 55 p = ap; 56 ep = p + nap; 57 58 if(p+BIT32SZ+BIT8SZ+BIT16SZ > ep) 59 return 0; 60 size = GBIT32(p); 61 p += BIT32SZ; 62 63 if(size > nap) 64 return 0; 65 if(size < BIT32SZ+BIT8SZ+BIT16SZ) 66 return 0; 67 68 f->type = GBIT8(p); 69 p += BIT8SZ; 70 f->tag = GBIT16(p); 71 p += BIT16SZ; 72 73 switch(f->type) 74 { 75 default: 76 return 0; 77 78 case Tversion: 79 if(p+BIT32SZ > ep) 80 return 0; 81 f->msize = GBIT32(p); 82 p += BIT32SZ; 83 p = gstring(p, ep, &f->version); 84 break; 85 86 /* 87 case Tsession: 88 if(p+BIT16SZ > ep) 89 return 0; 90 f->nchal = GBIT16(p); 91 p += BIT16SZ; 92 if(p+f->nchal > ep) 93 return 0; 94 f->chal = p; 95 p += f->nchal; 96 break; 97 */ 98 99 case Tflush: 100 if(p+BIT16SZ > ep) 101 return 0; 102 f->oldtag = GBIT16(p); 103 p += BIT16SZ; 104 break; 105 106 case Tauth: 107 if(p+BIT32SZ > ep) 108 return 0; 109 f->afid = GBIT32(p); 110 p += BIT32SZ; 111 p = gstring(p, ep, &f->uname); 112 if(p == nil) 113 break; 114 p = gstring(p, ep, &f->aname); 115 if(p == nil) 116 break; 117 break; 118 119 /* 120 b 121 case Tattach: 122 if(p+BIT32SZ > ep) 123 return 0; 124 f->fid = GBIT32(p); 125 p += BIT32SZ; 126 p = gstring(p, ep, &f->uname); 127 if(p == nil) 128 break; 129 p = gstring(p, ep, &f->aname); 130 if(p == nil) 131 break; 132 if(p+BIT16SZ > ep) 133 return 0; 134 f->nauth = GBIT16(p); 135 p += BIT16SZ; 136 if(p+f->nauth > ep) 137 return 0; 138 f->auth = p; 139 p += f->nauth; 140 break; 141 */ 142 143 case Tattach: 144 if(p+BIT32SZ > ep) 145 return 0; 146 f->fid = GBIT32(p); 147 p += BIT32SZ; 148 if(p+BIT32SZ > ep) 149 return 0; 150 f->afid = GBIT32(p); 151 p += BIT32SZ; 152 p = gstring(p, ep, &f->uname); 153 if(p == nil) 154 break; 155 p = gstring(p, ep, &f->aname); 156 if(p == nil) 157 break; 158 break; 159 160 161 case Twalk: 162 if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep) 163 return 0; 164 f->fid = GBIT32(p); 165 p += BIT32SZ; 166 f->newfid = GBIT32(p); 167 p += BIT32SZ; 168 f->nwname = GBIT16(p); 169 p += BIT16SZ; 170 if(f->nwname > MAXWELEM) 171 return 0; 172 for(i=0; i<f->nwname; i++){ 173 p = gstring(p, ep, &f->wname[i]); 174 if(p == nil) 175 break; 176 } 177 break; 178 179 case Topen: 180 if(p+BIT32SZ+BIT8SZ > ep) 181 return 0; 182 f->fid = GBIT32(p); 183 p += BIT32SZ; 184 f->mode = GBIT8(p); 185 p += BIT8SZ; 186 break; 187 188 case Tcreate: 189 if(p+BIT32SZ > ep) 190 return 0; 191 f->fid = GBIT32(p); 192 p += BIT32SZ; 193 p = gstring(p, ep, &f->name); 194 if(p == nil) 195 break; 196 if(p+BIT32SZ+BIT8SZ > ep) 197 return 0; 198 f->perm = GBIT32(p); 199 p += BIT32SZ; 200 f->mode = GBIT8(p); 201 p += BIT8SZ; 202 break; 203 204 case Tread: 205 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep) 206 return 0; 207 f->fid = GBIT32(p); 208 p += BIT32SZ; 209 f->offset = GBIT64(p); 210 p += BIT64SZ; 211 f->count = GBIT32(p); 212 p += BIT32SZ; 213 break; 214 215 case Twrite: 216 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep) 217 return 0; 218 f->fid = GBIT32(p); 219 p += BIT32SZ; 220 f->offset = GBIT64(p); 221 p += BIT64SZ; 222 f->count = GBIT32(p); 223 p += BIT32SZ; 224 if(p+f->count > ep) 225 return 0; 226 f->data = (char*)p; 227 p += f->count; 228 break; 229 230 case Tclunk: 231 case Tremove: 232 if(p+BIT32SZ > ep) 233 return 0; 234 f->fid = GBIT32(p); 235 p += BIT32SZ; 236 break; 237 238 case Tstat: 239 if(p+BIT32SZ > ep) 240 return 0; 241 f->fid = GBIT32(p); 242 p += BIT32SZ; 243 break; 244 245 case Twstat: 246 if(p+BIT32SZ+BIT16SZ > ep) 247 return 0; 248 f->fid = GBIT32(p); 249 p += BIT32SZ; 250 f->nstat = GBIT16(p); 251 p += BIT16SZ; 252 if(p+f->nstat > ep) 253 return 0; 254 f->stat = p; 255 p += f->nstat; 256 break; 257 258 /* 259 */ 260 case Rversion: 261 if(p+BIT32SZ > ep) 262 return 0; 263 f->msize = GBIT32(p); 264 p += BIT32SZ; 265 p = gstring(p, ep, &f->version); 266 break; 267 268 /* 269 case Rsession: 270 if(p+BIT16SZ > ep) 271 return 0; 272 f->nchal = GBIT16(p); 273 p += BIT16SZ; 274 if(p+f->nchal > ep) 275 return 0; 276 f->chal = p; 277 p += f->nchal; 278 p = gstring(p, ep, &f->authid); 279 if(p == nil) 280 break; 281 p = gstring(p, ep, &f->authdom); 282 break; 283 */ 284 285 case Rerror: 286 p = gstring(p, ep, &f->ename); 287 break; 288 289 case Rflush: 290 break; 291 292 /* 293 case Rattach: 294 p = gqid(p, ep, &f->qid); 295 if(p == nil) 296 break; 297 if(p+BIT16SZ > ep) 298 return 0; 299 f->nrauth = GBIT16(p); 300 p += BIT16SZ; 301 if(p+f->nrauth > ep) 302 return 0; 303 f->rauth = p; 304 p += f->nrauth; 305 break; 306 */ 307 308 case Rattach: 309 p = gqid(p, ep, &f->qid); 310 if(p == nil) 311 break; 312 break; 313 314 315 case Rwalk: 316 if(p+BIT16SZ > ep) 317 return 0; 318 f->nwqid = GBIT16(p); 319 p += BIT16SZ; 320 if(f->nwqid > MAXWELEM) 321 return 0; 322 for(i=0; i<f->nwqid; i++){ 323 p = gqid(p, ep, &f->wqid[i]); 324 if(p == nil) 325 break; 326 } 327 break; 328 329 case Ropen: 330 case Rcreate: 331 p = gqid(p, ep, &f->qid); 332 if(p == nil) 333 break; 334 if(p+BIT32SZ > ep) 335 return 0; 336 f->iounit = GBIT32(p); 337 p += BIT32SZ; 338 break; 339 340 case Rread: 341 if(p+BIT32SZ > ep) 342 return 0; 343 f->count = GBIT32(p); 344 p += BIT32SZ; 345 if(p+f->count > ep) 346 return 0; 347 f->data = (char*)p; 348 p += f->count; 349 break; 350 351 case Rwrite: 352 if(p+BIT32SZ > ep) 353 return 0; 354 f->count = GBIT32(p); 355 p += BIT32SZ; 356 break; 357 358 case Rclunk: 359 case Rremove: 360 break; 361 362 case Rstat: 363 if(p+BIT16SZ > ep) 364 return 0; 365 f->nstat = GBIT16(p); 366 p += BIT16SZ; 367 if(p+f->nstat > ep) 368 return 0; 369 f->stat = p; 370 p += f->nstat; 371 break; 372 373 case Rwstat: 374 break; 375 } 376 377 if(p==nil || p>ep) 378 return 0; 379 if(ap+size == p) 380 return size; 381 return 0; 382 } 383