1 #include "lib9.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 < BIT32SZ+BIT8SZ+BIT16SZ) 64 return 0; 65 66 f->type = GBIT8(p); 67 p += BIT8SZ; 68 f->tag = GBIT16(p); 69 p += BIT16SZ; 70 71 switch(f->type) 72 { 73 default: 74 return 0; 75 76 case Tversion: 77 if(p+BIT32SZ > ep) 78 return 0; 79 f->msize = GBIT32(p); 80 p += BIT32SZ; 81 p = gstring(p, ep, &f->version); 82 break; 83 84 case Tflush: 85 if(p+BIT16SZ > ep) 86 return 0; 87 f->oldtag = GBIT16(p); 88 p += BIT16SZ; 89 break; 90 91 case Tauth: 92 if(p+BIT32SZ > ep) 93 return 0; 94 f->afid = GBIT32(p); 95 p += BIT32SZ; 96 p = gstring(p, ep, &f->uname); 97 if(p == nil) 98 break; 99 p = gstring(p, ep, &f->aname); 100 if(p == nil) 101 break; 102 break; 103 104 case Tattach: 105 if(p+BIT32SZ > ep) 106 return 0; 107 f->fid = GBIT32(p); 108 p += BIT32SZ; 109 if(p+BIT32SZ > ep) 110 return 0; 111 f->afid = GBIT32(p); 112 p += BIT32SZ; 113 p = gstring(p, ep, &f->uname); 114 if(p == nil) 115 break; 116 p = gstring(p, ep, &f->aname); 117 if(p == nil) 118 break; 119 break; 120 121 case Twalk: 122 if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep) 123 return 0; 124 f->fid = GBIT32(p); 125 p += BIT32SZ; 126 f->newfid = GBIT32(p); 127 p += BIT32SZ; 128 f->nwname = GBIT16(p); 129 p += BIT16SZ; 130 if(f->nwname > MAXWELEM) 131 return 0; 132 for(i=0; i<f->nwname; i++){ 133 p = gstring(p, ep, &f->wname[i]); 134 if(p == nil) 135 break; 136 } 137 break; 138 139 case Topen: 140 if(p+BIT32SZ+BIT8SZ > ep) 141 return 0; 142 f->fid = GBIT32(p); 143 p += BIT32SZ; 144 f->mode = GBIT8(p); 145 p += BIT8SZ; 146 break; 147 148 case Tcreate: 149 if(p+BIT32SZ > ep) 150 return 0; 151 f->fid = GBIT32(p); 152 p += BIT32SZ; 153 p = gstring(p, ep, &f->name); 154 if(p == nil) 155 break; 156 if(p+BIT32SZ+BIT8SZ > ep) 157 return 0; 158 f->perm = GBIT32(p); 159 p += BIT32SZ; 160 f->mode = GBIT8(p); 161 p += BIT8SZ; 162 break; 163 164 case Tread: 165 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep) 166 return 0; 167 f->fid = GBIT32(p); 168 p += BIT32SZ; 169 f->offset = GBIT64(p); 170 p += BIT64SZ; 171 f->count = GBIT32(p); 172 p += BIT32SZ; 173 break; 174 175 case Twrite: 176 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep) 177 return 0; 178 f->fid = GBIT32(p); 179 p += BIT32SZ; 180 f->offset = GBIT64(p); 181 p += BIT64SZ; 182 f->count = GBIT32(p); 183 p += BIT32SZ; 184 if(p+f->count > ep) 185 return 0; 186 f->data = (char*)p; 187 p += f->count; 188 break; 189 190 case Tclunk: 191 case Tremove: 192 if(p+BIT32SZ > ep) 193 return 0; 194 f->fid = GBIT32(p); 195 p += BIT32SZ; 196 break; 197 198 case Tstat: 199 if(p+BIT32SZ > ep) 200 return 0; 201 f->fid = GBIT32(p); 202 p += BIT32SZ; 203 break; 204 205 case Twstat: 206 if(p+BIT32SZ+BIT16SZ > ep) 207 return 0; 208 f->fid = GBIT32(p); 209 p += BIT32SZ; 210 f->nstat = GBIT16(p); 211 p += BIT16SZ; 212 if(p+f->nstat > ep) 213 return 0; 214 f->stat = p; 215 p += f->nstat; 216 break; 217 218 /* 219 */ 220 case Rversion: 221 if(p+BIT32SZ > ep) 222 return 0; 223 f->msize = GBIT32(p); 224 p += BIT32SZ; 225 p = gstring(p, ep, &f->version); 226 break; 227 228 case Rerror: 229 p = gstring(p, ep, &f->ename); 230 break; 231 232 case Rflush: 233 break; 234 235 case Rauth: 236 p = gqid(p, ep, &f->aqid); 237 if(p == nil) 238 break; 239 break; 240 241 case Rattach: 242 p = gqid(p, ep, &f->qid); 243 if(p == nil) 244 break; 245 break; 246 247 case Rwalk: 248 if(p+BIT16SZ > ep) 249 return 0; 250 f->nwqid = GBIT16(p); 251 p += BIT16SZ; 252 if(f->nwqid > MAXWELEM) 253 return 0; 254 for(i=0; i<f->nwqid; i++){ 255 p = gqid(p, ep, &f->wqid[i]); 256 if(p == nil) 257 break; 258 } 259 break; 260 261 case Ropen: 262 case Rcreate: 263 p = gqid(p, ep, &f->qid); 264 if(p == nil) 265 break; 266 if(p+BIT32SZ > ep) 267 return 0; 268 f->iounit = GBIT32(p); 269 p += BIT32SZ; 270 break; 271 272 case Rread: 273 if(p+BIT32SZ > ep) 274 return 0; 275 f->count = GBIT32(p); 276 p += BIT32SZ; 277 if(p+f->count > ep) 278 return 0; 279 f->data = (char*)p; 280 p += f->count; 281 break; 282 283 case Rwrite: 284 if(p+BIT32SZ > ep) 285 return 0; 286 f->count = GBIT32(p); 287 p += BIT32SZ; 288 break; 289 290 case Rclunk: 291 case Rremove: 292 break; 293 294 case Rstat: 295 if(p+BIT16SZ > ep) 296 return 0; 297 f->nstat = GBIT16(p); 298 p += BIT16SZ; 299 if(p+f->nstat > ep) 300 return 0; 301 f->stat = p; 302 p += f->nstat; 303 break; 304 305 case Rwstat: 306 break; 307 } 308 309 if(p==nil || p>ep) 310 return 0; 311 if(ap+size == p) 312 return size; 313 return 0; 314 } 315