convM2S.c (5598B)
1 #include <u.h> 2 #include <libc.h> 3 #include <fcall.h> 4 5 static 6 uchar* 7 gstring(uchar *p, uchar *ep, char **s) 8 { 9 uint n; 10 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 } 24 25 static 26 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 } 39 40 /* 41 * no syntactic checks. 42 * three causes for error: 43 * 1. message size field is incorrect 44 * 2. input buffer too short for its own data (counts too long, etc.) 45 * 3. too many names or qids 46 * gqid() and gstring() return nil if they would reach beyond buffer. 47 * main switch statement checks range and also can fall through 48 * to test at end of routine. 49 */ 50 uint 51 convM2Su(uchar *ap, uint nap, Fcall *f, int dotu) 52 { 53 uchar *p, *ep; 54 uint i, size; 55 56 p = ap; 57 ep = p + nap; 58 59 if(p+BIT32SZ+BIT8SZ+BIT16SZ > ep) 60 return 0; 61 size = GBIT32(p); 62 p += BIT32SZ; 63 64 if(size < BIT32SZ+BIT8SZ+BIT16SZ) 65 return 0; 66 67 f->type = GBIT8(p); 68 p += BIT8SZ; 69 f->tag = GBIT16(p); 70 p += BIT16SZ; 71 72 switch(f->type) 73 { 74 default: 75 return 0; 76 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; 84 85 case Tflush: 86 if(p+BIT16SZ > ep) 87 return 0; 88 f->oldtag = GBIT16(p); 89 p += BIT16SZ; 90 break; 91 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 if(dotu){ 105 if(p+BIT32SZ > ep) 106 return 0; 107 f->uidnum = GBIT32(p); 108 p += BIT32SZ; 109 } 110 break; 111 112 case Tattach: 113 if(p+BIT32SZ > ep) 114 return 0; 115 f->fid = GBIT32(p); 116 p += BIT32SZ; 117 if(p+BIT32SZ > ep) 118 return 0; 119 f->afid = GBIT32(p); 120 p += BIT32SZ; 121 p = gstring(p, ep, &f->uname); 122 if(p == nil) 123 break; 124 p = gstring(p, ep, &f->aname); 125 if(p == nil) 126 break; 127 f->uidnum = NOUID; 128 if(dotu){ 129 if(p+BIT32SZ > ep) 130 return 0; 131 f->uidnum = GBIT32(p); 132 p += BIT32SZ; 133 } 134 break; 135 136 case Twalk: 137 if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep) 138 return 0; 139 f->fid = GBIT32(p); 140 p += BIT32SZ; 141 f->newfid = GBIT32(p); 142 p += BIT32SZ; 143 f->nwname = GBIT16(p); 144 p += BIT16SZ; 145 if(f->nwname > MAXWELEM) 146 return 0; 147 for(i=0; i<f->nwname; i++){ 148 p = gstring(p, ep, &f->wname[i]); 149 if(p == nil) 150 break; 151 } 152 break; 153 154 case Topen: 155 case Topenfd: 156 if(p+BIT32SZ+BIT8SZ > ep) 157 return 0; 158 f->fid = GBIT32(p); 159 p += BIT32SZ; 160 f->mode = GBIT8(p); 161 p += BIT8SZ; 162 break; 163 164 case Tcreate: 165 if(p+BIT32SZ > ep) 166 return 0; 167 f->fid = GBIT32(p); 168 p += BIT32SZ; 169 p = gstring(p, ep, &f->name); 170 if(p == nil) 171 break; 172 if(p+BIT32SZ+BIT8SZ > ep) 173 return 0; 174 f->perm = GBIT32(p); 175 p += BIT32SZ; 176 f->mode = GBIT8(p); 177 p += BIT8SZ; 178 if(dotu) 179 p = gstring(p, ep, &f->extension); 180 break; 181 182 case Tread: 183 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep) 184 return 0; 185 f->fid = GBIT32(p); 186 p += BIT32SZ; 187 f->offset = GBIT64(p); 188 p += BIT64SZ; 189 f->count = GBIT32(p); 190 p += BIT32SZ; 191 break; 192 193 case Twrite: 194 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep) 195 return 0; 196 f->fid = GBIT32(p); 197 p += BIT32SZ; 198 f->offset = GBIT64(p); 199 p += BIT64SZ; 200 f->count = GBIT32(p); 201 p += BIT32SZ; 202 if(p+f->count > ep) 203 return 0; 204 f->data = (char*)p; 205 p += f->count; 206 break; 207 208 case Tclunk: 209 case Tremove: 210 if(p+BIT32SZ > ep) 211 return 0; 212 f->fid = GBIT32(p); 213 p += BIT32SZ; 214 break; 215 216 case Tstat: 217 if(p+BIT32SZ > ep) 218 return 0; 219 f->fid = GBIT32(p); 220 p += BIT32SZ; 221 break; 222 223 case Twstat: 224 if(p+BIT32SZ+BIT16SZ > ep) 225 return 0; 226 f->fid = GBIT32(p); 227 p += BIT32SZ; 228 f->nstat = GBIT16(p); 229 p += BIT16SZ; 230 if(p+f->nstat > ep) 231 return 0; 232 f->stat = p; 233 p += f->nstat; 234 break; 235 236 /* 237 */ 238 case Rversion: 239 if(p+BIT32SZ > ep) 240 return 0; 241 f->msize = GBIT32(p); 242 p += BIT32SZ; 243 p = gstring(p, ep, &f->version); 244 break; 245 246 case Rerror: 247 p = gstring(p, ep, &f->ename); 248 f->errornum = 0; 249 if(dotu){ 250 if(p+BIT32SZ > ep) 251 return 0; 252 f->errornum = GBIT32(p); 253 p += BIT32SZ; 254 } 255 break; 256 257 case Rflush: 258 break; 259 260 case Rauth: 261 p = gqid(p, ep, &f->aqid); 262 if(p == nil) 263 break; 264 break; 265 266 case Rattach: 267 p = gqid(p, ep, &f->qid); 268 if(p == nil) 269 break; 270 break; 271 272 case Rwalk: 273 if(p+BIT16SZ > ep) 274 return 0; 275 f->nwqid = GBIT16(p); 276 p += BIT16SZ; 277 if(f->nwqid > MAXWELEM) 278 return 0; 279 for(i=0; i<f->nwqid; i++){ 280 p = gqid(p, ep, &f->wqid[i]); 281 if(p == nil) 282 break; 283 } 284 break; 285 286 case Ropen: 287 case Ropenfd: 288 case Rcreate: 289 p = gqid(p, ep, &f->qid); 290 if(p == nil) 291 break; 292 if(p+BIT32SZ > ep) 293 return 0; 294 f->iounit = GBIT32(p); 295 p += BIT32SZ; 296 if(f->type == Ropenfd){ 297 if(p+BIT32SZ > ep) 298 return 0; 299 f->unixfd = GBIT32(p); 300 p += BIT32SZ; 301 } 302 break; 303 304 case Rread: 305 if(p+BIT32SZ > ep) 306 return 0; 307 f->count = GBIT32(p); 308 p += BIT32SZ; 309 if(p+f->count > ep) 310 return 0; 311 f->data = (char*)p; 312 p += f->count; 313 break; 314 315 case Rwrite: 316 if(p+BIT32SZ > ep) 317 return 0; 318 f->count = GBIT32(p); 319 p += BIT32SZ; 320 break; 321 322 case Rclunk: 323 case Rremove: 324 break; 325 326 case Rstat: 327 if(p+BIT16SZ > ep) 328 return 0; 329 f->nstat = GBIT16(p); 330 p += BIT16SZ; 331 if(p+f->nstat > ep) 332 return 0; 333 f->stat = p; 334 p += f->nstat; 335 break; 336 337 case Rwstat: 338 break; 339 } 340 341 if(p==nil || p>ep) 342 return 0; 343 if(ap+size == p) 344 return size; 345 return 0; 346 } 347 348 uint 349 convM2S(uchar *ap, uint nap, Fcall *f) 350 { 351 return convM2Su(ap, nap, f, 0); 352 }