plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }