xref: /inferno-os/libkern/convM2S.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth #include	"lib9.h"
2*37da2899SCharles.Forsyth #include	"fcall.h"
3*37da2899SCharles.Forsyth 
4*37da2899SCharles.Forsyth static
5*37da2899SCharles.Forsyth uchar*
gstring(uchar * p,uchar * ep,char ** s)6*37da2899SCharles.Forsyth gstring(uchar *p, uchar *ep, char **s)
7*37da2899SCharles.Forsyth {
8*37da2899SCharles.Forsyth 	uint n;
9*37da2899SCharles.Forsyth 
10*37da2899SCharles.Forsyth 	if(p+BIT16SZ > ep)
11*37da2899SCharles.Forsyth 		return nil;
12*37da2899SCharles.Forsyth 	n = GBIT16(p);
13*37da2899SCharles.Forsyth 	p += BIT16SZ - 1;
14*37da2899SCharles.Forsyth 	if(p+n+1 > ep)
15*37da2899SCharles.Forsyth 		return nil;
16*37da2899SCharles.Forsyth 	/* move it down, on top of count, to make room for '\0' */
17*37da2899SCharles.Forsyth 	memmove(p, p + 1, n);
18*37da2899SCharles.Forsyth 	p[n] = '\0';
19*37da2899SCharles.Forsyth 	*s = (char*)p;
20*37da2899SCharles.Forsyth 	p += n+1;
21*37da2899SCharles.Forsyth 	return p;
22*37da2899SCharles.Forsyth }
23*37da2899SCharles.Forsyth 
24*37da2899SCharles.Forsyth static
25*37da2899SCharles.Forsyth uchar*
gqid(uchar * p,uchar * ep,Qid * q)26*37da2899SCharles.Forsyth gqid(uchar *p, uchar *ep, Qid *q)
27*37da2899SCharles.Forsyth {
28*37da2899SCharles.Forsyth 	if(p+QIDSZ > ep)
29*37da2899SCharles.Forsyth 		return nil;
30*37da2899SCharles.Forsyth 	q->type = GBIT8(p);
31*37da2899SCharles.Forsyth 	p += BIT8SZ;
32*37da2899SCharles.Forsyth 	q->vers = GBIT32(p);
33*37da2899SCharles.Forsyth 	p += BIT32SZ;
34*37da2899SCharles.Forsyth 	q->path = GBIT64(p);
35*37da2899SCharles.Forsyth 	p += BIT64SZ;
36*37da2899SCharles.Forsyth 	return p;
37*37da2899SCharles.Forsyth }
38*37da2899SCharles.Forsyth 
39*37da2899SCharles.Forsyth /*
40*37da2899SCharles.Forsyth  * no syntactic checks.
41*37da2899SCharles.Forsyth  * three causes for error:
42*37da2899SCharles.Forsyth  *  1. message size field is incorrect
43*37da2899SCharles.Forsyth  *  2. input buffer too short for its own data (counts too long, etc.)
44*37da2899SCharles.Forsyth  *  3. too many names or qids
45*37da2899SCharles.Forsyth  * gqid() and gstring() return nil if they would reach beyond buffer.
46*37da2899SCharles.Forsyth  * main switch statement checks range and also can fall through
47*37da2899SCharles.Forsyth  * to test at end of routine.
48*37da2899SCharles.Forsyth  */
49*37da2899SCharles.Forsyth uint
convM2S(uchar * ap,uint nap,Fcall * f)50*37da2899SCharles.Forsyth convM2S(uchar *ap, uint nap, Fcall *f)
51*37da2899SCharles.Forsyth {
52*37da2899SCharles.Forsyth 	uchar *p, *ep;
53*37da2899SCharles.Forsyth 	uint i, size;
54*37da2899SCharles.Forsyth 
55*37da2899SCharles.Forsyth 	p = ap;
56*37da2899SCharles.Forsyth 	ep = p + nap;
57*37da2899SCharles.Forsyth 
58*37da2899SCharles.Forsyth 	if(p+BIT32SZ+BIT8SZ+BIT16SZ > ep)
59*37da2899SCharles.Forsyth 		return 0;
60*37da2899SCharles.Forsyth 	size = GBIT32(p);
61*37da2899SCharles.Forsyth 	p += BIT32SZ;
62*37da2899SCharles.Forsyth 
63*37da2899SCharles.Forsyth 	if(size < BIT32SZ+BIT8SZ+BIT16SZ)
64*37da2899SCharles.Forsyth 		return 0;
65*37da2899SCharles.Forsyth 
66*37da2899SCharles.Forsyth 	f->type = GBIT8(p);
67*37da2899SCharles.Forsyth 	p += BIT8SZ;
68*37da2899SCharles.Forsyth 	f->tag = GBIT16(p);
69*37da2899SCharles.Forsyth 	p += BIT16SZ;
70*37da2899SCharles.Forsyth 
71*37da2899SCharles.Forsyth 	switch(f->type)
72*37da2899SCharles.Forsyth 	{
73*37da2899SCharles.Forsyth 	default:
74*37da2899SCharles.Forsyth 		return 0;
75*37da2899SCharles.Forsyth 
76*37da2899SCharles.Forsyth 	case Tversion:
77*37da2899SCharles.Forsyth 		if(p+BIT32SZ > ep)
78*37da2899SCharles.Forsyth 			return 0;
79*37da2899SCharles.Forsyth 		f->msize = GBIT32(p);
80*37da2899SCharles.Forsyth 		p += BIT32SZ;
81*37da2899SCharles.Forsyth 		p = gstring(p, ep, &f->version);
82*37da2899SCharles.Forsyth 		break;
83*37da2899SCharles.Forsyth 
84*37da2899SCharles.Forsyth 	case Tflush:
85*37da2899SCharles.Forsyth 		if(p+BIT16SZ > ep)
86*37da2899SCharles.Forsyth 			return 0;
87*37da2899SCharles.Forsyth 		f->oldtag = GBIT16(p);
88*37da2899SCharles.Forsyth 		p += BIT16SZ;
89*37da2899SCharles.Forsyth 		break;
90*37da2899SCharles.Forsyth 
91*37da2899SCharles.Forsyth 	case Tauth:
92*37da2899SCharles.Forsyth 		if(p+BIT32SZ > ep)
93*37da2899SCharles.Forsyth 			return 0;
94*37da2899SCharles.Forsyth 		f->afid = GBIT32(p);
95*37da2899SCharles.Forsyth 		p += BIT32SZ;
96*37da2899SCharles.Forsyth 		p = gstring(p, ep, &f->uname);
97*37da2899SCharles.Forsyth 		if(p == nil)
98*37da2899SCharles.Forsyth 			break;
99*37da2899SCharles.Forsyth 		p = gstring(p, ep, &f->aname);
100*37da2899SCharles.Forsyth 		if(p == nil)
101*37da2899SCharles.Forsyth 			break;
102*37da2899SCharles.Forsyth 		break;
103*37da2899SCharles.Forsyth 
104*37da2899SCharles.Forsyth 	case Tattach:
105*37da2899SCharles.Forsyth 		if(p+BIT32SZ > ep)
106*37da2899SCharles.Forsyth 			return 0;
107*37da2899SCharles.Forsyth 		f->fid = GBIT32(p);
108*37da2899SCharles.Forsyth 		p += BIT32SZ;
109*37da2899SCharles.Forsyth 		if(p+BIT32SZ > ep)
110*37da2899SCharles.Forsyth 			return 0;
111*37da2899SCharles.Forsyth 		f->afid = GBIT32(p);
112*37da2899SCharles.Forsyth 		p += BIT32SZ;
113*37da2899SCharles.Forsyth 		p = gstring(p, ep, &f->uname);
114*37da2899SCharles.Forsyth 		if(p == nil)
115*37da2899SCharles.Forsyth 			break;
116*37da2899SCharles.Forsyth 		p = gstring(p, ep, &f->aname);
117*37da2899SCharles.Forsyth 		if(p == nil)
118*37da2899SCharles.Forsyth 			break;
119*37da2899SCharles.Forsyth 		break;
120*37da2899SCharles.Forsyth 
121*37da2899SCharles.Forsyth 	case Twalk:
122*37da2899SCharles.Forsyth 		if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep)
123*37da2899SCharles.Forsyth 			return 0;
124*37da2899SCharles.Forsyth 		f->fid = GBIT32(p);
125*37da2899SCharles.Forsyth 		p += BIT32SZ;
126*37da2899SCharles.Forsyth 		f->newfid = GBIT32(p);
127*37da2899SCharles.Forsyth 		p += BIT32SZ;
128*37da2899SCharles.Forsyth 		f->nwname = GBIT16(p);
129*37da2899SCharles.Forsyth 		p += BIT16SZ;
130*37da2899SCharles.Forsyth 		if(f->nwname > MAXWELEM)
131*37da2899SCharles.Forsyth 			return 0;
132*37da2899SCharles.Forsyth 		for(i=0; i<f->nwname; i++){
133*37da2899SCharles.Forsyth 			p = gstring(p, ep, &f->wname[i]);
134*37da2899SCharles.Forsyth 			if(p == nil)
135*37da2899SCharles.Forsyth 				break;
136*37da2899SCharles.Forsyth 		}
137*37da2899SCharles.Forsyth 		break;
138*37da2899SCharles.Forsyth 
139*37da2899SCharles.Forsyth 	case Topen:
140*37da2899SCharles.Forsyth 		if(p+BIT32SZ+BIT8SZ > ep)
141*37da2899SCharles.Forsyth 			return 0;
142*37da2899SCharles.Forsyth 		f->fid = GBIT32(p);
143*37da2899SCharles.Forsyth 		p += BIT32SZ;
144*37da2899SCharles.Forsyth 		f->mode = GBIT8(p);
145*37da2899SCharles.Forsyth 		p += BIT8SZ;
146*37da2899SCharles.Forsyth 		break;
147*37da2899SCharles.Forsyth 
148*37da2899SCharles.Forsyth 	case Tcreate:
149*37da2899SCharles.Forsyth 		if(p+BIT32SZ > ep)
150*37da2899SCharles.Forsyth 			return 0;
151*37da2899SCharles.Forsyth 		f->fid = GBIT32(p);
152*37da2899SCharles.Forsyth 		p += BIT32SZ;
153*37da2899SCharles.Forsyth 		p = gstring(p, ep, &f->name);
154*37da2899SCharles.Forsyth 		if(p == nil)
155*37da2899SCharles.Forsyth 			break;
156*37da2899SCharles.Forsyth 		if(p+BIT32SZ+BIT8SZ > ep)
157*37da2899SCharles.Forsyth 			return 0;
158*37da2899SCharles.Forsyth 		f->perm = GBIT32(p);
159*37da2899SCharles.Forsyth 		p += BIT32SZ;
160*37da2899SCharles.Forsyth 		f->mode = GBIT8(p);
161*37da2899SCharles.Forsyth 		p += BIT8SZ;
162*37da2899SCharles.Forsyth 		break;
163*37da2899SCharles.Forsyth 
164*37da2899SCharles.Forsyth 	case Tread:
165*37da2899SCharles.Forsyth 		if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
166*37da2899SCharles.Forsyth 			return 0;
167*37da2899SCharles.Forsyth 		f->fid = GBIT32(p);
168*37da2899SCharles.Forsyth 		p += BIT32SZ;
169*37da2899SCharles.Forsyth 		f->offset = GBIT64(p);
170*37da2899SCharles.Forsyth 		p += BIT64SZ;
171*37da2899SCharles.Forsyth 		f->count = GBIT32(p);
172*37da2899SCharles.Forsyth 		p += BIT32SZ;
173*37da2899SCharles.Forsyth 		break;
174*37da2899SCharles.Forsyth 
175*37da2899SCharles.Forsyth 	case Twrite:
176*37da2899SCharles.Forsyth 		if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
177*37da2899SCharles.Forsyth 			return 0;
178*37da2899SCharles.Forsyth 		f->fid = GBIT32(p);
179*37da2899SCharles.Forsyth 		p += BIT32SZ;
180*37da2899SCharles.Forsyth 		f->offset = GBIT64(p);
181*37da2899SCharles.Forsyth 		p += BIT64SZ;
182*37da2899SCharles.Forsyth 		f->count = GBIT32(p);
183*37da2899SCharles.Forsyth 		p += BIT32SZ;
184*37da2899SCharles.Forsyth 		if(p+f->count > ep)
185*37da2899SCharles.Forsyth 			return 0;
186*37da2899SCharles.Forsyth 		f->data = (char*)p;
187*37da2899SCharles.Forsyth 		p += f->count;
188*37da2899SCharles.Forsyth 		break;
189*37da2899SCharles.Forsyth 
190*37da2899SCharles.Forsyth 	case Tclunk:
191*37da2899SCharles.Forsyth 	case Tremove:
192*37da2899SCharles.Forsyth 		if(p+BIT32SZ > ep)
193*37da2899SCharles.Forsyth 			return 0;
194*37da2899SCharles.Forsyth 		f->fid = GBIT32(p);
195*37da2899SCharles.Forsyth 		p += BIT32SZ;
196*37da2899SCharles.Forsyth 		break;
197*37da2899SCharles.Forsyth 
198*37da2899SCharles.Forsyth 	case Tstat:
199*37da2899SCharles.Forsyth 		if(p+BIT32SZ > ep)
200*37da2899SCharles.Forsyth 			return 0;
201*37da2899SCharles.Forsyth 		f->fid = GBIT32(p);
202*37da2899SCharles.Forsyth 		p += BIT32SZ;
203*37da2899SCharles.Forsyth 		break;
204*37da2899SCharles.Forsyth 
205*37da2899SCharles.Forsyth 	case Twstat:
206*37da2899SCharles.Forsyth 		if(p+BIT32SZ+BIT16SZ > ep)
207*37da2899SCharles.Forsyth 			return 0;
208*37da2899SCharles.Forsyth 		f->fid = GBIT32(p);
209*37da2899SCharles.Forsyth 		p += BIT32SZ;
210*37da2899SCharles.Forsyth 		f->nstat = GBIT16(p);
211*37da2899SCharles.Forsyth 		p += BIT16SZ;
212*37da2899SCharles.Forsyth 		if(p+f->nstat > ep)
213*37da2899SCharles.Forsyth 			return 0;
214*37da2899SCharles.Forsyth 		f->stat = p;
215*37da2899SCharles.Forsyth 		p += f->nstat;
216*37da2899SCharles.Forsyth 		break;
217*37da2899SCharles.Forsyth 
218*37da2899SCharles.Forsyth /*
219*37da2899SCharles.Forsyth  */
220*37da2899SCharles.Forsyth 	case Rversion:
221*37da2899SCharles.Forsyth 		if(p+BIT32SZ > ep)
222*37da2899SCharles.Forsyth 			return 0;
223*37da2899SCharles.Forsyth 		f->msize = GBIT32(p);
224*37da2899SCharles.Forsyth 		p += BIT32SZ;
225*37da2899SCharles.Forsyth 		p = gstring(p, ep, &f->version);
226*37da2899SCharles.Forsyth 		break;
227*37da2899SCharles.Forsyth 
228*37da2899SCharles.Forsyth 	case Rerror:
229*37da2899SCharles.Forsyth 		p = gstring(p, ep, &f->ename);
230*37da2899SCharles.Forsyth 		break;
231*37da2899SCharles.Forsyth 
232*37da2899SCharles.Forsyth 	case Rflush:
233*37da2899SCharles.Forsyth 		break;
234*37da2899SCharles.Forsyth 
235*37da2899SCharles.Forsyth 	case Rauth:
236*37da2899SCharles.Forsyth 		p = gqid(p, ep, &f->aqid);
237*37da2899SCharles.Forsyth 		if(p == nil)
238*37da2899SCharles.Forsyth 			break;
239*37da2899SCharles.Forsyth 		break;
240*37da2899SCharles.Forsyth 
241*37da2899SCharles.Forsyth 	case Rattach:
242*37da2899SCharles.Forsyth 		p = gqid(p, ep, &f->qid);
243*37da2899SCharles.Forsyth 		if(p == nil)
244*37da2899SCharles.Forsyth 			break;
245*37da2899SCharles.Forsyth 		break;
246*37da2899SCharles.Forsyth 
247*37da2899SCharles.Forsyth 	case Rwalk:
248*37da2899SCharles.Forsyth 		if(p+BIT16SZ > ep)
249*37da2899SCharles.Forsyth 			return 0;
250*37da2899SCharles.Forsyth 		f->nwqid = GBIT16(p);
251*37da2899SCharles.Forsyth 		p += BIT16SZ;
252*37da2899SCharles.Forsyth 		if(f->nwqid > MAXWELEM)
253*37da2899SCharles.Forsyth 			return 0;
254*37da2899SCharles.Forsyth 		for(i=0; i<f->nwqid; i++){
255*37da2899SCharles.Forsyth 			p = gqid(p, ep, &f->wqid[i]);
256*37da2899SCharles.Forsyth 			if(p == nil)
257*37da2899SCharles.Forsyth 				break;
258*37da2899SCharles.Forsyth 		}
259*37da2899SCharles.Forsyth 		break;
260*37da2899SCharles.Forsyth 
261*37da2899SCharles.Forsyth 	case Ropen:
262*37da2899SCharles.Forsyth 	case Rcreate:
263*37da2899SCharles.Forsyth 		p = gqid(p, ep, &f->qid);
264*37da2899SCharles.Forsyth 		if(p == nil)
265*37da2899SCharles.Forsyth 			break;
266*37da2899SCharles.Forsyth 		if(p+BIT32SZ > ep)
267*37da2899SCharles.Forsyth 			return 0;
268*37da2899SCharles.Forsyth 		f->iounit = GBIT32(p);
269*37da2899SCharles.Forsyth 		p += BIT32SZ;
270*37da2899SCharles.Forsyth 		break;
271*37da2899SCharles.Forsyth 
272*37da2899SCharles.Forsyth 	case Rread:
273*37da2899SCharles.Forsyth 		if(p+BIT32SZ > ep)
274*37da2899SCharles.Forsyth 			return 0;
275*37da2899SCharles.Forsyth 		f->count = GBIT32(p);
276*37da2899SCharles.Forsyth 		p += BIT32SZ;
277*37da2899SCharles.Forsyth 		if(p+f->count > ep)
278*37da2899SCharles.Forsyth 			return 0;
279*37da2899SCharles.Forsyth 		f->data = (char*)p;
280*37da2899SCharles.Forsyth 		p += f->count;
281*37da2899SCharles.Forsyth 		break;
282*37da2899SCharles.Forsyth 
283*37da2899SCharles.Forsyth 	case Rwrite:
284*37da2899SCharles.Forsyth 		if(p+BIT32SZ > ep)
285*37da2899SCharles.Forsyth 			return 0;
286*37da2899SCharles.Forsyth 		f->count = GBIT32(p);
287*37da2899SCharles.Forsyth 		p += BIT32SZ;
288*37da2899SCharles.Forsyth 		break;
289*37da2899SCharles.Forsyth 
290*37da2899SCharles.Forsyth 	case Rclunk:
291*37da2899SCharles.Forsyth 	case Rremove:
292*37da2899SCharles.Forsyth 		break;
293*37da2899SCharles.Forsyth 
294*37da2899SCharles.Forsyth 	case Rstat:
295*37da2899SCharles.Forsyth 		if(p+BIT16SZ > ep)
296*37da2899SCharles.Forsyth 			return 0;
297*37da2899SCharles.Forsyth 		f->nstat = GBIT16(p);
298*37da2899SCharles.Forsyth 		p += BIT16SZ;
299*37da2899SCharles.Forsyth 		if(p+f->nstat > ep)
300*37da2899SCharles.Forsyth 			return 0;
301*37da2899SCharles.Forsyth 		f->stat = p;
302*37da2899SCharles.Forsyth 		p += f->nstat;
303*37da2899SCharles.Forsyth 		break;
304*37da2899SCharles.Forsyth 
305*37da2899SCharles.Forsyth 	case Rwstat:
306*37da2899SCharles.Forsyth 		break;
307*37da2899SCharles.Forsyth 	}
308*37da2899SCharles.Forsyth 
309*37da2899SCharles.Forsyth 	if(p==nil || p>ep)
310*37da2899SCharles.Forsyth 		return 0;
311*37da2899SCharles.Forsyth 	if(ap+size == p)
312*37da2899SCharles.Forsyth 		return size;
313*37da2899SCharles.Forsyth 	return 0;
314*37da2899SCharles.Forsyth }
315