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 break;
105 case Tattach:
106 if(p+BIT32SZ > ep)
107 return 0;
108 f->fid = GBIT32(p);
109 p += BIT32SZ;
110 if(p+BIT32SZ > ep)
111 return 0;
112 f->afid = GBIT32(p);
113 p += BIT32SZ;
114 p = gstring(p, ep, &f->uname);
115 if(p == nil)
116 break;
117 p = gstring(p, ep, &f->aname);
118 if(p == nil)
119 break;
120 break;
122 case Twalk:
123 if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep)
124 return 0;
125 f->fid = GBIT32(p);
126 p += BIT32SZ;
127 f->newfid = GBIT32(p);
128 p += BIT32SZ;
129 f->nwname = GBIT16(p);
130 p += BIT16SZ;
131 if(f->nwname > MAXWELEM)
132 return 0;
133 for(i=0; i<f->nwname; i++){
134 p = gstring(p, ep, &f->wname[i]);
135 if(p == nil)
136 break;
138 break;
140 case Topen:
141 case Topenfd:
142 if(p+BIT32SZ+BIT8SZ > ep)
143 return 0;
144 f->fid = GBIT32(p);
145 p += BIT32SZ;
146 f->mode = GBIT8(p);
147 p += BIT8SZ;
148 break;
150 case Tcreate:
151 if(p+BIT32SZ > ep)
152 return 0;
153 f->fid = GBIT32(p);
154 p += BIT32SZ;
155 p = gstring(p, ep, &f->name);
156 if(p == nil)
157 break;
158 if(p+BIT32SZ+BIT8SZ > ep)
159 return 0;
160 f->perm = GBIT32(p);
161 p += BIT32SZ;
162 f->mode = GBIT8(p);
163 p += BIT8SZ;
164 if(dotu)
165 p = gstring(p, ep, &f->extension);
166 break;
168 case Tread:
169 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
170 return 0;
171 f->fid = GBIT32(p);
172 p += BIT32SZ;
173 f->offset = GBIT64(p);
174 p += BIT64SZ;
175 f->count = GBIT32(p);
176 p += BIT32SZ;
177 break;
179 case Twrite:
180 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
181 return 0;
182 f->fid = GBIT32(p);
183 p += BIT32SZ;
184 f->offset = GBIT64(p);
185 p += BIT64SZ;
186 f->count = GBIT32(p);
187 p += BIT32SZ;
188 if(p+f->count > ep)
189 return 0;
190 f->data = (char*)p;
191 p += f->count;
192 break;
194 case Tclunk:
195 case Tremove:
196 if(p+BIT32SZ > ep)
197 return 0;
198 f->fid = GBIT32(p);
199 p += BIT32SZ;
200 break;
202 case Tstat:
203 if(p+BIT32SZ > ep)
204 return 0;
205 f->fid = GBIT32(p);
206 p += BIT32SZ;
207 break;
209 case Twstat:
210 if(p+BIT32SZ+BIT16SZ > ep)
211 return 0;
212 f->fid = GBIT32(p);
213 p += BIT32SZ;
214 f->nstat = GBIT16(p);
215 p += BIT16SZ;
216 if(p+f->nstat > ep)
217 return 0;
218 f->stat = p;
219 p += f->nstat;
220 break;
222 /*
223 */
224 case Rversion:
225 if(p+BIT32SZ > ep)
226 return 0;
227 f->msize = GBIT32(p);
228 p += BIT32SZ;
229 p = gstring(p, ep, &f->version);
230 break;
232 case Rerror:
233 p = gstring(p, ep, &f->ename);
234 f->errornum = 0;
235 if(dotu){
236 if(p+BIT16SZ > ep)
237 return 0;
238 f->errornum = GBIT16(p);
239 p += BIT16SZ;
241 break;
243 case Rflush:
244 break;
246 case Rauth:
247 p = gqid(p, ep, &f->aqid);
248 if(p == nil)
249 break;
250 break;
252 case Rattach:
253 p = gqid(p, ep, &f->qid);
254 if(p == nil)
255 break;
256 break;
258 case Rwalk:
259 if(p+BIT16SZ > ep)
260 return 0;
261 f->nwqid = GBIT16(p);
262 p += BIT16SZ;
263 if(f->nwqid > MAXWELEM)
264 return 0;
265 for(i=0; i<f->nwqid; i++){
266 p = gqid(p, ep, &f->wqid[i]);
267 if(p == nil)
268 break;
270 break;
272 case Ropen:
273 case Ropenfd:
274 case Rcreate:
275 p = gqid(p, ep, &f->qid);
276 if(p == nil)
277 break;
278 if(p+BIT32SZ > ep)
279 return 0;
280 f->iounit = GBIT32(p);
281 p += BIT32SZ;
282 if(f->type == Ropenfd){
283 if(p+BIT32SZ > ep)
284 return 0;
285 f->unixfd = GBIT32(p);
286 p += BIT32SZ;
288 break;
290 case Rread:
291 if(p+BIT32SZ > ep)
292 return 0;
293 f->count = GBIT32(p);
294 p += BIT32SZ;
295 if(p+f->count > ep)
296 return 0;
297 f->data = (char*)p;
298 p += f->count;
299 break;
301 case Rwrite:
302 if(p+BIT32SZ > ep)
303 return 0;
304 f->count = GBIT32(p);
305 p += BIT32SZ;
306 break;
308 case Rclunk:
309 case Rremove:
310 break;
312 case Rstat:
313 if(p+BIT16SZ > ep)
314 return 0;
315 f->nstat = GBIT16(p);
316 p += BIT16SZ;
317 if(p+f->nstat > ep)
318 return 0;
319 f->stat = p;
320 p += f->nstat;
321 break;
323 case Rwstat:
324 break;
327 if(p==nil || p>ep)
328 return 0;
329 if(ap+size == p)
330 return size;
331 return 0;
334 uint
335 convM2S(uchar *ap, uint nap, Fcall *f)
337 return convM2Su(ap, nap, f, 0);