Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include	<plan9.h>
2
#include	<fcall.h>
3
 
4
static
5
uchar*
6
gstring(uchar *p, uchar *ep, char **s)
7
{
8
	uint n;
9
 
10
	if(p+BIT16SZ > ep)
11
		return nil;
12
	n = GBIT16(p);
13
	p += BIT16SZ - 1;
14
	if(p+n+1 > ep)
15
		return nil;
16
	/* move it down, on top of count, to make room for '\0' */
17
	memmove(p, p + 1, n);
18
	p[n] = '\0';
19
	*s = (char*)p;
20
	p += n+1;
21
	return p;
22
}
23
 
24
static
25
uchar*
26
gqid(uchar *p, uchar *ep, Qid *q)
27
{
28
	if(p+QIDSZ > ep)
29
		return nil;
30
	q->type = GBIT8(p);
31
	p += BIT8SZ;
32
	q->vers = GBIT32(p);
33
	p += BIT32SZ;
34
	q->path = GBIT64(p);
35
	p += BIT64SZ;
36
	return p;
37
}
38
 
39
/*
40
 * no syntactic checks.
41
 * three causes for error:
42
 *  1. message size field is incorrect
43
 *  2. input buffer too short for its own data (counts too long, etc.)
44
 *  3. too many names or qids
45
 * gqid() and gstring() return nil if they would reach beyond buffer.
46
 * main switch statement checks range and also can fall through
47
 * to test at end of routine.
48
 */
