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 convM2S(uchar *ap, uint nap, Fcall *f)
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 break;
166 case Tread:
167 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
168 return 0;
169 f->fid = GBIT32(p);
170 p += BIT32SZ;
171 f->offset = GBIT64(p);
172 p += BIT64SZ;
173 f->count = GBIT32(p);
174 p += BIT32SZ;
175 break;
177 case Twrite:
178 if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
179 return 0;
180 f->fid = GBIT32(p);
181 p += BIT32SZ;
182 f->offset = GBIT64(p);
183 p += BIT64SZ;
184 f->count = GBIT32(p);
185 p += BIT32SZ;
186 if(p+f->count > ep)
187 return 0;
188 f->data = (char*)p;
189 p += f->count;
190 break;
192 case Tclunk:
193 case Tremove:
194 if(p+BIT32SZ > ep)
195 return 0;
196 f->fid = GBIT32(p);
197 p += BIT32SZ;
198 break;
200 case Tstat:
201 if(p+BIT32SZ > ep)
202 return 0;
203 f->fid = GBIT32(p);
204 p += BIT32SZ;
205 break;
207 case Twstat:
208 if(p+BIT32SZ+BIT16SZ > ep)
209 return 0;
210 f->fid = GBIT32(p);
211 p += BIT32SZ;
212 f->nstat = GBIT16(p);
213 p += BIT16SZ;
214 if(p+f->nstat > ep)
215 return 0;
216 f->stat = p;
217 p += f->nstat;
218 break;
220 /*
221 */
222 case Rversion:
223 if(p+BIT32SZ > ep)
224 return 0;
225 f->msize = GBIT32(p);
226 p += BIT32SZ;
227 p = gstring(p, ep, &f->version);
228 break;
230 case Rerror:
231 p = gstring(p, ep, &f->ename);
232 break;
234 case Rflush:
235 break;
237 case Rauth:
238 p = gqid(p, ep, &f->aqid);
239 if(p == nil)
240 break;
241 break;
243 case Rattach:
244 p = gqid(p, ep, &f->qid);
245 if(p == nil)
246 break;
247 break;
249 case Rwalk:
250 if(p+BIT16SZ > ep)
251 return 0;
252 f->nwqid = GBIT16(p);
253 p += BIT16SZ;
254 if(f->nwqid > MAXWELEM)
255 return 0;
256 for(i=0; i<f->nwqid; i++){
257 p = gqid(p, ep, &f->wqid[i]);
258 if(p == nil)
259 break;
261 break;
263 case Ropen:
264 case Ropenfd:
265 case Rcreate:
266 p = gqid(p, ep, &f->qid);
267 if(p == nil)
268 break;
269 if(p+BIT32SZ > ep)
270 return 0;
271 f->iounit = GBIT32(p);
272 p += BIT32SZ;
273 if(f->type == Ropenfd){
274 if(p+BIT32SZ > ep)
275 return 0;
276 f->unixfd = GBIT32(p);
277 p += BIT32SZ;
279 break;
281 case Rread:
282 if(p+BIT32SZ > ep)
283 return 0;
284 f->count = GBIT32(p);
285 p += BIT32SZ;
286 if(p+f->count > ep)
287 return 0;
288 f->data = (char*)p;
289 p += f->count;
290 break;
292 case Rwrite:
293 if(p+BIT32SZ > ep)
294 return 0;
295 f->count = GBIT32(p);
296 p += BIT32SZ;
297 break;
299 case Rclunk:
300 case Rremove:
301 break;
303 case Rstat:
304 if(p+BIT16SZ > ep)
305 return 0;
306 f->nstat = GBIT16(p);
307 p += BIT16SZ;
308 if(p+f->nstat > ep)
309 return 0;
310 f->stat = p;
311 p += f->nstat;
312 break;
314 case Rwstat:
315 break;
318 if(p==nil || p>ep)
319 return 0;
320 if(ap+size == p)
321 return size;
322 return 0;