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 f->uidnum = NOUID;
104 break;
106 case Tattach:
107 if(p+BIT32SZ > ep)
108 return 0;
109 f->fid = GBIT32(p);
110 p += BIT32SZ;
111 if(p+BIT32SZ > ep)
112 return 0;
113 f->afid = GBIT32(p);
114 p += BIT32SZ;
115 p = gstring(p, ep, &f->uname);
116 if(p == nil)
117 break;
118 p = gstring(p, ep, &f->aname);
119 if(p == nil)
120 break;
121 f->uidnum = NOUID;
122 break;
124 case Twalk:
125 if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep)
126 return 0;
127 f->fid = GBIT32(p);
128 p += BIT32SZ;
129 f->newfid = GBIT32(p);
130 p += BIT32SZ;
131 f->nwname = GBIT16(p);
132 p += BIT16SZ;
133 if(f->nwname > MAXWELEM)
134 return 0;
135 for(i=0; i<f->nwname; i++){
136 p = gstring(p, ep, &f->wname[i]);
137 if(p == nil)
138 break;
140 break;
142 case Topen:
143 case Topenfd:
144 if(p+BIT32SZ+BIT8SZ > ep)
145 return 0;
146 f->fid = GBIT32(p);
147 p += BIT32SZ;
148 f->mode = GBIT8(p);
149 p += BIT8SZ;
150 break;
152 case Tcreate:
153 if(p+BIT32SZ > ep)
154 return 0;
155 f->fid = GBIT32(p);
156 p += BIT32SZ;
157 p = gstring(p, ep, &f->name);
158 if(p == nil)
159 break;
160 if(p+BIT32SZ+BIT8SZ > ep)
161 return 0;
162 f->perm = GBIT32(p);
163 p += BIT32SZ;
164 f->mode = GBIT8(p);
165 p += BIT8SZ;
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 break;
237 case Rflush:
238 break;
240 case Rauth:
241 p = gqid(p, ep, &f->aqid);
242 if(p == nil)
243 break;
244 break;
246 case Rattach:
247 p = gqid(p, ep, &f->qid);
248 if(p == nil)
249 break;
250 break;
252 case Rwalk:
253 if(p+BIT16SZ > ep)
254 return 0;
255 f->nwqid = GBIT16(p);
256 p += BIT16SZ;
257 if(f->nwqid > MAXWELEM)
258 return 0;
259 for(i=0; i<f->nwqid; i++){
260 p = gqid(p, ep, &f->wqid[i]);
261 if(p == nil)
262 break;
264 break;
266 case Ropen:
267 case Ropenfd:
268 case Rcreate:
269 p = gqid(p, ep, &f->qid);
270 if(p == nil)
271 break;
272 if(p+BIT32SZ > ep)
273 return 0;
274 f->iounit = GBIT32(p);
275 p += BIT32SZ;
276 if(f->type == Ropenfd){
277 if(p+BIT32SZ > ep)
278 return 0;
279 f->unixfd = GBIT32(p);
280 p += BIT32SZ;
282 break;
284 case Rread:
285 if(p+BIT32SZ > ep)
286 return 0;
287 f->count = GBIT32(p);
288 p += BIT32SZ;
289 if(p+f->count > ep)
290 return 0;
291 f->data = (char*)p;
292 p += f->count;
293 break;
295 case Rwrite:
296 if(p+BIT32SZ > ep)
297 return 0;
298 f->count = GBIT32(p);
299 p += BIT32SZ;
300 break;
302 case Rclunk:
303 case Rremove:
304 break;
306 case Rstat:
307 if(p+BIT16SZ > ep)
308 return 0;
309 f->nstat = GBIT16(p);
310 p += BIT16SZ;
311 if(p+f->nstat > ep)
312 return 0;
313 f->stat = p;
314 p += f->nstat;
315 break;
317 case Rwstat:
318 break;
321 if(p==nil || p>ep)
322 return 0;
323 if(ap+size == p)
324 return size;
325 return 0;