49
uint
50
convM2S(uchar *ap, uint nap, Fcall *f)
51
{
52
	uchar *p, *ep;
53
	uint i, size;
54
 
55
	p = ap;
56
	ep = p + nap;
57
 
58
	if(p+BIT32SZ+BIT8SZ+BIT16SZ > ep)
59
		return 0;
60
	size = GBIT32(p);
61
	p += BIT32SZ;
62
 
63
	if(size > nap)
64
		return 0;
65
	if(size < BIT32SZ+BIT8SZ+BIT16SZ)
66
		return 0;
67
 
68
	f->type = GBIT8(p);
69
	p += BIT8SZ;
70
	f->tag = GBIT16(p);
71
	p += BIT16SZ;
72
 
73
	switch(f->type)
74
	{
75
	default:
76
		return 0;
77
 
78
	case Tversion:
79
		if(p+BIT32SZ > ep)
80
			return 0;
81
		f->msize = GBIT32(p);
82
		p += BIT32SZ;
83
		p = gstring(p, ep, &f->version);
84
		break;
85
 
86
/*
87
	case Tsession:
88
		if(p+BIT16SZ > ep)
89
			return 0;
90
		f->nchal = GBIT16(p);
91
		p += BIT16SZ;
92
		if(p+f->nchal > ep)
93
			return 0;
94
		f->chal = p;
95
		p += f->nchal;
96
		break;
97
*/
98
 
99
	case Tflush:
100
		if(p+BIT16SZ > ep)
101
			return 0;
102
		f->oldtag = GBIT16(p);
103
		p += BIT16SZ;
104
		break;
105
 
106
	case Tauth:
107
		if(p+BIT32SZ > ep)
108
			return 0;
109
		f->afid = GBIT32(p);
110
		p += BIT32SZ;
111
		p = gstring(p, ep, &f->uname);
112
		if(p == nil)
113
			break;
114
		p = gstring(p, ep, &f->aname);
115
		if(p == nil)
116
			break;
117
		break;
118
 
119
/*
120
b
121
	case Tattach:
122
		if(p+BIT32SZ > ep)
123
			return 0;
124
		f->fid = GBIT32(p);
125
		p += BIT32SZ;
126
		p = gstring(p, ep, &f->uname);
127
		if(p == nil)
128
			break;
129
		p = gstring(p, ep, &f->aname);
130
		if(p == nil)
131
			break;
132
		if(p+BIT16SZ > ep)
133
			return 0;
134
		f->nauth = GBIT16(p);
135
		p += BIT16SZ;
136
		if(p+f->nauth > ep)
137
			return 0;
138
		f->auth = p;
139
		p += f->nauth;
140
		break;
141
*/
142
 
143
	case Tattach:
144
		if(p+BIT32SZ > ep)
145
			return 0;
146
		f->fid = GBIT32(p);
147
		p += BIT32SZ;
148
		if(p+BIT32SZ > ep)
149
			return 0;
150
		f->afid = GBIT32(p);
151
		p += BIT32SZ;
152
		p = gstring(p, ep, &f->uname);
153
		if(p == nil)
154
			break;
155
		p = gstring(p, ep, &f->aname);
156
		if(p == nil)
157
			break;
158
		break;
159
 
160
 
161
	case Twalk:
162
		if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep)
163
			return 0;
164
		f->fid = GBIT32(p);
165
		p += BIT32SZ;
166
		f->newfid = GBIT32(p);
167
		p += BIT32SZ;
168
		f->nwname = GBIT16(p);
169
		p += BIT16SZ;
170
		if(f->nwname > MAXWELEM)
171
			return 0;
172
		for(i=0; i<f->nwname; i++){
173
			p = gstring(p, ep, &f->wname[i]);
174
			if(p == nil)
175
				break;
176
		}
177
		break;
178
 
179
	case Topen:
180
		if(p+BIT32SZ+BIT8SZ > ep)
181
			return 0;
182
		f->fid = GBIT32(p);
183
		p += BIT32SZ;
184
		f->mode = GBIT8(p);
185
		p += BIT8SZ;
186
		break;
187
 
188
	case Tcreate:
189
		if(p+BIT32SZ > ep)
190
			return 0;
191
		f->fid = GBIT32(p);
192
		p += BIT32SZ;
193
		p = gstring(p, ep, &f->name);
194
		if(p == nil)
195
			break;
196
		if(p+BIT32SZ+BIT8SZ > ep)
197
			return 0;
198
		f->perm = GBIT32(p);
199
		p += BIT32SZ;
200
		f->mode = GBIT8(p);
201
		p += BIT8SZ;
202
		break;
203
 
204
	case Tread:
205
		if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
206
			return 0;
207
		f->fid = GBIT32(p);
208
		p += BIT32SZ;
209
		f->offset = GBIT64(p);
210
		p += BIT64SZ;
211
		f->count = GBIT32(p);
212
		p += BIT32SZ;
213
		break;
214
 
215
	case Twrite:
216
		if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
217
			return 0;
218
		f->fid = GBIT32(p);
219
		p += BIT32SZ;
220
		f->offset = GBIT64(p);
221
		p += BIT64SZ;
222
		f->count = GBIT32(p);
223
		p += BIT32SZ;
224
		if(p+f->count > ep)
225
			return 0;
226
		f->data = (char*)p;
227
		p += f->count;
228
		break;
229
 
230
	case Tclunk:
231
	case Tremove:
232
		if(p+BIT32SZ > ep)
233
			return 0;
234
		f->fid = GBIT32(p);
235
		p += BIT32SZ;
236
		break;
237
 
238
	case Tstat:
239
		if(p+BIT32SZ > ep)
240
			return 0;
241
		f->fid = GBIT32(p);
242
		p += BIT32SZ;
243
		break;
244
 
245
	case Twstat:
246
		if(p+BIT32SZ+BIT16SZ > ep)
247
			return 0;
248
		f->fid = GBIT32(p);
249
		p += BIT32SZ;
250
		f->nstat = GBIT16(p);
251
		p += BIT16SZ;
252
		if(p+f->nstat > ep)
253
			return 0;
254
		f->stat = p;
255
		p += f->nstat;
256
		break;
257
 
258
/*
259
 */
260
	case Rversion:
261
		if(p+BIT32SZ > ep)
262
			return 0;
263
		f->msize = GBIT32(p);
264
		p += BIT32SZ;
265
		p = gstring(p, ep, &f->version);
266
		break;
267
 
268
/*
269
	case Rsession:
270
		if(p+BIT16SZ > ep)
271
			return 0;
272
		f->nchal = GBIT16(p);
273
		p += BIT16SZ;
274
		if(p+f->nchal > ep)
275
			return 0;
276
		f->chal = p;
277
		p += f->nchal;
278
		p = gstring(p, ep, &f->authid);
279
		if(p == nil)
280
			break;
281
		p = gstring(p, ep, &f->authdom);
282
		break;
283
*/
284
 
285
	case Rerror:
286
		p = gstring(p, ep, &f->ename);
287
		break;
288
 
289
	case Rflush:
290
		break;
291
 
292
/*
293
	case Rattach:
294
		p = gqid(p, ep, &f->qid);
295
		if(p == nil)
296
			break;
297
		if(p+BIT16SZ > ep)
298
			return 0;
299
		f->nrauth = GBIT16(p);
300
		p += BIT16SZ;
301
		if(p+f->nrauth > ep)
302
			return 0;
303
		f->rauth = p;
304
		p += f->nrauth;
305
		break;
306
*/
307
 
308
	case Rattach:
309
		p = gqid(p, ep, &f->qid);
310
		if(p == nil)
311
			break;
312
		break;
313
 
314
 
315
	case Rwalk:
316
		if(p+BIT16SZ > ep)
317
			return 0;
318
		f->nwqid = GBIT16(p);
319
		p += BIT16SZ;
320
		if(f->nwqid > MAXWELEM)
321
			return 0;
322
		for(i=0; i<f->nwqid; i++){
323
			p = gqid(p, ep, &f->wqid[i]);
324
			if(p == nil)
325
				break;
326
		}
327
		break;
328
 
329
	case Ropen:
330
	case Rcreate:
331
		p = gqid(p, ep, &f->qid);
332
		if(p == nil)
333
			break;
334
		if(p+BIT32SZ > ep)
335
			return 0;
336
		f->iounit = GBIT32(p);
337
		p += BIT32SZ;
338
		break;
339
 
340
	case Rread:
341
		if(p+BIT32SZ > ep)
342
			return 0;
343
		f->count = GBIT32(p);
344
		p += BIT32SZ;
345
		if(p+f->count > ep)
346
			return 0;
347
		f->data = (char*)p;
348
		p += f->count;
349
		break;
350
 
351
	case Rwrite:
352
		if(p+BIT32SZ > ep)
353
			return 0;
354
		f->count = GBIT32(p);
355
		p += BIT32SZ;
356
		break;
357
 
358
	case Rclunk:
359
	case Rremove:
360
		break;
361
 
362
	case Rstat:
363
		if(p+BIT16SZ > ep)
364
			return 0;
365
		f->nstat = GBIT16(p);
366
		p += BIT16SZ;
367
		if(p+f->nstat > ep)
368
			return 0;
369
		f->stat = p;
370
		p += f->nstat;
371
		break;
372
 
373
	case Rwstat:
374
		break;
375
	}
376
 
377
	if(p==nil || p>ep)
378
		return 0;
379
	if(ap+size == p)
380
		return size;
381
	return 0;
382
}