| convM2S.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
| git clone git://git.suckless.org/9base | |
| Log | |
| Files | |
| Refs | |
| README | |
| LICENSE | |
| --- | |
| 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 } |