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 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 f->errornum = 0;
233 if(dotu){
234 if(p+BIT16SZ > ep)
235 return 0;
236 f->errornum = GBIT16(p);
237 p += BIT16SZ;
239 break;
241 case Rflush:
242 break;
244 case Rauth:
245 p = gqid(p, ep, &f->aqid);
246 if(p == nil)
247 break;
248 break;
250 case Rattach:
251 p = gqid(p, ep, &f->qid);
252 if(p == nil)
253 break;
254 break;
256 case Rwalk:
257 if(p+BIT16SZ > ep)
258 return 0;
259 f->nwqid = GBIT16(p);
260 p += BIT16SZ;
261 if(f->nwqid > MAXWELEM)
262 return 0;
263 for(i=0; i<f->nwqid; i++){
264 p = gqid(p, ep, &f->wqid[i]);
265 if(p == nil)
266 break;
268 break;
270 case Ropen:
271 case Ropenfd:
272 case Rcreate:
273 p = gqid(p, ep, &f->qid);
274 if(p == nil)
275 break;
276 if(p+BIT32SZ > ep)
277 return 0;
278 f->iounit = GBIT32(p);
279 p += BIT32SZ;
280 if(f->type == Ropenfd){
281 if(p+BIT32SZ > ep)
282 return 0;
283 f->unixfd = GBIT32(p);
284 p += BIT32SZ;
286 break;
288 case Rread:
289 if(p+BIT32SZ > ep)
290 return 0;
291 f->count = GBIT32(p);
292 p += BIT32SZ;
293 if(p+f->count > ep)
294 return 0;
295 f->data = (char*)p;
296 p += f->count;
297 break;
299 case Rwrite:
300 if(p+BIT32SZ > ep)
301 return 0;
302 f->count = GBIT32(p);
303 p += BIT32SZ;
304 break;
306 case Rclunk:
307 case Rremove:
308 break;
310 case Rstat:
311 if(p+BIT16SZ > ep)
312 return 0;
313 f->nstat = GBIT16(p);
314 p += BIT16SZ;
315 if(p+f->nstat > ep)
316 return 0;
317 f->stat = p;
318 p += f->nstat;
319 break;
321 case Rwstat:
322 break;
325 if(p==nil || p>ep)
326 return 0;
327 if(ap+size == p)
328 return size;
329 return 0;
332 uint
333 convM2S(uchar *ap, uint nap, Fcall *f)
335 return convM2Su(ap, nap, f, 0);