convM2S.c (4968B)
1 #include "u.h" 2 #include "lib.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 break; 104 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; 121 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; 139 140 case Topen: 141 if(p+BIT32SZ+BIT8SZ > ep) 142 return 0; 143 f->fid = GBIT32(p); 144 p += BIT32SZ; 145 f->mode = GBIT8(p); 146 p += BIT8SZ; 147 break; 148 149 case Tcreate: 150 if(p+BIT32SZ > ep) 151 return 0; 152 f->fid = GBIT32(p); 153 p += BIT32SZ; 154 p = gstring(p, ep, &f->name); 155 if(p == nil) 156 break; 157 if(p+BIT32SZ+BIT8SZ > ep) 158 return 0; 159 f->perm = GBIT32(p); 160 p += BIT32SZ; 161 f->mode = GBIT8(p); 162 p += BIT8SZ; 163 break; 164 165 case Tread: 166 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep) 167 return 0; 168 f->fid = GBIT32(p); 169 p += BIT32SZ; 170 f->offset = GBIT64(p); 171 p += BIT64SZ; 172 f->count = GBIT32(p); 173 p += BIT32SZ; 174 break; 175 176 case Twrite: 177 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep) 178 return 0; 179 f->fid = GBIT32(p); 180 p += BIT32SZ; 181 f->offset = GBIT64(p); 182 p += BIT64SZ; 183 f->count = GBIT32(p); 184 p += BIT32SZ; 185 if(p+f->count > ep) 186 return 0; 187 f->data = (char*)p; 188 p += f->count; 189 break; 190 191 case Tclunk: 192 case Tremove: 193 if(p+BIT32SZ > ep) 194 return 0; 195 f->fid = GBIT32(p); 196 p += BIT32SZ; 197 break; 198 199 case Tstat: 200 if(p+BIT32SZ > ep) 201 return 0; 202 f->fid = GBIT32(p); 203 p += BIT32SZ; 204 break; 205 206 case Twstat: 207 if(p+BIT32SZ+BIT16SZ > ep) 208 return 0; 209 f->fid = GBIT32(p); 210 p += BIT32SZ; 211 f->nstat = GBIT16(p); 212 p += BIT16SZ; 213 if(p+f->nstat > ep) 214 return 0; 215 f->stat = p; 216 p += f->nstat; 217 break; 218 219 /* 220 */ 221 case Rversion: 222 if(p+BIT32SZ > ep) 223 return 0; 224 f->msize = GBIT32(p); 225 p += BIT32SZ; 226 p = gstring(p, ep, &f->version); 227 break; 228 229 case Rerror: 230 p = gstring(p, ep, &f->ename); 231 break; 232 233 case Rflush: 234 break; 235 236 case Rauth: 237 p = gqid(p, ep, &f->aqid); 238 if(p == nil) 239 break; 240 break; 241 242 case Rattach: 243 p = gqid(p, ep, &f->qid); 244 if(p == nil) 245 break; 246 break; 247 248 case Rwalk: 249 if(p+BIT16SZ > ep) 250 return 0; 251 f->nwqid = GBIT16(p); 252 p += BIT16SZ; 253 if(f->nwqid > MAXWELEM) 254 return 0; 255 for(i=0; i<f->nwqid; i++){ 256 p = gqid(p, ep, &f->wqid[i]); 257 if(p == nil) 258 break; 259 } 260 break; 261 262 case Ropen: 263 case Rcreate: 264 p = gqid(p, ep, &f->qid); 265 if(p == nil) 266 break; 267 if(p+BIT32SZ > ep) 268 return 0; 269 f->iounit = GBIT32(p); 270 p += BIT32SZ; 271 break; 272 273 case Rread: 274 if(p+BIT32SZ > ep) 275 return 0; 276 f->count = GBIT32(p); 277 p += BIT32SZ; 278 if(p+f->count > ep) 279 return 0; 280 f->data = (char*)p; 281 p += f->count; 282 break; 283 284 case Rwrite: 285 if(p+BIT32SZ > ep) 286 return 0; 287 f->count = GBIT32(p); 288 p += BIT32SZ; 289 break; 290 291 case Rclunk: 292 case Rremove: 293 break; 294 295 case Rstat: 296 if(p+BIT16SZ > ep) 297 return 0; 298 f->nstat = GBIT16(p); 299 p += BIT16SZ; 300 if(p+f->nstat > ep) 301 return 0; 302 f->stat = p; 303 p += f->nstat; 304 break; 305 306 case Rwstat: 307 break; 308 } 309 310 if(p==nil || p>ep) 311 return 0; 312 if(ap+size == p) 313 return size; 314 return 0; 315 }