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	<u.h>
2
#include	<libc.h>
3
#include	<fcall.h>
4
 
5
static
6
uchar*
7
gstring(uchar *p, uchar *ep, char **s)
8
{
9
	uint n;
10
 
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
}
24
 
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
}
39
 
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;
55
 
56
	p = ap;
57
	ep = p + nap;
58
 
59
	if(p+BIT32SZ+BIT8SZ+BIT16SZ > ep)
60
		return 0;
61
	size = GBIT32(p);
62
	p += BIT32SZ;
63
 
64
	if(size < BIT32SZ+BIT8SZ+BIT16SZ)
65
		return 0;
66
 
67
	f->type = GBIT8(p);
68
	p += BIT8SZ;
69
	f->tag = GBIT16(p);
70
	p += BIT16SZ;
71
 
72
	switch(f->type)
73
	{
74
	default:
75
		return 0;
76
 
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;
84
 
85
	case Tflush:
86
		if(p+BIT16SZ > ep)
87
			return 0;
88
		f->oldtag = GBIT16(p);
89
		p += BIT16SZ;
90
		break;
91
 
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;
104
 
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;
121
 
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;
137
		}
138
		break;
139
 
140
	case Topen:
141
		if(p+BIT32SZ+BIT8SZ > ep)
142
			return 0;
143
		f->fid = GBIT32(p);
144
		p += BIT32SZ;
145
		f->mode = GBIT8(p);
146
		p += BIT8SZ;
147
		break;
148
 
149
	case Tcreate:
150
		if(p+BIT32SZ > ep)
151
			return 0;
152
		f->fid = GBIT32(p);
153
		p += BIT32SZ;
154
		p = gstring(p, ep, &f->name);
155
		if(p == nil)
156
			break;
157
		if(p+BIT32SZ+BIT8SZ > ep)
158
			return 0;
159
		f->perm = GBIT32(p);
160
		p += BIT32SZ;
161
		f->mode = GBIT8(p);
162
		p += BIT8SZ;
163
		break;
164
 
165
	case Tread:
166
		if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
167
			return 0;
168
		f->fid = GBIT32(p);
169
		p += BIT32SZ;
170
		f->offset = GBIT64(p);
171
		p += BIT64SZ;
172
		f->count = GBIT32(p);
173
		p += BIT32SZ;
174
		break;
175
 
176
	case Twrite:
177
		if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
178
			return 0;
179
		f->fid = GBIT32(p);
180
		p += BIT32SZ;
181
		f->offset = GBIT64(p);
182
		p += BIT64SZ;
183
		f->count = GBIT32(p);
184
		p += BIT32SZ;
185
		if(p+f->count > ep)
186
			return 0;
187
		f->data = (char*)p;
188
		p += f->count;
189
		break;
190
 
191
	case Tclunk:
192
	case Tremove:
193
		if(p+BIT32SZ > ep)
194
			return 0;
195
		f->fid = GBIT32(p);
196
		p += BIT32SZ;
197
		break;
198
 
199
	case Tstat:
200
		if(p+BIT32SZ > ep)
201
			return 0;
202
		f->fid = GBIT32(p);
203
		p += BIT32SZ;
204
		break;
205
 
206
	case Twstat:
207
		if(p+BIT32SZ+BIT16SZ > ep)
208
			return 0;
209
		f->fid = GBIT32(p);
210
		p += BIT32SZ;
211
		f->nstat = GBIT16(p);
212
		p += BIT16SZ;
213
		if(p+f->nstat > ep)
214
			return 0;
215
		f->stat = p;
216
		p += f->nstat;
217
		break;
218
 
219
/*
220
 */
221
	case Rversion:
222
		if(p+BIT32SZ > ep)
223
			return 0;
224
		f->msize = GBIT32(p);
225
		p += BIT32SZ;
226
		p = gstring(p, ep, &f->version);
227
		break;
228
 
229
	case Rerror:
230
		p = gstring(p, ep, &f->ename);
231
		break;
232
 
233
	case Rflush:
234
		break;
235
 
236
	case Rauth:
237
		p = gqid(p, ep, &f->aqid);
238
		if(p == nil)
239
			break;
240
		break;
241
 
242
	case Rattach:
243
		p = gqid(p, ep, &f->qid);
244
		if(p == nil)
245
			break;
246
		break;
247
 
248
	case Rwalk:
249
		if(p+BIT16SZ > ep)
250
			return 0;
251
		f->nwqid = GBIT16(p);
252
		p += BIT16SZ;
253
		if(f->nwqid > MAXWELEM)
254
			return 0;
255
		for(i=0; i<f->nwqid; i++){
256
			p = gqid(p, ep, &f->wqid[i]);
257
			if(p == nil)
258
				break;
259
		}
260
		break;
261
 
262
	case Ropen:
263
	case Rcreate:
264
		p = gqid(p, ep, &f->qid);
265
		if(p == nil)
266
			break;
267
		if(p+BIT32SZ > ep)
268
			return 0;
269
		f->iounit = GBIT32(p);
270
		p += BIT32SZ;
271
		break;
272
 
273
	case Rread:
274
		if(p+BIT32SZ > ep)
275
			return 0;
276
		f->count = GBIT32(p);
277
		p += BIT32SZ;
278
		if(p+f->count > ep)
279
			return 0;
280
		f->data = (char*)p;
281
		p += f->count;
282
		break;
283
 
284
	case Rwrite:
285
		if(p+BIT32SZ > ep)
286
			return 0;
287
		f->count = GBIT32(p);
288
		p += BIT32SZ;
289
		break;
290
 
291
	case Rclunk:
292
	case Rremove:
293
		break;
294
 
295
	case Rstat:
296
		if(p+BIT16SZ > ep)
297
			return 0;
298
		f->nstat = GBIT16(p);
299
		p += BIT16SZ;
300
		if(p+f->nstat > ep)
301
			return 0;
302
		f->stat = p;
303
		p += f->nstat;
304
		break;
305
 
306
	case Rwstat:
307
		break;
308
	}
309
 
310
	if(p==nil || p>ep)
311
		return 0;
312
	if(ap+size == p)
313
		return size;
314
	return 0;
315
}