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