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