Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <fcall.h>
5 static
6 uchar*
7 gstring(uchar *p, uchar *ep, char **s)
8 {
9 uint n;
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 }
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 }
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 convM2Su(uchar *ap, uint nap, Fcall *f, int dotu)
52 {
53 uchar *p, *ep;
54 uint i, size;
56 p = ap;
57 ep = p + nap;
59 if(p+BIT32SZ+BIT8SZ+BIT16SZ > ep)
60 return 0;
61 size = GBIT32(p);
62 p += BIT32SZ;
64 if(size < BIT32SZ+BIT8SZ+BIT16SZ)
65 return 0;
67 f->type = GBIT8(p);
68 p += BIT8SZ;
69 f->tag = GBIT16(p);
70 p += BIT16SZ;
72 switch(f->type)
73 {
74 default:
75 return 0;
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;
85 case Tflush:
86 if(p+BIT16SZ > ep)
87 return 0;
88 f->oldtag = GBIT16(p);
89 p += BIT16SZ;
90 break;
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 f->uidnum = NOUID;
104 if(dotu){
105 if(p+BIT32SZ > ep)
106 return 0;
107 f->uidnum = GBIT32(p);
108 p += BIT32SZ;
110 break;
112 case Tattach:
113 if(p+BIT32SZ > ep)
114 return 0;
115 f->fid = GBIT32(p);
116 p += BIT32SZ;
117 if(p+BIT32SZ > ep)
118 return 0;
119 f->afid = GBIT32(p);
120 p += BIT32SZ;
121 p = gstring(p, ep, &f->uname);
122 if(p == nil)
123 break;
124 p = gstring(p, ep, &f->aname);
125 if(p == nil)
126 break;
127 f->uidnum = NOUID;
128 if(dotu){
129 if(p+BIT32SZ > ep)
130 return 0;
131 f->uidnum = GBIT32(p);
132 p += BIT32SZ;
134 break;
136 case Twalk:
137 if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep)
138 return 0;
139 f->fid = GBIT32(p);
140 p += BIT32SZ;
141 f->newfid = GBIT32(p);
142 p += BIT32SZ;
143 f->nwname = GBIT16(p);
144 p += BIT16SZ;
145 if(f->nwname > MAXWELEM)
146 return 0;
147 for(i=0; i<f->nwname; i++){
148 p = gstring(p, ep, &f->wname[i]);
149 if(p == nil)
150 break;
152 break;
154 case Topen:
155 case Topenfd:
156 if(p+BIT32SZ+BIT8SZ > ep)
157 return 0;
158 f->fid = GBIT32(p);
159 p += BIT32SZ;
160 f->mode = GBIT8(p);
161 p += BIT8SZ;
162 break;
164 case Tcreate:
165 if(p+BIT32SZ > ep)
166 return 0;
167 f->fid = GBIT32(p);
168 p += BIT32SZ;
169 p = gstring(p, ep, &f->name);
170 if(p == nil)
171 break;
172 if(p+BIT32SZ+BIT8SZ > ep)
173 return 0;
174 f->perm = GBIT32(p);
175 p += BIT32SZ;
176 f->mode = GBIT8(p);
177 p += BIT8SZ;
178 if(dotu)
179 p = gstring(p, ep, &f->extension);
180 break;
182 case Tread:
183 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
184 return 0;
185 f->fid = GBIT32(p);
186 p += BIT32SZ;
187 f->offset = GBIT64(p);
188 p += BIT64SZ;
189 f->count = GBIT32(p);
190 p += BIT32SZ;
191 break;
193 case Twrite:
194 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
195 return 0;
196 f->fid = GBIT32(p);
197 p += BIT32SZ;
198 f->offset = GBIT64(p);
199 p += BIT64SZ;
200 f->count = GBIT32(p);
201 p += BIT32SZ;
202 if(p+f->count > ep)
203 return 0;
204 f->data = (char*)p;
205 p += f->count;
206 break;
208 case Tclunk:
209 case Tremove:
210 if(p+BIT32SZ > ep)
211 return 0;
212 f->fid = GBIT32(p);
213 p += BIT32SZ;
214 break;
216 case Tstat:
217 if(p+BIT32SZ > ep)
218 return 0;
219 f->fid = GBIT32(p);
220 p += BIT32SZ;
221 break;
223 case Twstat:
224 if(p+BIT32SZ+BIT16SZ > ep)
225 return 0;
226 f->fid = GBIT32(p);
227 p += BIT32SZ;
228 f->nstat = GBIT16(p);
229 p += BIT16SZ;
230 if(p+f->nstat > ep)
231 return 0;
232 f->stat = p;
233 p += f->nstat;
234 break;
236 /*
237 */
238 case Rversion:
239 if(p+BIT32SZ > ep)
240 return 0;
241 f->msize = GBIT32(p);
242 p += BIT32SZ;
243 p = gstring(p, ep, &f->version);
244 break;
246 case Rerror:
247 p = gstring(p, ep, &f->ename);
248 f->errornum = 0;
249 if(dotu){
250 if(p+BIT32SZ > ep)
251 return 0;
252 f->errornum = GBIT32(p);
253 p += BIT32SZ;
255 break;
257 case Rflush:
258 break;
260 case Rauth:
261 p = gqid(p, ep, &f->aqid);
262 if(p == nil)
263 break;
264 break;
266 case Rattach:
267 p = gqid(p, ep, &f->qid);
268 if(p == nil)
269 break;
270 break;
272 case Rwalk:
273 if(p+BIT16SZ > ep)
274 return 0;
275 f->nwqid = GBIT16(p);
276 p += BIT16SZ;
277 if(f->nwqid > MAXWELEM)
278 return 0;
279 for(i=0; i<f->nwqid; i++){
280 p = gqid(p, ep, &f->wqid[i]);
281 if(p == nil)
282 break;
284 break;
286 case Ropen:
287 case Ropenfd:
288 case Rcreate:
289 p = gqid(p, ep, &f->qid);
290 if(p == nil)
291 break;
292 if(p+BIT32SZ > ep)
293 return 0;
294 f->iounit = GBIT32(p);
295 p += BIT32SZ;
296 if(f->type == Ropenfd){
297 if(p+BIT32SZ > ep)
298 return 0;
299 f->unixfd = GBIT32(p);
300 p += BIT32SZ;
302 break;
304 case Rread:
305 if(p+BIT32SZ > ep)
306 return 0;
307 f->count = GBIT32(p);
308 p += BIT32SZ;
309 if(p+f->count > ep)
310 return 0;
311 f->data = (char*)p;
312 p += f->count;
313 break;
315 case Rwrite:
316 if(p+BIT32SZ > ep)
317 return 0;
318 f->count = GBIT32(p);
319 p += BIT32SZ;
320 break;
322 case Rclunk:
323 case Rremove:
324 break;
326 case Rstat:
327 if(p+BIT16SZ > ep)
328 return 0;
329 f->nstat = GBIT16(p);
330 p += BIT16SZ;
331 if(p+f->nstat > ep)
332 return 0;
333 f->stat = p;
334 p += f->nstat;
335 break;
337 case Rwstat:
338 break;
341 if(p==nil || p>ep)
342 return 0;
343 if(ap+size == p)
344 return size;
345 return 0;
348 uint
349 convM2S(uchar *ap, uint nap, Fcall *f)
351 return convM2Su(ap, nap, f, 0);