convM2S.c (5169B)
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 convM2S(uchar *ap, uint nap, Fcall *f) 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 break; 105 106 case Tattach: 107 if(p+BIT32SZ > ep) 108 return 0; 109 f->fid = GBIT32(p); 110 p += BIT32SZ; 111 if(p+BIT32SZ > ep) 112 return 0; 113 f->afid = GBIT32(p); 114 p += BIT32SZ; 115 p = gstring(p, ep, &f->uname); 116 if(p == nil) 117 break; 118 p = gstring(p, ep, &f->aname); 119 if(p == nil) 120 break; 121 f->uidnum = NOUID; 122 break; 123 124 case Twalk: 125 if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep) 126 return 0; 127 f->fid = GBIT32(p); 128 p += BIT32SZ; 129 f->newfid = GBIT32(p); 130 p += BIT32SZ; 131 f->nwname = GBIT16(p); 132 p += BIT16SZ; 133 if(f->nwname > MAXWELEM) 134 return 0; 135 for(i=0; i<f->nwname; i++){ 136 p = gstring(p, ep, &f->wname[i]); 137 if(p == nil) 138 break; 139 } 140 break; 141 142 case Topen: 143 case Topenfd: 144 if(p+BIT32SZ+BIT8SZ > ep) 145 return 0; 146 f->fid = GBIT32(p); 147 p += BIT32SZ; 148 f->mode = GBIT8(p); 149 p += BIT8SZ; 150 break; 151 152 case Tcreate: 153 if(p+BIT32SZ > ep) 154 return 0; 155 f->fid = GBIT32(p); 156 p += BIT32SZ; 157 p = gstring(p, ep, &f->name); 158 if(p == nil) 159 break; 160 if(p+BIT32SZ+BIT8SZ > ep) 161 return 0; 162 f->perm = GBIT32(p); 163 p += BIT32SZ; 164 f->mode = GBIT8(p); 165 p += BIT8SZ; 166 break; 167 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; 178 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; 193 194 case Tclunk: 195 case Tremove: 196 if(p+BIT32SZ > ep) 197 return 0; 198 f->fid = GBIT32(p); 199 p += BIT32SZ; 200 break; 201 202 case Tstat: 203 if(p+BIT32SZ > ep) 204 return 0; 205 f->fid = GBIT32(p); 206 p += BIT32SZ; 207 break; 208 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; 221 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; 231 232 case Rerror: 233 p = gstring(p, ep, &f->ename); 234 f->errornum = 0; 235 break; 236 237 case Rflush: 238 break; 239 240 case Rauth: 241 p = gqid(p, ep, &f->aqid); 242 if(p == nil) 243 break; 244 break; 245 246 case Rattach: 247 p = gqid(p, ep, &f->qid); 248 if(p == nil) 249 break; 250 break; 251 252 case Rwalk: 253 if(p+BIT16SZ > ep) 254 return 0; 255 f->nwqid = GBIT16(p); 256 p += BIT16SZ; 257 if(f->nwqid > MAXWELEM) 258 return 0; 259 for(i=0; i<f->nwqid; i++){ 260 p = gqid(p, ep, &f->wqid[i]); 261 if(p == nil) 262 break; 263 } 264 break; 265 266 case Ropen: 267 case Ropenfd: 268 case Rcreate: 269 p = gqid(p, ep, &f->qid); 270 if(p == nil) 271 break; 272 if(p+BIT32SZ > ep) 273 return 0; 274 f->iounit = GBIT32(p); 275 p += BIT32SZ; 276 if(f->type == Ropenfd){ 277 if(p+BIT32SZ > ep) 278 return 0; 279 f->unixfd = GBIT32(p); 280 p += BIT32SZ; 281 } 282 break; 283 284 case Rread: 285 if(p+BIT32SZ > ep) 286 return 0; 287 f->count = GBIT32(p); 288 p += BIT32SZ; 289 if(p+f->count > ep) 290 return 0; 291 f->data = (char*)p; 292 p += f->count; 293 break; 294 295 case Rwrite: 296 if(p+BIT32SZ > ep) 297 return 0; 298 f->count = GBIT32(p); 299 p += BIT32SZ; 300 break; 301 302 case Rclunk: 303 case Rremove: 304 break; 305 306 case Rstat: 307 if(p+BIT16SZ > ep) 308 return 0; 309 f->nstat = GBIT16(p); 310 p += BIT16SZ; 311 if(p+f->nstat > ep) 312 return 0; 313 f->stat = p; 314 p += f->nstat; 315 break; 316 317 case Rwstat: 318 break; 319 } 320 321 if(p==nil || p>ep) 322 return 0; 323 if(ap+size == p) 324 return size; 325 return 0; 326 }