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 }