vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

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 }