xref: /plan9/sys/src/libc/9sys/convM2S.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
13e12c5d1SDavid du Colombier #include	<u.h>
23e12c5d1SDavid du Colombier #include	<libc.h>
33e12c5d1SDavid du Colombier #include	<fcall.h>
43e12c5d1SDavid du Colombier 
5*9a747e4fSDavid du Colombier static
6*9a747e4fSDavid du Colombier uchar*
gstring(uchar * p,uchar * ep,char ** s)7*9a747e4fSDavid du Colombier gstring(uchar *p, uchar *ep, char **s)
83e12c5d1SDavid du Colombier {
9*9a747e4fSDavid du Colombier 	uint n;
103e12c5d1SDavid du Colombier 
11*9a747e4fSDavid du Colombier 	if(p+BIT16SZ > ep)
12*9a747e4fSDavid du Colombier 		return nil;
13*9a747e4fSDavid du Colombier 	n = GBIT16(p);
14*9a747e4fSDavid du Colombier 	p += BIT16SZ - 1;
15*9a747e4fSDavid du Colombier 	if(p+n+1 > ep)
16*9a747e4fSDavid du Colombier 		return nil;
17*9a747e4fSDavid du Colombier 	/* move it down, on top of count, to make room for '\0' */
18*9a747e4fSDavid du Colombier 	memmove(p, p + 1, n);
19*9a747e4fSDavid du Colombier 	p[n] = '\0';
20*9a747e4fSDavid du Colombier 	*s = (char*)p;
21*9a747e4fSDavid du Colombier 	p += n+1;
22*9a747e4fSDavid du Colombier 	return p;
23*9a747e4fSDavid du Colombier }
24*9a747e4fSDavid du Colombier 
25*9a747e4fSDavid du Colombier static
26*9a747e4fSDavid du Colombier uchar*
gqid(uchar * p,uchar * ep,Qid * q)27*9a747e4fSDavid du Colombier gqid(uchar *p, uchar *ep, Qid *q)
28*9a747e4fSDavid du Colombier {
29*9a747e4fSDavid du Colombier 	if(p+QIDSZ > ep)
30*9a747e4fSDavid du Colombier 		return nil;
31*9a747e4fSDavid du Colombier 	q->type = GBIT8(p);
32*9a747e4fSDavid du Colombier 	p += BIT8SZ;
33*9a747e4fSDavid du Colombier 	q->vers = GBIT32(p);
34*9a747e4fSDavid du Colombier 	p += BIT32SZ;
35*9a747e4fSDavid du Colombier 	q->path = GBIT64(p);
36*9a747e4fSDavid du Colombier 	p += BIT64SZ;
37*9a747e4fSDavid du Colombier 	return p;
38*9a747e4fSDavid du Colombier }
39*9a747e4fSDavid du Colombier 
40*9a747e4fSDavid du Colombier /*
41*9a747e4fSDavid du Colombier  * no syntactic checks.
42*9a747e4fSDavid du Colombier  * three causes for error:
43*9a747e4fSDavid du Colombier  *  1. message size field is incorrect
44*9a747e4fSDavid du Colombier  *  2. input buffer too short for its own data (counts too long, etc.)
45*9a747e4fSDavid du Colombier  *  3. too many names or qids
46*9a747e4fSDavid du Colombier  * gqid() and gstring() return nil if they would reach beyond buffer.
47*9a747e4fSDavid du Colombier  * main switch statement checks range and also can fall through
48*9a747e4fSDavid du Colombier  * to test at end of routine.
49*9a747e4fSDavid du Colombier  */
50*9a747e4fSDavid du Colombier uint
convM2S(uchar * ap,uint nap,Fcall * f)51*9a747e4fSDavid du Colombier convM2S(uchar *ap, uint nap, Fcall *f)
52*9a747e4fSDavid du Colombier {
53*9a747e4fSDavid du Colombier 	uchar *p, *ep;
54*9a747e4fSDavid du Colombier 	uint i, size;
55*9a747e4fSDavid du Colombier 
56*9a747e4fSDavid du Colombier 	p = ap;
57*9a747e4fSDavid du Colombier 	ep = p + nap;
58*9a747e4fSDavid du Colombier 
59*9a747e4fSDavid du Colombier 	if(p+BIT32SZ+BIT8SZ+BIT16SZ > ep)
60*9a747e4fSDavid du Colombier 		return 0;
61*9a747e4fSDavid du Colombier 	size = GBIT32(p);
62*9a747e4fSDavid du Colombier 	p += BIT32SZ;
63*9a747e4fSDavid du Colombier 
64*9a747e4fSDavid du Colombier 	if(size < BIT32SZ+BIT8SZ+BIT16SZ)
65*9a747e4fSDavid du Colombier 		return 0;
66*9a747e4fSDavid du Colombier 
67*9a747e4fSDavid du Colombier 	f->type = GBIT8(p);
68*9a747e4fSDavid du Colombier 	p += BIT8SZ;
69*9a747e4fSDavid du Colombier 	f->tag = GBIT16(p);
70*9a747e4fSDavid du Colombier 	p += BIT16SZ;
71*9a747e4fSDavid du Colombier 
723e12c5d1SDavid du Colombier 	switch(f->type)
733e12c5d1SDavid du Colombier 	{
743e12c5d1SDavid du Colombier 	default:
753e12c5d1SDavid du Colombier 		return 0;
763e12c5d1SDavid du Colombier 
77*9a747e4fSDavid du Colombier 	case Tversion:
78*9a747e4fSDavid du Colombier 		if(p+BIT32SZ > ep)
79*9a747e4fSDavid du Colombier 			return 0;
80*9a747e4fSDavid du Colombier 		f->msize = GBIT32(p);
81*9a747e4fSDavid du Colombier 		p += BIT32SZ;
82*9a747e4fSDavid du Colombier 		p = gstring(p, ep, &f->version);
833e12c5d1SDavid du Colombier 		break;
843e12c5d1SDavid du Colombier 
853e12c5d1SDavid du Colombier 	case Tflush:
86*9a747e4fSDavid du Colombier 		if(p+BIT16SZ > ep)
87*9a747e4fSDavid du Colombier 			return 0;
88*9a747e4fSDavid du Colombier 		f->oldtag = GBIT16(p);
89*9a747e4fSDavid du Colombier 		p += BIT16SZ;
90219b2ee8SDavid du Colombier 		break;
91219b2ee8SDavid du Colombier 
923e12c5d1SDavid du Colombier 	case Tauth:
93*9a747e4fSDavid du Colombier 		if(p+BIT32SZ > ep)
94*9a747e4fSDavid du Colombier 			return 0;
95*9a747e4fSDavid du Colombier 		f->afid = GBIT32(p);
96*9a747e4fSDavid du Colombier 		p += BIT32SZ;
97*9a747e4fSDavid du Colombier 		p = gstring(p, ep, &f->uname);
98*9a747e4fSDavid du Colombier 		if(p == nil)
99*9a747e4fSDavid du Colombier 			break;
100*9a747e4fSDavid du Colombier 		p = gstring(p, ep, &f->aname);
101*9a747e4fSDavid du Colombier 		if(p == nil)
102*9a747e4fSDavid du Colombier 			break;
1033e12c5d1SDavid du Colombier 		break;
1043e12c5d1SDavid du Colombier 
105*9a747e4fSDavid du Colombier 	case Tattach:
106*9a747e4fSDavid du Colombier 		if(p+BIT32SZ > ep)
107*9a747e4fSDavid du Colombier 			return 0;
108*9a747e4fSDavid du Colombier 		f->fid = GBIT32(p);
109*9a747e4fSDavid du Colombier 		p += BIT32SZ;
110*9a747e4fSDavid du Colombier 		if(p+BIT32SZ > ep)
111*9a747e4fSDavid du Colombier 			return 0;
112*9a747e4fSDavid du Colombier 		f->afid = GBIT32(p);
113*9a747e4fSDavid du Colombier 		p += BIT32SZ;
114*9a747e4fSDavid du Colombier 		p = gstring(p, ep, &f->uname);
115*9a747e4fSDavid du Colombier 		if(p == nil)
116*9a747e4fSDavid du Colombier 			break;
117*9a747e4fSDavid du Colombier 		p = gstring(p, ep, &f->aname);
118*9a747e4fSDavid du Colombier 		if(p == nil)
119*9a747e4fSDavid du Colombier 			break;
1203e12c5d1SDavid du Colombier 		break;
1213e12c5d1SDavid du Colombier 
1223e12c5d1SDavid du Colombier 	case Twalk:
123*9a747e4fSDavid du Colombier 		if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep)
124*9a747e4fSDavid du Colombier 			return 0;
125*9a747e4fSDavid du Colombier 		f->fid = GBIT32(p);
126*9a747e4fSDavid du Colombier 		p += BIT32SZ;
127*9a747e4fSDavid du Colombier 		f->newfid = GBIT32(p);
128*9a747e4fSDavid du Colombier 		p += BIT32SZ;
129*9a747e4fSDavid du Colombier 		f->nwname = GBIT16(p);
130*9a747e4fSDavid du Colombier 		p += BIT16SZ;
131*9a747e4fSDavid du Colombier 		if(f->nwname > MAXWELEM)
132*9a747e4fSDavid du Colombier 			return 0;
133*9a747e4fSDavid du Colombier 		for(i=0; i<f->nwname; i++){
134*9a747e4fSDavid du Colombier 			p = gstring(p, ep, &f->wname[i]);
135*9a747e4fSDavid du Colombier 			if(p == nil)
136*9a747e4fSDavid du Colombier 				break;
137*9a747e4fSDavid du Colombier 		}
1383e12c5d1SDavid du Colombier 		break;
1393e12c5d1SDavid du Colombier 
1403e12c5d1SDavid du Colombier 	case Topen:
141*9a747e4fSDavid du Colombier 		if(p+BIT32SZ+BIT8SZ > ep)
142*9a747e4fSDavid du Colombier 			return 0;
143*9a747e4fSDavid du Colombier 		f->fid = GBIT32(p);
144*9a747e4fSDavid du Colombier 		p += BIT32SZ;
145*9a747e4fSDavid du Colombier 		f->mode = GBIT8(p);
146*9a747e4fSDavid du Colombier 		p += BIT8SZ;
1473e12c5d1SDavid du Colombier 		break;
1483e12c5d1SDavid du Colombier 
1493e12c5d1SDavid du Colombier 	case Tcreate:
150*9a747e4fSDavid du Colombier 		if(p+BIT32SZ > ep)
151*9a747e4fSDavid du Colombier 			return 0;
152*9a747e4fSDavid du Colombier 		f->fid = GBIT32(p);
153*9a747e4fSDavid du Colombier 		p += BIT32SZ;
154*9a747e4fSDavid du Colombier 		p = gstring(p, ep, &f->name);
155*9a747e4fSDavid du Colombier 		if(p == nil)
156*9a747e4fSDavid du Colombier 			break;
157*9a747e4fSDavid du Colombier 		if(p+BIT32SZ+BIT8SZ > ep)
158*9a747e4fSDavid du Colombier 			return 0;
159*9a747e4fSDavid du Colombier 		f->perm = GBIT32(p);
160*9a747e4fSDavid du Colombier 		p += BIT32SZ;
161*9a747e4fSDavid du Colombier 		f->mode = GBIT8(p);
162*9a747e4fSDavid du Colombier 		p += BIT8SZ;
1633e12c5d1SDavid du Colombier 		break;
1643e12c5d1SDavid du Colombier 
1653e12c5d1SDavid du Colombier 	case Tread:
166*9a747e4fSDavid du Colombier 		if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
167*9a747e4fSDavid du Colombier 			return 0;
168*9a747e4fSDavid du Colombier 		f->fid = GBIT32(p);
169*9a747e4fSDavid du Colombier 		p += BIT32SZ;
170*9a747e4fSDavid du Colombier 		f->offset = GBIT64(p);
171*9a747e4fSDavid du Colombier 		p += BIT64SZ;
172*9a747e4fSDavid du Colombier 		f->count = GBIT32(p);
173*9a747e4fSDavid du Colombier 		p += BIT32SZ;
1743e12c5d1SDavid du Colombier 		break;
1753e12c5d1SDavid du Colombier 
1763e12c5d1SDavid du Colombier 	case Twrite:
177*9a747e4fSDavid du Colombier 		if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
178*9a747e4fSDavid du Colombier 			return 0;
179*9a747e4fSDavid du Colombier 		f->fid = GBIT32(p);
180*9a747e4fSDavid du Colombier 		p += BIT32SZ;
181*9a747e4fSDavid du Colombier 		f->offset = GBIT64(p);
182*9a747e4fSDavid du Colombier 		p += BIT64SZ;
183*9a747e4fSDavid du Colombier 		f->count = GBIT32(p);
184*9a747e4fSDavid du Colombier 		p += BIT32SZ;
185*9a747e4fSDavid du Colombier 		if(p+f->count > ep)
186*9a747e4fSDavid du Colombier 			return 0;
187*9a747e4fSDavid du Colombier 		f->data = (char*)p;
188*9a747e4fSDavid du Colombier 		p += f->count;
1893e12c5d1SDavid du Colombier 		break;
1903e12c5d1SDavid du Colombier 
1913e12c5d1SDavid du Colombier 	case Tclunk:
1923e12c5d1SDavid du Colombier 	case Tremove:
193*9a747e4fSDavid du Colombier 		if(p+BIT32SZ > ep)
194*9a747e4fSDavid du Colombier 			return 0;
195*9a747e4fSDavid du Colombier 		f->fid = GBIT32(p);
196*9a747e4fSDavid du Colombier 		p += BIT32SZ;
1973e12c5d1SDavid du Colombier 		break;
1983e12c5d1SDavid du Colombier 
1993e12c5d1SDavid du Colombier 	case Tstat:
200*9a747e4fSDavid du Colombier 		if(p+BIT32SZ > ep)
201*9a747e4fSDavid du Colombier 			return 0;
202*9a747e4fSDavid du Colombier 		f->fid = GBIT32(p);
203*9a747e4fSDavid du Colombier 		p += BIT32SZ;
2043e12c5d1SDavid du Colombier 		break;
2053e12c5d1SDavid du Colombier 
2063e12c5d1SDavid du Colombier 	case Twstat:
207*9a747e4fSDavid du Colombier 		if(p+BIT32SZ+BIT16SZ > ep)
208*9a747e4fSDavid du Colombier 			return 0;
209*9a747e4fSDavid du Colombier 		f->fid = GBIT32(p);
210*9a747e4fSDavid du Colombier 		p += BIT32SZ;
211*9a747e4fSDavid du Colombier 		f->nstat = GBIT16(p);
212*9a747e4fSDavid du Colombier 		p += BIT16SZ;
213*9a747e4fSDavid du Colombier 		if(p+f->nstat > ep)
214*9a747e4fSDavid du Colombier 			return 0;
215*9a747e4fSDavid du Colombier 		f->stat = p;
216*9a747e4fSDavid du Colombier 		p += f->nstat;
2173e12c5d1SDavid du Colombier 		break;
2183e12c5d1SDavid du Colombier 
2193e12c5d1SDavid du Colombier /*
2203e12c5d1SDavid du Colombier  */
221*9a747e4fSDavid du Colombier 	case Rversion:
222*9a747e4fSDavid du Colombier 		if(p+BIT32SZ > ep)
223*9a747e4fSDavid du Colombier 			return 0;
224*9a747e4fSDavid du Colombier 		f->msize = GBIT32(p);
225*9a747e4fSDavid du Colombier 		p += BIT32SZ;
226*9a747e4fSDavid du Colombier 		p = gstring(p, ep, &f->version);
2273e12c5d1SDavid du Colombier 		break;
2283e12c5d1SDavid du Colombier 
2293e12c5d1SDavid du Colombier 	case Rerror:
230*9a747e4fSDavid du Colombier 		p = gstring(p, ep, &f->ename);
2313e12c5d1SDavid du Colombier 		break;
2323e12c5d1SDavid du Colombier 
2333e12c5d1SDavid du Colombier 	case Rflush:
2343e12c5d1SDavid du Colombier 		break;
2353e12c5d1SDavid du Colombier 
2363e12c5d1SDavid du Colombier 	case Rauth:
237*9a747e4fSDavid du Colombier 		p = gqid(p, ep, &f->aqid);
238*9a747e4fSDavid du Colombier 		if(p == nil)
239*9a747e4fSDavid du Colombier 			break;
2403e12c5d1SDavid du Colombier 		break;
2413e12c5d1SDavid du Colombier 
242*9a747e4fSDavid du Colombier 	case Rattach:
243*9a747e4fSDavid du Colombier 		p = gqid(p, ep, &f->qid);
244*9a747e4fSDavid du Colombier 		if(p == nil)
245*9a747e4fSDavid du Colombier 			break;
2463e12c5d1SDavid du Colombier 		break;
2473e12c5d1SDavid du Colombier 
2483e12c5d1SDavid du Colombier 	case Rwalk:
249*9a747e4fSDavid du Colombier 		if(p+BIT16SZ > ep)
250*9a747e4fSDavid du Colombier 			return 0;
251*9a747e4fSDavid du Colombier 		f->nwqid = GBIT16(p);
252*9a747e4fSDavid du Colombier 		p += BIT16SZ;
253*9a747e4fSDavid du Colombier 		if(f->nwqid > MAXWELEM)
254*9a747e4fSDavid du Colombier 			return 0;
255*9a747e4fSDavid du Colombier 		for(i=0; i<f->nwqid; i++){
256*9a747e4fSDavid du Colombier 			p = gqid(p, ep, &f->wqid[i]);
257*9a747e4fSDavid du Colombier 			if(p == nil)
258*9a747e4fSDavid du Colombier 				break;
259*9a747e4fSDavid du Colombier 		}
2603e12c5d1SDavid du Colombier 		break;
2613e12c5d1SDavid du Colombier 
2623e12c5d1SDavid du Colombier 	case Ropen:
2633e12c5d1SDavid du Colombier 	case Rcreate:
264*9a747e4fSDavid du Colombier 		p = gqid(p, ep, &f->qid);
265*9a747e4fSDavid du Colombier 		if(p == nil)
266*9a747e4fSDavid du Colombier 			break;
267*9a747e4fSDavid du Colombier 		if(p+BIT32SZ > ep)
268*9a747e4fSDavid du Colombier 			return 0;
269*9a747e4fSDavid du Colombier 		f->iounit = GBIT32(p);
270*9a747e4fSDavid du Colombier 		p += BIT32SZ;
2713e12c5d1SDavid du Colombier 		break;
2723e12c5d1SDavid du Colombier 
2733e12c5d1SDavid du Colombier 	case Rread:
274*9a747e4fSDavid du Colombier 		if(p+BIT32SZ > ep)
275*9a747e4fSDavid du Colombier 			return 0;
276*9a747e4fSDavid du Colombier 		f->count = GBIT32(p);
277*9a747e4fSDavid du Colombier 		p += BIT32SZ;
278*9a747e4fSDavid du Colombier 		if(p+f->count > ep)
279*9a747e4fSDavid du Colombier 			return 0;
280*9a747e4fSDavid du Colombier 		f->data = (char*)p;
281*9a747e4fSDavid du Colombier 		p += f->count;
2823e12c5d1SDavid du Colombier 		break;
2833e12c5d1SDavid du Colombier 
2843e12c5d1SDavid du Colombier 	case Rwrite:
285*9a747e4fSDavid du Colombier 		if(p+BIT32SZ > ep)
286*9a747e4fSDavid du Colombier 			return 0;
287*9a747e4fSDavid du Colombier 		f->count = GBIT32(p);
288*9a747e4fSDavid du Colombier 		p += BIT32SZ;
2893e12c5d1SDavid du Colombier 		break;
2903e12c5d1SDavid du Colombier 
2913e12c5d1SDavid du Colombier 	case Rclunk:
2923e12c5d1SDavid du Colombier 	case Rremove:
2933e12c5d1SDavid du Colombier 		break;
2943e12c5d1SDavid du Colombier 
2953e12c5d1SDavid du Colombier 	case Rstat:
296*9a747e4fSDavid du Colombier 		if(p+BIT16SZ > ep)
297*9a747e4fSDavid du Colombier 			return 0;
298*9a747e4fSDavid du Colombier 		f->nstat = GBIT16(p);
299*9a747e4fSDavid du Colombier 		p += BIT16SZ;
300*9a747e4fSDavid du Colombier 		if(p+f->nstat > ep)
301*9a747e4fSDavid du Colombier 			return 0;
302*9a747e4fSDavid du Colombier 		f->stat = p;
303*9a747e4fSDavid du Colombier 		p += f->nstat;
3043e12c5d1SDavid du Colombier 		break;
3053e12c5d1SDavid du Colombier 
3063e12c5d1SDavid du Colombier 	case Rwstat:
3073e12c5d1SDavid du Colombier 		break;
3083e12c5d1SDavid du Colombier 	}
309*9a747e4fSDavid du Colombier 
310*9a747e4fSDavid du Colombier 	if(p==nil || p>ep)
311*9a747e4fSDavid du Colombier 		return 0;
312*9a747e4fSDavid du Colombier 	if(ap+size == p)
313*9a747e4fSDavid du Colombier 		return size;
3143e12c5d1SDavid du Colombier 	return 0;
3153e12c5d1SDavid du Colombier }
316